如果我有一个构造函数,它是:
data Garage = Gar String
如果我想测试一个类型是否等于我的车库类型,我会这样做:
(==(Gar _)) (Gar "g")
但是,编译器抱怨下划线。如果我用它替换"g"
它返回True
. 有没有办法可以与通配符进行比较?
如果我有一个构造函数,它是:
data Garage = Gar String
如果我想测试一个类型是否等于我的车库类型,我会这样做:
(==(Gar _)) (Gar "g")
但是,编译器抱怨下划线。如果我用它替换"g"
它返回True
. 有没有办法可以与通配符进行比较?
为什么你的代码不起作用?
看起来您想要进行模式匹配,但实际上您正在==
使用参数Gar _
和Gar "g"
. 因此 Haskell 感到困惑并说出类似“表达式上下文中的模式语法:_”之类的话。
如何修复?
你可以:
添加deriving Eq
到数据声明的末尾,或
自己实现Eq
:
instance Eq Garage where
(Gar l) == (Gar r) = l == r
是否可以对构造函数通配符进行模式匹配?(为了完整性)
是的,这是一个废话功能:
f :: Garage -> Int
f (Gar "abc") = 12
f (Gar _) = 4
不过,这对于具有多个构造函数的数据类型可能会更有用。
你想做模式匹配,像这样:
case x of
Gar _ -> True
_ -> False
如果你想要它作为函数,然后添加类似的东西
isGarage (Gar _) = True
isGarage _ = False
也许您的问题假设您需要在 Haskell 中进行运行时类型检查,但这不是必需的。Garage
Haskell 将确保您的所有类型在编译时都是正确的,因此不需要检查数据是否属于您的数据类型的函数,并且该函数不起作用:
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 ()
你会得到一个类型错误。你不能只是对待String
s 和Garage
s 一样。
如果你想混合车库和字符串,这里是这样做的方法,保持类型安全:
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 ()
像这样的功能
isGarage (Gar _) = True
isGarage _ = False
非常没用,因为它有 type Garage -> Bool
。所以它总是会返回类型True
,Garage
并且任何其他类型都会发生类型检查失败。
我认为模式匹配足以满足您的要求。但只是为了表明如果你知道你将要作用的类型,你可以使用类型类来拥有这种功能。因此,如果您知道您将从给定的一组类型中获取值,那么您可以执行类似的操作
{-# 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