为什么列表理解接受混合的 `[Char]` 和 `[[Char]]` 而不会在 Haskell 中出错?
Why does a list comprehension accept mixed `[Char]` and `[[Char]]` without error in Haskell?
在学习Haskell的过程中,我发现了一些令我困惑的事情。
我不明白为什么此代码有效:
Prelude> [y | y <- "a", y <- ["a"]]
["a"]
我尝试更改为显式 [Char]
并得到相同的结果(这是有道理的):
Prelude> [y | y <- ['a'], y <- ["a"]]
["a"]
令人惊讶的是,这也是有效的:
Prelude> [y | y <- "a", y <- [["a"]]]
[["a"]]
[编辑]
给出的错误与同一事实无关:
正如我所料,这恰恰相反:
Prelude> [y | y <- 'a', y <- ['a']]
<interactive>:12:11: error:
* Couldn't match expected type `[t0]' with actual type `Char'
* In the expression: 'a'
In a stmt of a list comprehension: y <- 'a'
In the expression: [y | y <- 'a', y <- ['a']]
[y | y <- 'a']
无效,因为 'a' 不是列表。
[/编辑]
我认为这是 String
与 Char
造成的一些常见混乱,但绝对不是:
Prelude> [y | y <- [1], y <- [[2]]]
[[2]]
郑重声明,我使用的是 GHCi 8.2.2 版和 Arch Linux。
打开警告!您应该看到第一个 y
被第二个覆盖。
有点类似于
let y = True
in let y = "a"
in y
第一个定义被遮盖了,就好像它是
let _ = True
in let y = "a"
in y
甚至,删除阴影绑定,
let y = "a"
in y
类似地,列表理解如
[y | y <- "a", y <- ["a"]]
计算结果与
相同
[y | _ <- "a", y <- ["a"]]
-- or, if you prefer
[y | x <- "a", y <- ["a"]]
请注意,与上面的 let
不同,在列表推导中,我们不能简单地删除隐藏的绑定 y <- ...
。例如,
[y | y <- [1,2], y <- [3,4]]
产生 [3,4,3,4]
,不同于 [y | y <- [3,4]]
。
在这里您可以看到每个示例生成的警告:
Prelude> :set -Wall
Prelude> [y | y <- "a", y <- ["a"]]
<interactive>:41:6: warning: [-Wunused-matches]
Defined but not used: `y'
<interactive>:41:16: warning: [-Wname-shadowing]
This binding for `y' shadows the existing binding
bound at <interactive>:41:6
["a"]
Prelude> [y | x <- "a", y <- ["a"]]
<interactive>:47:6: warning: [-Wunused-matches]
Defined but not used: `x'
["a"]
-- no warning here
Prelude> [y | _ <- "a", y <- ["a"]]
["a"]
Prelude> [y | y <- [1,2] , y <- [3,4]]
<interactive>:49:1: warning: [-Wtype-defaults]
* Defaulting the following constraints to type `Integer'
(Show a0) arising from a use of `print' at <interactive>:49:1-29
(Num a0) arising from a use of `it' at <interactive>:49:1-29
* In a stmt of an interactive GHCi command: print it
<interactive>:49:6: warning: [-Wunused-matches]
Defined but not used: `y'
<interactive>:49:12: warning: [-Wtype-defaults]
* Defaulting the following constraint to type `Integer'
Num t0 arising from the literal `1'
* In the expression: 1
In the expression: [1, 2]
In a stmt of a list comprehension: y <- [1, 2]
<interactive>:49:12: warning: [-Wtype-defaults]
* Defaulting the following constraint to type `Integer'
Num t0 arising from the literal `1'
* In the expression: 1
In the expression: [1, 2]
In a stmt of a list comprehension: y <- [1, 2]
<interactive>:49:19: warning: [-Wname-shadowing]
This binding for `y' shadows the existing binding
bound at <interactive>:49:6
[3,4,3,4]
在学习Haskell的过程中,我发现了一些令我困惑的事情。
我不明白为什么此代码有效:
Prelude> [y | y <- "a", y <- ["a"]]
["a"]
我尝试更改为显式 [Char]
并得到相同的结果(这是有道理的):
Prelude> [y | y <- ['a'], y <- ["a"]]
["a"]
令人惊讶的是,这也是有效的:
Prelude> [y | y <- "a", y <- [["a"]]]
[["a"]]
[编辑] 给出的错误与同一事实无关:
正如我所料,这恰恰相反:
Prelude> [y | y <- 'a', y <- ['a']]
<interactive>:12:11: error:
* Couldn't match expected type `[t0]' with actual type `Char'
* In the expression: 'a'
In a stmt of a list comprehension: y <- 'a'
In the expression: [y | y <- 'a', y <- ['a']]
[y | y <- 'a']
无效,因为 'a' 不是列表。
[/编辑]
我认为这是 String
与 Char
造成的一些常见混乱,但绝对不是:
Prelude> [y | y <- [1], y <- [[2]]]
[[2]]
郑重声明,我使用的是 GHCi 8.2.2 版和 Arch Linux。
打开警告!您应该看到第一个 y
被第二个覆盖。
有点类似于
let y = True
in let y = "a"
in y
第一个定义被遮盖了,就好像它是
let _ = True
in let y = "a"
in y
甚至,删除阴影绑定,
let y = "a"
in y
类似地,列表理解如
[y | y <- "a", y <- ["a"]]
计算结果与
相同[y | _ <- "a", y <- ["a"]]
-- or, if you prefer
[y | x <- "a", y <- ["a"]]
请注意,与上面的 let
不同,在列表推导中,我们不能简单地删除隐藏的绑定 y <- ...
。例如,
[y | y <- [1,2], y <- [3,4]]
产生 [3,4,3,4]
,不同于 [y | y <- [3,4]]
。
在这里您可以看到每个示例生成的警告:
Prelude> :set -Wall
Prelude> [y | y <- "a", y <- ["a"]]
<interactive>:41:6: warning: [-Wunused-matches]
Defined but not used: `y'
<interactive>:41:16: warning: [-Wname-shadowing]
This binding for `y' shadows the existing binding
bound at <interactive>:41:6
["a"]
Prelude> [y | x <- "a", y <- ["a"]]
<interactive>:47:6: warning: [-Wunused-matches]
Defined but not used: `x'
["a"]
-- no warning here
Prelude> [y | _ <- "a", y <- ["a"]]
["a"]
Prelude> [y | y <- [1,2] , y <- [3,4]]
<interactive>:49:1: warning: [-Wtype-defaults]
* Defaulting the following constraints to type `Integer'
(Show a0) arising from a use of `print' at <interactive>:49:1-29
(Num a0) arising from a use of `it' at <interactive>:49:1-29
* In a stmt of an interactive GHCi command: print it
<interactive>:49:6: warning: [-Wunused-matches]
Defined but not used: `y'
<interactive>:49:12: warning: [-Wtype-defaults]
* Defaulting the following constraint to type `Integer'
Num t0 arising from the literal `1'
* In the expression: 1
In the expression: [1, 2]
In a stmt of a list comprehension: y <- [1, 2]
<interactive>:49:12: warning: [-Wtype-defaults]
* Defaulting the following constraint to type `Integer'
Num t0 arising from the literal `1'
* In the expression: 1
In the expression: [1, 2]
In a stmt of a list comprehension: y <- [1, 2]
<interactive>:49:19: warning: [-Wname-shadowing]
This binding for `y' shadows the existing binding
bound at <interactive>:49:6
[3,4,3,4]