我正在尝试使用'良好的Haskell风格'进行编码,因此我尝试遵循我发现的典型编码标准.此外,使用-Wall和-Werror进行编译,因为我习惯于来自C.我经常得到的一个警告是"没有类型签名的顶级绑定",然后编译器告诉我类型签名应该是什么.
我想念明确定义类型签名的优点是什么.作为一个具体的例子:
-- matchStr :: String -> String -> Maybe (String)
matchStr str s
| isPrefixOf str s = Just(drop (length str) s)
| otherwise = Nothing
Run Code Online (Sandbox Code Playgroud)
现在,如果我想将类型从String更改为ByteString以提高性能,会发生什么?我将不得不导入ByteString包并使用某些函数的限定版本.不需要进行其他更改.如果我有类型签名,那么我也必须更改它,但Haskell编译器会注意到这个更改并正确地推断出新类型.
那我错过了什么?为什么在一般情况下明确地将类型签名放在函数上是个好主意?也就是说,我知道可能有例外,这是一个好主意,但为什么它一般被认为是好的?
Wyz*_*a-- 43
如果在定义函数时出错,编译器可能会推断出与您预期的类型不同的类型.如果您已声明了所期望的类型,编译器将在函数的定义中报告错误.
如果没有声明,编译器就无法知道它的推断类型是"错误的",而是最终会在你试图调用函数的地方报告错误,这使得问题真正存在的地方不太清楚.
如果调用函数没有类型声明任何话,而不是报告错误的存在,编译器可能只是推断不正确类型也为它们,造成问题的来电.您最终会在某处收到错误消息,但它可能与问题的实际根目录相差甚远.
此外,您可以声明比编译器推断的更具体的类型.例如,如果您编写函数:
foo n = n + 1
Run Code Online (Sandbox Code Playgroud)
编译器将推断类型Num a => a -> a,这意味着它必须编译可以与任何Num实例一起使用的通用代码.如果将类型声明为Int -> Int,则编译器可能能够生成仅专用于整数的更高效代码.
最后,类型声明用作文档.编译器可能能够推断复杂表达式的类型,但对于人类读者来说并不容易.类型声明提供了"大图",可以帮助程序员理解函数的功能.
请注意,Haddock注释附加到声明,而不是定义.编写类型声明是使用Haddock为函数提供附加文档的第一步.
cre*_*ert 21
我认为文档具有显式类型签名的一个优点.
从"类型和编程语言":
在阅读程序时,类型也很有用.过程头和模块接口中的类型声明构成了一种文档形式,提供了有关行为的有用提示.此外,与注释中嵌入的描述不同,这种形式的文档不会过时,因为在编译器的每次运行期间都会检查它.类型的这种角色在模块签名中尤为重要.
Mat*_*hid 15
有几个原因.
FilePath对比String)值得注意的是,有些人提倡您从类型签名开始,并在稍后填写实现.
无论如何,大多数人似乎都建议对所有或大多数顶级声明使用类型签名.你是否给他们提供局部变量/功能是一个品味问题.
| 归档时间: |
|
| 查看次数: |
1377 次 |
| 最近记录: |