gpt4 book ai didi

haskell - 当编译器可以推断类型时,为函数使用类型签名的充分理由是什么

转载 作者:行者123 更新时间:2023-12-02 05:19:23 26 4
gpt4 key购买 nike

我正在尝试使用“良好的 Haskell 风格”进行编码,因此我正在尝试遵循我发现的典型编码标准。另外,使用 -Wall 和 -Werror 进行编译,就像我在使用 C 语言时所习惯的那样。我经常收到的警告之一是“没有类型签名的顶级绑定(bind)”,然后编译器告诉我类型签名应该是什么。

我不知道显式定义类型签名的优点是什么。举个具体的例子:

-- matchStr :: String -> String ->  Maybe (String)
matchStr str s
| isPrefixOf str s = Just(drop (length str) s)
| otherwise = Nothing

现在,如果我想将类型从 String 更改为 ByteString 以提高性能,会发生什么情况?我必须导入 ByteString 包并使用某些函数的合格版本。无需进行其他更改。如果我有类型签名,那么我还必须更改它,但 Haskell 编译器会注意到此更改并正确推断新类型。

那我错过了什么?为什么在一般情况下在函数上显式放置类型签名被认为是一个好主意?也就是说,我知道在某些情况下它可能是个好主意,但为什么它总体上被认为是好的?

最佳答案

如果您在定义函数时犯了错误,编译器可能会推断出与您期望的类型不同的类型。如果您声明了所需的类型,编译器将在函数定义中报告错误。

如果没有声明,编译器就无法知道其推断的类型是“错误的”,并且最终会在您尝试调用函数的地方报告错误,这不太清楚问题的真正所在。

如果调用函数也没有类型声明,那么编译器可能不会报告错误,而是推断出不正确的类型,从而导致调用者出现问题。您最终会在某处收到错误消息,但它可能与问题的实际根源相去甚远。

<小时/>

此外,您还可以声明比编译器推断的类型更具体的类型。例如,如果您编写函数:

foo n = n + 1

编译器将推断类型 Num a => a -> a,这意味着它必须编译可与任何 Num 实例一起使用的通用代码。如果将类型声明为 Int -> Int,编译器可能能够生成专门针对整数的更高效的代码。

<小时/>

最后,类型声明充当文档。编译器也许能够推断复杂表达式的类型,但对于人类读者来说并不那么容易。类型声明提供了“全局”,可以帮助程序员理解函数的作用。

请注意Haddock注释附加在声明上,而不是定义上。编写类型声明是为使用 Haddock 的函数提供附加文档的第一步。

关于haskell - 当编译器可以推断类型时,为函数使用类型签名的充分理由是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23401698/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com