在Haskell的代数数据类型的替代品之间的选择
-
13-09-2019 - |
题
当型X
定义为:
data X =
X { sVal :: String } |
I { iVal :: Int } |
B { bVal :: Bool }
和我想要一个Int
值内的X
,如果有一个,否则为零。
returnInt :: X -> Int
如何确定哪种类型X
的参数returnInt
是?
解决方案
就在这里澄清一点,让我重写你的数据类型,以避免X的含义含糊:
data SomeType = X { myString :: String} | I {myInt :: Int} | B {myBool :: Bool}
在此定义不存在X,I和B类型。 X,I和B是创建类型强> Sometype
的值的构造。注意:当你问ghci的是什么这些类型构造建造的任何值的类型会发生什么:
*Main> :t (I 5)
(I 5) :: Sometype
*Main> :t (B False)
(B False) :: Sometype
它们属于相同类型!!
正如可以使用X,I和B来构造类型,可以使用模式匹配来解构的类型,像在其他的答案进行以上:
returnInt :: SomeType -> Int
returnInt (I x) = x -- if the pattern matches (I x) then return x
returnInt _ = error "I need an integer value, you moron" -- throw an error otherwise
发生在顺序只要记住,模式匹配:如果该值在一些行中的图案相匹配,在低于该线的图案将不会被执行
请注意,当你定义你的类型,像你这样,使用所谓记录语法(看看这里:的 http://en.wikibooks.org/wiki/Haskell/More_on_datatypes ),你有功能,如,对于免费!!
尝试寻找上明特的类型,例如:
*Main> :t myInt
myInt :: SomeType -> Int
和看一下这个功能做的:
*Main> myInt (I 5)
5
*Main> myInt (B False)
*** Exception: No match in record selector Main.myInt
这正是returnInt
的行为定义如上。奇怪的错误信息只是告诉你该函数不知道如何处理的类型SOMETYPE不匹配(I x)
的成员。
如果您使用更常见的语法定义类型:
data SomeType2 = X String | I Int | B Bool
然后你松那些好的记录功能。
在错误消息终止程序的执行。这是烦人有时。如果您需要更安全的行为为您的功能GBacon的回答仅仅是做到这一点。了解Maybe a
类型,并用它来应付这种计算需要返回一些值,或者什么也不返回(试试这个:的 http://en.wikibooks.org/wiki/Haskell/Hierarchical_libraries/Maybe )。
其他提示
使用模式匹配。
returnInt :: X -> Int
returnInt (I x) = x
returnInt _ = 0
使用更灵活的定义为所有可能的X
值:
returnInt :: X -> Maybe Int
returnInt (I i) = Just i
returnInt _ = Nothing
然后可以使用 maybe
一>对特定违约想要-0可能是一个有效的值(这是被称为 semipredicate问题):
*Main> maybe 0 id (returnInt $ X "")
0
*Main> maybe 0 id (returnInt $ I 123)
123
*Main> maybe (-1) id (returnInt $ X "yo")
-1
在另一方面,部分功能风险运行时异常:
*Main> let returnInt (I i) = i
*Main> :t returnInt
returnInt :: X -> Int
*Main> returnInt (B True)
*** Exception: <interactive>:1:4-22: Non-exhaustive patterns in function returnInt
如果你感觉真的小青蛙,你可以使用MonadPlus
returnInt :: (MonadPlus m) => X -> m Int
returnInt (I i) = return i
returnInt _ = mzero
,以获得更大的灵活性:
*Main> maybe 0 id (returnInt $ X "")
0
*Main> maybe 0 id (returnInt $ I 123)
123
*Main> returnInt (I 123) `mplus` returnInt (I 456) :: [Int]
[123,456]
给定一个功能是这样的:
returnInt :: X -> Int
returnInt x = {- some integer -}
... x
的类型总是X
。你关心什么是x
是否使用X
,I
或B
类型构造。
使用模式匹配来分辨:
returnInt :: X -> Int
returnInt (X _) = error "needed an Int, got a String"
returnInt (I { iVal = n }) = n
returnInt (B _) = error "needed an Int, got a Bool"