了解Haskell的类型系统

时间:2014-04-14 13:23:07

标签: haskell

我有三个功能

boombangs xs = [if x < 10 then "BOOM" else "BANG" | x <- xs odd x]

length' xs = sum [1 | _ <- xs]

removeNonUppercase st = [x | x <- st, x `elem` ['A'..'Z']]

这是我得到的每个函数的类型(类型签名?)

*Main> :t boombangs
boombangs :: Integral a => [a] -> [[Char]]
*Main> :t length'
length' :: Num a => [t] -> a
*Main> :t removeNonUppercase 
removeNonUppercase :: [Char] -> [Char]
当我将一个int数组传递给removeNonUppercase或将一个字符串传递给boombangs时,Haskell会给我一个错误。它也是,但是当我没有在任何地方指定类型时,它怎么知道它错了。

另外,为什么boombangs和removeNonUppercase的类型不同,即使它们在相同的输入上工作。

如果这个问题看起来含糊不清或完全无知,我道歉。我刚刚开始学习你是一个Haskell而我正在慢慢地围绕这个范例,主要是用C和python进行编程。

任何有关haskell和类型系统的更多信息的资源也将受到赞赏。

3 个答案:

答案 0 :(得分:5)

GHC使用类型推断来猜测你的函数可以是什么类型。

boombangs中,由于列表推导中的x <- xs,它可以告诉您传入列表,并且它可以告诉列表元素必须具有类型{{1因为您将Integral a => a应用于每个元素。由于列表理解中的文字oddString,它知道您正在返回"BOOM"的列表。

"BANG"中,您的类型仅受length'约束,这需要sum。您的输入类型是任何类型的列表,因为您实际上没有对元素本身执行任何操作,但您确实指出该参数是Num a => [a]的列表。

_ <- xs中,它会看到您传入列表的原因与前两个函数相同,并且因为您要检查每个元素是否在列表中{{1因此,每个元素都必须是removeNonUpperCase,因此您需要获取['A'..'Z']的列表并返回Char的列表,因为没有执行其他转换要素。由于Char只是Char的别名,因此它完全了解类型。

答案 1 :(得分:2)

  

当我没有在任何地方指定类型时,它怎么知道它是错的。

Haskell编译器,在您的情况下,GHC可以进行类型推断,这意味着它可以通过上下文信息(几乎总是)找出表达式的类型。例如,对于

mbangs xs = [if x < 10 then "BOOM" else "BANG" | x <- xs, odd x]

您可以像这样手动推断其类型:

  1. 您可以按列表理解来定义mbangs,因此xs必须是列表,

  2. 您对odd元素应用xs,因此xs的类型必须为(Integral a) => [a],因为odd的类型为(Integral a) => a -> Bool

  3. 此外,对于xs的每个元素,您可以通过输出函数String生成if x < 10 then "BOOM" else "BANG"

  4. 因此mbangs的类型必须为Integral a => [a] -> [[Char]],而ghci只是告诉您。

  5.   

    为什么boombangs和removeNonUppercase的类型不同,即使它们在相同的输入上工作。

    因为您在列表推导定义中使用了不同的输出函数。

答案 2 :(得分:0)

对于boombangs,您可以通过应用于x的运算符看到它不能是字符串。对于removeNonUpperCase,可以看到元素必须位于['A'..'Z']中,因此不能成为整数。这也解释了为什么他们不能在相同的输入上工作。