0

如果我有一个构造函数,它是:

data Garage = Gar String

如果我想测试一个类型是否等于我的车库类型,我会这样做:

(==(Gar _)) (Gar "g")

但是,编译器抱怨下划线。如果我用它替换"g"它返回True. 有没有办法可以与通配符进行比较?

4

4 回答 4

4

为什么你的代码不起作用?

看起来您想要进行模式匹配,但实际上您正在==使用参数Gar _Gar "g". 因此 Haskell 感到困惑并说出类似“表达式上下文中的模式语法:_”之类的话。

如何修复?

你可以:

  1. 添加deriving Eq到数据声明的末尾,或

  2. 自己实现Eq

    instance Eq Garage where
        (Gar l) == (Gar r) = l == r
    

是否可以对构造函数通配符进行模式匹配?(为了完整性)

是的,这是一个废话功能:

f :: Garage -> Int
f (Gar "abc") = 12
f (Gar _) = 4

不过,这对于具有多个构造函数的数据类型可能会更有用。

于 2012-09-20T20:44:51.290 回答
2

你想做模式匹配,像这样:

case x of
   Gar _ -> True
   _     -> False

如果你想要它作为函数,然后添加类似的东西

isGarage (Gar _) = True
isGarage _       = False
于 2012-09-20T20:33:01.500 回答
0

也许您的问题假设您需要在 Haskell 中进行运行时类型检查,但这不是必需的。GarageHaskell 将确保您的所有类型在编译时都是正确的,因此不需要检查数据是否属于您的数据类型的函数,并且该函数不起作用:

justPrintGarages (Gar x) = print x -- if the argument is a Garage, print its content
justPrintGarages _ = return ()     -- if it's anything else, do nothing.

如果我们问 ghci 有什么类型justPrintGarages,它会告诉我们

printGarages :: Garage -> IO ()

哎呀!我们应该告诉我们是否有车库的功能只适用于车库???是的。那是因为 Haskell 故意阻止你混合类型,因为它是运行时错误的泥潭。静态类型是你的朋友。静态类型带走了一个痛苦的世界。因为静态类型,你不能定义

printGaragesAndShebangs (Gar x) = print x
printGaragesAndShebangs ('#':'!':xs) = putStr xs
printGaragesAndShebangs _ = return ()

你会得到一个类型错误。你不能只是对待Strings 和Garages 一样。

如果你想混合车库和字符串,这里是这样做的方法,保持类型安全:

data GarageStringInt = GsiG Garage | GsiS String | GsiI Int

GarageStringInt这是一个可怕的名字,GisG等等,但如果你在你的代码中需要这个,它会代表一些明智的东西(我希望),你可以给它一个描述它代表什么的名字。)

现在我们可以写

printGaragesAndShebangs :: GarageStringInt -> IO ()
printGaragesAndShebangs (GsiG (Gar x)) = print x
printGaragesAndShebangs (GsiS ('#':'!':xs)) = putStr xs
printGaragesAndShebangs _ = return ()
于 2012-09-21T08:23:34.860 回答
0

像这样的功能

isGarage (Gar _) = True
isGarage _       = False

非常没用,因为它有 type Garage -> Bool。所以它总是会返回类型TrueGarage并且任何其他类型都会发生类型检查失败。

我认为模式匹配足以满足您的要求。但只是为了表明如果你知道你将要作用的类型,你可以使用类型类来拥有这种功能。因此,如果您知道您将从给定的一组类型中获取值,那么您可以执行类似的操作

{-# LANGUAGE FlexibleInstances #-}
data Garage = Gar String

class IsGarage a where
    isGarage :: a -> Bool
    isGarage _ = False

instance IsGarage Garage where
    isGarage _ = True

instance IsGarage [Char]

在 ghci

*Main> :t isGarage 
isGarage :: IsGarage a => a -> Bool
*Main> isGarage "3"
False
*Main> isGarage (Gar "2")
True
于 2012-09-21T08:48:19.357 回答