我有一个非常简单的问题。我想在使用绑定运算符的代码块之后使用where子句,但是我得到了编译错误。
这是一个简单的例子:
main =
putStrLn "where clause test:" >>
return [1..10] >>= \list ->
print list'
where list' = reverse list -- test1.hs:5:28: Not in scope: `list'
我可以在列表'中使用let子句,如
main =
putStrLn "where clause test:" >>
return [1..10] >>= \list ->
let list' = reverse list -- works of course
in print list'
但是我真的很喜欢它,如果我可以使用where子句...
我也尝试过做符号
main = do
putStrLn "where clause test:"
list <- return [1..10]
print list'
where list' = reverse list --test3.hs:5:30: Not in scope: `list'
同样的问题。在这种情况下我可以使用where子句吗?
答案 0 :(得分:11)
问题是let
- in
是一个表达式,可以在其他表达式中使用,而where
只能用于(模块|类|实例| GADT)声明或(函数|模式)绑定。
来自Haskell 98报告declarations and bindings,
p | g 1
=
e 1
| g 2=
e 2
...
| g m=
e m
where {
decls}
是糖的
p
= let
declsin
if
g 1then
e 1else
>if
g 2then
e 2else
> ...
if
g mthen
e melse error "Unmatched pattern"
或者,通过删除警卫简化事情,
p
=
ewhere {
decls}
是糖的
p
= let
declsin
e
在函数和模式绑定中。即使您的 e 是do {
... }
结构,也是如此。
如果您希望在较大的表达式中具有特定子表达式的局部绑定,则需要在let
内使用in
- let
(或简称为do
,但这只是let
- in
)的糖。
你甚至不能写
main = do
putStrLn "where clause test: "
list <- return [1..10]
(print list' where list' = reverse list)
因为“ e where {
decls }
”不是合法表达式 - where
只能用于声明和绑定。
main = do
putStrLn "where clause test: "
list <- return [1..10]
let list' = list'' where list'' = reverse list
print list'
这是合法的(如果有些人为)。
答案 1 :(得分:11)
正如ephemient所解释的那样,你不能像你那样使用where
条款。
发生错误是因为在此代码中:
main =
return [1..10] >>= \list ->
print list'
where
list' = reverse list
where
- 子句附加到主函数。
这是具有更多括号的相同功能:
main = return [1..10] >>= (\list -> print list')
where
list' = reverse list
我认为很明显为什么会出现“out of scope
”错误:list
的绑定深入main
表达式,而不是where
子句可以达到。
在这种情况下我通常做的事情(我被同样的事情咬了很多次)。我只是引入一个函数并将list
作为参数传递。
main = do
list <- return [1..10]
let list' = f list
print list'
where
f list = reverse list -- Consider renaming list,
-- or writing in point-free style
当然,我认为f
函数中的实际代码比reverse
要多得多,这就是为什么你希望它在where
子句中,而不是内联{ {1}}绑定。如果let
函数中的代码非常小,我只是将它写在f
绑定中,并且不会经历引入新函数的开销。
答案 2 :(得分:1)
据我所知,where子句仅用于本地绑定。 &gt;(>)绑定语句的内部部分不是本地绑定(该句子中有两种不同的绑定)。
与此比较:
main = f [1..10]
f list =
putStrLn "where clause test:" >> print list'
where list' = reverse list
您可能需要参考Haskell 98 syntax report - 不确定会有多少帮助。
如果我错了,有人肯定会纠正我,但我很确定你不能使用上面显示的样式中的where子句。 list
永远不会在where子句的范围内,除非它是函数的参数。