我获得了类似以下的数据类型
data Value = IntVal Integer |
BoolVal Bool
deriving Show
我正在尝试编写一个函数getVal
,它接受一个Value并返回其中的实际值。我试图用模式匹配来实现
getVal (IntVal val) = val
getVal (Bool bool) = bool
但是Haskell抱怨返回的类型 无法匹配预期类型'整数'实行类型' Bool'
所以我给它一个签名返回一个类型变量
getVar :: Value -> a
但它不会工作
答案 0 :(得分:9)
是的,这可以通过类型类或GADT的帮助来处理,或者您甚至可以使用cast
利用Data.Typeable
。但是当你非常了解Haskell,以及当你知道自己在做什么时,所有这些都是有用的。
在您的情况下,您应该真正尝试了解Haskell的工作原理。 Haskell是关于施加明智的不变量,这使得无法编写“坏”程序(好吧,这就是我说的)。这是通过类型系统完成的,如果没有附加那些不变量,你就无法做任何事情。
所以现在,你对a
类型的东西做不了多少,因为你对它知之甚少。如果您想从函数返回值Int
或Bool
(实际上可以看到存在量化),您将能够对{{1}上执行的值执行操作Int
上的和。例如,您可以获得该值的文本表示。
你想要的不仅仅是机会。在这种情况下,您可能不应该同时返回Bool
和 Int
,而无法理解您的确切结果。
因此,您可以执行以下操作:
Bool
或者您可以发送:
getVar :: Value -> Either Int Bool
这是Haskell的自然流程。在程序的每个分支中,您现在都知道您正在处理什么。
希望它有所帮助。
答案 1 :(得分:4)
一种方法是使用类型类,使函数在返回值中具有多态性:
\> :t getVal
getVal :: GetValue a => Value -> Maybe a
通过简单的代码,如下所示:
data Value = IntVal Integer
| BoolVal Bool
deriving Show
class GetValue a where
getVal :: Value -> Maybe a
instance GetValue Integer where
getVal (IntVal i) = Just i
getVal _ = Nothing
instance GetValue Bool where
getVal (BoolVal b) = Just b
getVal _ = Nothing
让类型推断决定正确的函数:
\> import Data.Maybe (fromJust)
\> (3 +) .fromJust . getVal $ IntVal 5 -- getVal :: Value -> Maybe Integer
8
\> not . fromJust . getVal $ BoolVal False -- getVal :: Value -> Maybe Bool
True
答案 2 :(得分:3)
这是GADT
的工作:
{-# LANGUAGE GADTs #-}
data Value a where
IntVal :: Integer -> Value Integer
BoolVal :: Bool -> Value Bool
getVal :: Value a -> a
getVal (IntVal i) = i
getVal (BoolVal b) = b
答案 3 :(得分:2)
user3237465和behzad.nouri已为您的具体问题提供了答案。但是,我想知道你是否在想与OO和动态类型语言进行类比。如果你正在服用"价值"作为函数的参数,那么你应该使用模式匹配来使用它所拥有的值来做正确的事情。所以假设你正在写一个函数" showValue"将值作为字符串返回。我想你正在尝试做类似的事情:
showValue :: Value -> String
showValue v = let v1 = getValue v in <something>
但是这在Haskell中不起作用,因为类型系统坚持知道什么类型&#34; v1&#34;是。相反,你这样写:
showValue (IntVal i) = "The Value is an integer " ++ show i
showValue (BoolVal b) = "The Value is a boolean " ++ show b