Haskell函数组成混乱

 美丽女人一起来_381 发布于 2023-02-12 06:00

我正在努力学习haskell,而且我一直在学习了解你是一个Haskell的第6章和第7章.为什么以下两个函数定义不能给出相同的结果?我以为(f.g)x = f(g(x))?

Def 1

let{ t :: Eq x => [x] -> Int; t xs = length( nub xs)}
t [1]
1

Def 2

let t = length . nub 
t [1]

:78:4:
    No instance for (Num ()) arising from the literal `1'
    Possible fix: add an instance declaration for (Num ())
    In the expression: 1
    In the first argument of `t', namely `[1]'
    In the expression: t [1]

Tikhon Jelvi.. 9

问题在于您的类型签名和可怕的单态限制.您的第一个版本中有类型签名,但在第二个版本中没有; 具有讽刺意味的是,它本来会有相反的方式!

试试这个:

?>let t :: Eq x => [x] -> Int; t = length . nub
?>t [1]
1

单态限制强制看起来不像函数的东西具有单态类型,除非它们具有显式类型签名.您的类型t具有多态性:注意类型变量x.然而,随着单态限制,x被"默认"为().看一下这个:

?>let t = length . nub
?>:t t
t :: [()] -> Int

这与上面带有类型签名的版本非常不同!

()由于默认,编译器选择单态类型.默认只是Haskell用于从类型类中选择类型的过程.所有这一切的真正含义是,在REPL,哈斯克尔会尝试使用(),如果在遇到模棱两可的类型变量类型Show,EqOrd类.是的,这基本上是随意的,但是无需在任何地方编写类型签名,这对于玩游戏非常方便!此外,默认规则在文件中更为保守,因此这基本上只是在GHCi中发生的事情.

事实上,默认()似乎主要是printf在GHCi中正确工作的黑客!这是一个不起眼的Haskell古玩,但我在实践中忽略了它.

除了包含类型签名外,您还可以在repl中关闭单态限制:

?>:set -XNoMonomorphismRestriction

这在GHCi中很好,但我不会在实际模块中使用它 - 相反,请确保始终在文件内包含顶级定义的类型签名.

编辑:自GHC 7.8.1起,GHCi默认关闭单态限制.这意味着所有这些代码都可以与最新版本的GHCi一起使用,并且您不需要显式设置标志.但是,对于没有类型签名的文件中定义的值,它仍然是一个问题.

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有