gpt4 book ai didi

Haskell 函数组合困惑

转载 作者:行者123 更新时间:2023-12-02 21:18:30 25 4
gpt4 key购买 nike

我正在尝试学习 Haskell,我已经阅读了《Learn you a Haskell》的第 6 章和第 7 章。为什么以下两个函数定义没有给出相同的结果?我以为 (f . g) x = f (g (x))?

防御 1

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

防御 2

let t = length . nub 
t [1]

<interactive>: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]

最佳答案

问题出在你的类型签名和可怕的单态限制上。您在第一个版本中有类型签名,但在第二个版本中没有;具有讽刺意味的是,它会以相反的方式起作用!

试试这个:

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

单态限制强制那些看起来不像函数的东西具有单态类型,除非它们具有显式类型签名。您想要 t 的类型是多态的:注意类型变量 x 。然而,由于单态性限制,x “默认”为 () 。看看这个:

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

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

编译器选择()对于单态类型,因为 defaulting 。默认只是 Haskell 用于从类型类中选择类型的过程。所有这一切真正意味着,在 repl 中,Haskell 将尝试使用 ()如果在 Show 中遇到不明确的类型变量,请键入, EqOrd类。是的,这基本上是任意的,但是它非常方便,无需到处编写类型签名!另外,文件中的默认规则更加保守,因此这基本上只是 GHCi 中发生的事情。

事实上,默认为()似乎主要是黑客制作printf在 GHCi 中可以正常工作!这是一个不起眼的 Haskell 古董,但在实践中我会忽略它。

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

λ>:set -XNoMonomorphismRestriction

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

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

关于Haskell 函数组合困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20470682/

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