func = elem [1..10] 在 GHCi 中工作但不编译

func = elem [1..10] works in GHCi but doesn't compile

在 GHCi 中 运行 这个命令

func = elem [1..10]

工作正常,并返回了部分功能。我很好奇为什么它有效?当我尝试编译这段代码时,它给了我一个错误。例如,这不适用于其他功能。 Map 在 GHCi 和编译时给我一个错误。

func = map [1..10]

想知道 GHCi 和函数 elem 有什么特别之处。

我知道我可以这样写:

func = (`elem` [1..10])

func = (`map` [1..10])

它有效,但为什么其他方法对 elem 有效。

elem [1..10] 是一个非常明智的术语。示例:

Prelude> elem [1..10] [[0..9], [1..10]]
True
Prelude> elem [1..10] [[0..8], [1..7]]
False

也许更常见的是这样写

Prelude> [1..10] `elem` [[0..9], [1..10]]
True
Prelude> [1..10] `elem` [[0..8], [1..7]]
False

但这只是同一事物的不同语法版本。

这也意味着它 可以 被编译,你只需要给它一个合适的签名(或者让 GHC 为你推断一个)。例如,

f :: [[Int]] -> Bool
f = elem [1..10]

...它是告诉您数字列表列表是否包含列表 [1..10] 的函数。 IE。与 elem 的任何其他用法一样,它会告诉您某个列表是否包含某个元素。这个元素恰好本身就是一个列表这一事实是无关紧要的。

另一方面 map [1..10] 是错误的,因为 map 的第一个参数必须是 函数 。列表虽然可以是列表元素,但永远不能是函数.

运算符部分 (`elem`[1..10])(`map`[1..10]) 则完全不同。在这些示例中,[1..10] 实际上是 second 参数。该部分省略了 left/first 参数。所以在这种情况下,我们所说的是

Prelude> 3 `elem` [1..10]
True
Prelude> 19 `elem` [1..10]
False

...这也适用于

Prelude> negate `map` [1..10]
[-1,-2,-3,-4,-5,-6,-7,-8,-9,-10]

尽管更常见的写法是 map negate [1..10]negate<$>[1..10]


从某种意义上说,既迂腐又无政府主义,列表 实际上可以是函数:用 -XOverloadedLists 扩展名,您可以编写一个 class-实例,允许您使用列表语法定义函数。我看不出这有什么意义,但了解这种理论上的可能性也许是件好事。特别是,启用该扩展后,map [1..10] 令人困惑地 确实 编译,你只会在其他地方得到一个涉及 Could not deduce ... The type variable ‘a0’ is ambiguous 乱码的令人困惑的错误.