如何编写函数根据用户定义的数据类型返回Integer或Bool?

时间:2015-11-29 14:29:58

标签: haskell functional-programming polymorphism

我获得了类似以下的数据类型

data Value = IntVal Integer |
             BoolVal Bool
             deriving Show

我正在尝试编写一个函数getVal,它接受​​一个Value并返回其中的实际值。我试图用模式匹配来实现

getVal (IntVal val) = val
getVal (Bool bool) = bool

但是Haskell抱怨返回的类型     无法匹配预期类型'整数'实行类型' Bool'

所以我给它一个签名返回一个类型变量

getVar :: Value -> a

但它不会工作

4 个答案:

答案 0 :(得分:9)

是的,这可以通过类型类或GADT的帮助来处理,或者您甚至可以使用cast利用Data.Typeable。但是当你非常了解Haskell,以及当你知道自己在做什么时,所有这些都是有用的。

在您的情况下,您应该真正尝试了解Haskell的工作原理。 Haskell是关于施加明智的不变量,这使得无法编写“坏”程序(好吧,这就是我说的)。这是通过类型系统完成的,如果没有附加那些不变量,你就无法做任何事情。

所以现在,你对a类型的东西做不了多少,因为你对它知之甚少。如果您想从函数返回值IntBool(实际上可以看到存在量化),您将能够对{{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