在这里澄清一点,让我重写你的数据类型以避免在 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),您可以免费获得类似的功能!
尝试查看 myInt 的类型,例如:
*Main> :t myInt
myInt :: SomeType -> Int
看看这个函数做了什么:
*Main> myInt (I 5)
5
*Main> myInt (B False)
*** Exception: No match in record selector Main.myInt
这正是上面定义的returnInt 的行为。奇怪的错误信息只是告诉你该函数不知道如何处理与 (I x) 不匹配的 SomeType 类型的成员。
如果您使用更常见的语法定义类型:
data SomeType2 = X String | I Int | B Bool
那么你就失去了那些不错的记录功能。
错误消息终止程序的执行。这有时很烦人。如果您的功能需要更安全的行为,GBacon 的答案就是这样做的方法。了解Maybe a 类型并使用它来处理这种需要返回一些值或什么都不返回的计算(试试这个:http://en.wikibooks.org/wiki/Haskell/Hierarchical_libraries/Maybe)。