本文介绍了为什么我的顶级函数需要在Haskell中签名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
GHC警告说,我没有顶层的功能签名。我不明白为什么我需要他们。提供它们的问题是它们非常复杂,像这样(自动生成): applyValue :: forall t t1 t2 t3 t4。
(t2 - > t)
- > (t2→t3→t4→t1)→> t2 - > t3 - > t4 - > (t - > Bool) - > [t1]
那么为什么我还要麻烦添加它们?
函数本身:
applyValue getValueAt在结构标记处使用stitchAndMove matchAt =
如果matchAt(getValueAt at )
然后[stitchAndMove在织物标记处]
else []
解决方案
- 作为机器可检查文档的一种形式。如果您认为这种类型是正确的类型,那么在那里要求编译器仔细检查您在以后的不可避免的重构会话期间是否没有自己的界面。
- 作为人类可读文档。尽管正如你所观察到的,当你注意到你正在编写一个糟糕的机器生成类型的时候,现在可能是时候考虑一下你需要什么(类型级别)抽象来让它可读。
- 对于haddock。 Haddock注释会附加到类型签名,而不是绑定,所以如果您遗漏了类型签名,那么您仔细手写的文档将被默默忽略。
- 改进错误消息和ghci查询结果:虽然类型变量的实际名称无关紧要,但GHC在用户提供时尽量保留名称。像
(节点 - > Bool) - > (edge→> Bool)→> (图表 - > Bool)
可以比(t1 - > Bool) - > (t2→Bool)→> (t3 - > Bool)
,即使它们是相同的。
GHC warns that I don't have the function signatures at the top level. I don't get why I would need them. The problem with providing them is that they are quite sophisticated, like this one (autogenerated):
applyValue :: forall t t1 t2 t3 t4.
(t2 -> t)
-> (t2 -> t3 -> t4 -> t1) -> t2 -> t3 -> t4 -> (t -> Bool) -> [t1]
So why would I bother adding them?
the function itself:
applyValue getValueAt stitchAndMove at fabric mark matchAt =
if matchAt (getValueAt at)
then [stitchAndMove at fabric mark]
else []
解决方案
- As a form of machine-checkable documentation. If you believe that type to be the right type, putting it there asks the compiler to double-check that you didn't hose your own interface during your later inevitable refactoring sessions.
- As human-readable documentation. Although as you observe, when you notice you're writing an awful machine-generated type, it's probably time to think about what (type-level) abstractions you need to make it human-readable.
- For haddock. Haddock comments get attached to type signatures, not bindings, so if you leave out a type signature, your carefully hand-written documentation will be silently ignored.
- To improve error messages and ghci query results: although the actual names of type variables don't matter, GHC tries hard to preserve names when they're provided by the user. Something like
(node -> Bool) -> (edge -> Bool) -> (graph -> Bool)
can be much more readable than(t1 -> Bool) -> (t2 -> Bool) -> (t3 -> Bool)
, even though they're equivalent.
这篇关于为什么我的顶级函数需要在Haskell中签名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!