我觉得我在读完Graham Hutton's monad article后感到困惑 . 以下是砖墙 . (文章中的文字)
使用>> =,我们的评估器现在可以重写为:eval(Val n)= Just n
eval(Div x y)= eval x >> =(\ n - > eval y >> =(\ m - > safediv n m))
除法的情况可以理解如下:求x并调用其结果值n,然后计算y并调用其结果值m,最后通过应用safediv组合两个结果 .
我还没有理解 n
和 m
中来自lambdas的 temporary results are stored . "nesting of lambdas"有哪些规则并重新审核其结果?
编辑:
我接受我是一个新手,我的基础不强 . 理解不好的一个原因是绑定运算符 >>=
的定义和结果的混淆 . 我看了一下绑定运算符将返回计算值的事实
"f applied on x".
我会尝试总结一下(半)理解 .
在此上下文中绑定运算符的定义:
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
Nothing >>= _ = Nothing
(Just x) >>= f = f x
解释上述定义:
Signature - 绑定运算符采用 Maybe a
的类型,另一个带有签名 ((a->maybe a)
的高阶函数,并将其应用于 a
并返回类型为 Maybe b
的结果值
Pattern 1 - 当 Maybe a
为 Nothing
时,绑定运算符不关心具有签名的函数 (a->maybe a)
- 返回 Nothing
.
Pattern 2 - 当 Maybe a
为 Just x
时,绑定运算符关心该函数并应用函数ie( f x
,函数 f
从 Just x
应用值 x
)并返回值为 Maybe b
的结果值 .
这里 a
和 b
可以是不同的类型 . 例如 a
可以是整数 b
可以是 String
.
现在,如果我们在给定的除法示例中应用bind的定义,
eval (Val n) = Just n
eval (Div x y) = eval x >>= (\n ->
eval y >>= (\m ->
safediv n m))
eval x
在 eval (Div x y)
will return Just n 行中,基于模式 eval (Val n) = Just n . 这是绑定运算符的第一个参数 . 因此我们可以把它写成
eval (Div x y) = Maybe a >>= f -- .We are applying `>>=` operator.
eval (Div x y) = Just n >>= (\n -> eval y >>= (\m -> safediv n m))
因为绑定运算符 >>=
的结果在我们的上下文中是 f x ,所以"lambda" (\n -> eval y >>= (\m -> safediv n m)) 将应用于 n
.
能告诉我,到目前为止我的理解是否正确 . 如果这种理解是正确的,我需要在 n 上找出"lambda" (\n -> eval y >>= (\m -> safediv n m)) 的应用结果:
(\n -> eval y >>= (\m -> safediv n m)) n
2 回答
我担心如果你不理解词法范围和词法闭包的基础知识,那么你将很难理解嵌套lambda中的这种“状态”管理,特别是在desugared monad代码的情况下 .
所以你的问题的答案实际上并不在于你所要求的,而是在你的理解中缺少一些先决条件 .
考虑
现在
f'
包含类似于闭包的东西 - 它是第一个lambda的主体,其中x
的值被记住为3
. 依次将值传递给f'
,也就是"fills in the placeholder"`y,之后x的记忆值和y的现在可用值是(根据需要)用于评估表达式2y 7x .Monads只是使用这样的结构来记住以前的monadic步骤中的值 . 当然,通常你会使用
do
语法糖来隐藏这种lambda管道 .附:如果它可能不明显,这两行是等价的:
我只是使用明确的curried形式来绘制与monadic lambdas的平行 .
我不太清楚我理解你的问题 . 例如
eval x
的"temporary result"变为n
,eval y
的"temporary result"变为m
. 对于safediv n m
,范围内都可以访问n
和m
,因此您可以引用它们,就像您可以引用您所在范围内的任何变量一样,例如:当你嵌套let
表达式时 .注意,通过
Maybe
的bind(>>=
)定义,即(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
,值(例如n
)为lambda(\n -> ...)
的"handed" . 因此,例如expr x
评估为Maybe a
,然后您将其应用于>>=
,例如themaybe >>= lambda
. 在下面的定义中,lambda对应于f
,因此您可以看到,如果eval x
被评估为Just a
,它将x
应用于lambda(即f x
) . lambda本身的计算结果为Maybe a
,这就是为什么你可以进一步链接/嵌套另一个>>= lambda
的原因 .