繁体   English   中英

了解haskell monads的范围

[英]Understanding scoping with haskell monads

我试图理解范围在do块中是如何工作的。

如果我有以下代码:

l = [1, 2, 3]
m = [1, 2]

然后这工作正常

res = do
    a <- l
    b <- m
    return (a, b)

并返回ml的笛卡尔积。

为了理解范围,我试图以不同的形式重写它(没有做块)

我知道块只是monadic操作的语法糖,所以我试图“unsugar”它并使用并想出了这个:

res = l >>= (\a -> m) >>= (\b -> return (a, b))

奇怪的是我得到这个错误Not in scope: 'a'

任何人都可以告诉我我做错了什么,可能,范围如何工作,因为看起来像魔术,do块中的return能够访问?

非常感谢你

问题是代码中lambda的范围不太正确。 它应该一直延伸到表达式的末尾,而不仅仅是小计算。 你的代码应该是desugar

 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范围仍然存在。 事实上,这种嵌套是手工写出来的一点点痛苦,这是写法的推动力的一部分:)

问题出在你的括号上。 你写

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM