我有三个功能
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和类型系统的更多信息的资源也将受到赞赏。
答案 0 :(得分:5)
GHC使用类型推断来猜测你的函数可以是什么类型。
在boombangs
中,由于列表推导中的x <- xs
,它可以告诉您传入列表,并且它可以告诉列表元素必须具有类型{{1因为您将Integral a => a
应用于每个元素。由于列表理解中的文字odd
和String
,它知道您正在返回"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]
您可以像这样手动推断其类型:
您可以按列表理解来定义mbangs
,因此xs
必须是列表,
您对odd
元素应用xs
,因此xs
的类型必须为(Integral a) => [a]
,因为odd
的类型为(Integral a) => a -> Bool
。
此外,对于xs
的每个元素,您可以通过输出函数String
生成if x < 10 then "BOOM" else "BANG"
,
因此mbangs
的类型必须为Integral a => [a] -> [[Char]]
,而ghci
只是告诉您。
为什么boombangs和removeNonUppercase的类型不同,即使它们在相同的输入上工作。
因为您在列表推导定义中使用了不同的输出函数。
答案 2 :(得分:0)
对于boombangs
,您可以通过应用于x的运算符看到它不能是字符串。对于removeNonUpperCase
,可以看到元素必须位于['A'..'Z']
中,因此不能成为整数。这也解释了为什么他们不能在相同的输入上工作。