了解 haskell monad 的作用域
Understanding scoping with haskell monads
我正在尝试了解作用域在 do 块中的工作原理。
如果我有以下代码:
l = [1, 2, 3]
m = [1, 2]
那么这很好
res = do
a <- l
b <- m
return (a, b)
和returnm
和l
的笛卡尔积。
为了理解范围,我尝试以不同的形式重写它(没有 do 块)
我知道 do 块只是 monadic 操作的语法糖所以我尝试 "unsugar" 它并使用 this 并想出了这个:
res = l >>= (\a -> m) >>= (\b -> return (a, b))
奇怪的是我得到了这个错误 Not in scope: ‘a’
。
谁能告诉我哪里做错了,可能还有范围界定是如何工作的,因为 do 块中的 return
能够访问一个 ?
看起来真的很神奇
非常感谢
问题是您代码中的 lambda 范围不太正确。它应该一直延伸到表达式的末尾,而不仅仅是围绕小计算。你的代码应该脱糖到
l >>= (\a -> m >>= (\b -> return (a, b))
顺便把括号去掉,这样会更舒服一些。
l >>= \a -> m >>= \b -> return (a, b)
但是这样就把意思弄糊涂了。如果你想痛苦地明确,我们可以转换为前缀表示法并说
bind a f = a >>= f
bind l (\a -> bind m (\b -> return (a, b))
也许去除一些运算符糖会有所帮助。
请注意 >>= 是如何嵌套在 内部 lambda 中的,而不是围绕它。这确保 a
保留在范围内。事实上,这种嵌套用手写出来有点痛苦,这是 do-notation 的一部分推动力:)
问题出在你的括号上。你写
res = l >>= (\a -> m) >>= (\b -> return (a, b))
但你需要的是
res = l >>= (\a -> m >>= (\b -> return (a, b)))
也可以这样写
res = l >>= \a -> m >>= \b -> return (a, b)
您过早结束了 lambda 表达式绑定 a
,然后尝试使用 a
。
我正在尝试了解作用域在 do 块中的工作原理。
如果我有以下代码:
l = [1, 2, 3]
m = [1, 2]
那么这很好
res = do
a <- l
b <- m
return (a, b)
和returnm
和l
的笛卡尔积。
为了理解范围,我尝试以不同的形式重写它(没有 do 块)
我知道 do 块只是 monadic 操作的语法糖所以我尝试 "unsugar" 它并使用 this 并想出了这个:
res = l >>= (\a -> m) >>= (\b -> return (a, b))
奇怪的是我得到了这个错误 Not in scope: ‘a’
。
谁能告诉我哪里做错了,可能还有范围界定是如何工作的,因为 do 块中的 return
能够访问一个 ?
非常感谢
问题是您代码中的 lambda 范围不太正确。它应该一直延伸到表达式的末尾,而不仅仅是围绕小计算。你的代码应该脱糖到
l >>= (\a -> m >>= (\b -> return (a, b))
顺便把括号去掉,这样会更舒服一些。
l >>= \a -> m >>= \b -> return (a, b)
但是这样就把意思弄糊涂了。如果你想痛苦地明确,我们可以转换为前缀表示法并说
bind a f = a >>= f
bind l (\a -> bind m (\b -> return (a, b))
也许去除一些运算符糖会有所帮助。
请注意 >>= 是如何嵌套在 内部 lambda 中的,而不是围绕它。这确保 a
保留在范围内。事实上,这种嵌套用手写出来有点痛苦,这是 do-notation 的一部分推动力:)
问题出在你的括号上。你写
res = l >>= (\a -> m) >>= (\b -> return (a, b))
但你需要的是
res = l >>= (\a -> m >>= (\b -> return (a, b)))
也可以这样写
res = l >>= \a -> m >>= \b -> return (a, b)
您过早结束了 lambda 表达式绑定 a
,然后尝试使用 a
。