了解Haskell的类型系统

Ana*_*nth 0 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']]
Run Code Online (Sandbox Code Playgroud)

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

*Main> :t boombangs
boombangs :: Integral a => [a] -> [[Char]]
*Main> :t length'
length' :: Num a => [t] -> a
*Main> :t removeNonUppercase 
removeNonUppercase :: [Char] -> [Char]
Run Code Online (Sandbox Code Playgroud)

当我传递一组int来删除NonUppercase或一个字符串到boombangs时,Haskell应该给我一个错误.它也是,但是当我没有在任何地方指定类型时,它怎么知道它是错的.

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

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

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

bhe*_*ilr 5

GHC使用类型推断来尝试猜测您的函数可以是什么类型.

boombangs,它可以告诉你是否因为x <- xs列表理解而传入列表,并且它可以告诉列表元素必须具有类型,Integral a => a因为您正在应用于odd每个元素.它知道你正在返回一个Strings 列表,因为文字"BOOM""BANG"列表内容理解.

length',您的类型仅受限制sum,这需要Num a => [a].您的输入类型是任何类型的列表,因为您实际上没有对元素本身执行任何操作,但您确实指出该参数是一个列表_ <- xs.

removeNonUpperCase,它看到你传入一个列表的原因与前两个函数相同,并且因为你正在检查每个元素是否在列表中['A'..'Z'],所以每个元素都必须是a Char,所以你要列出一个列表的CharS和返回的清单CharS,因为没有其他变换在元件上执行.由于String它只是一个别名[Char],它完全知道类型.

  • 内置的`length`函数提供了它的类型签名,使用`Int`而不是`Integer`,`Float`或`Double`更有效.内置定义也与您的定义不同,但它仍然基本上基于`+`.'+`的类型是`Num a => a - > a - > a`,因为我们希望该运算符能够处理所有数字,而不仅仅是`Int`.类型签名之间唯一真正的区别是内置使用了"Num"的具体实例,而你的更为通用.在实践中,使其更通用是没有用的. (2认同)