我认为在阅读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
中lambda的临时结果是如何存储的。什么是" lambdas嵌套的规则"并重新审视其结果?
编辑:
我接受我是一个新手,我的基础知识并不强烈。理解不好的一个原因是对绑定运算符>>=
的定义和结果的混淆。我忽略了绑定运算符将返回计算值
"f applied on x".
我会尝试总结一下(半)的理解。
在此上下文中绑定运算符的定义:
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
Nothing >>= _ = Nothing
(Just x) >>= f = f x
解释上述定义:
签名 - 绑定运算符采用Maybe a
的类型,另一个带有签名((a->maybe a)
的高阶函数,并将其应用于a
并返回结果值输入Maybe b
模式1 - 当Maybe a
为Nothing
时,绑定运算符并不关心带有签名(a->maybe a)
的函数 - 返回{{ 1}}。
模式2 - 当Nothing
为Maybe a
时,绑定运算符关心函数并应用函数ie(Just x
,function f x
从f
获取值x
,并返回类型为Just x
的结果值。
此处Maybe b
和a
可以是不同类型。例如b
可以是整数a
可以是b
。
现在,如果我们在给定的除法示例中应用bind的定义,
String
行eval (Val n) = Just n
eval (Div x y) = eval x >>= (\n ->
eval y >>= (\m ->
safediv n m))
中的 eval x
将根据 eval (Div x y)
模式返回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))
的结果在我们的上下文中是 >>=
,所以" lambda" f x
将应用于(\n -> eval y >>= (\m -> safediv n m))
。
请你知道我的理解到目前为止是否正确。
如果这种理解是正确的,我需要弄清楚" lambda"的应用结果。 n
上的 (\n -> eval y >>= (\m -> safediv n m))
:
n
答案 0 :(得分:4)
我害怕如果你不理解词法范围和词法闭包的基础知识,那么你将很难理解嵌套lambda中的这种“状态”管理,特别是在desugared monad代码的情况下。
所以你的问题的答案实际上并不在于你所要求的,而是在你的理解中缺少一些先决条件。
考虑
> let f = \x -> \y -> y * 2 + x * 7
> let f' = f 3
现在f'
包含类似于闭包的东西 - 它是第一个lambda的主体,其中x
的值已被记住为3
。依次将值传递给f'
,也“填充占位符”y,之后记忆的x值和y的现在可用值(按需)用于评估表达式2y + 7x。
> f' 4
29
Monads只是使用这样的结构来记住以前的monadic步骤中的值。当然,通常你会使用隐藏这种lambda管道的do
句法糖。
P.S。如果它可能不明显,这两行是等价的:
> let f = \x -> \y -> y * 2 + x * 7
> let f x y = y * 2 + x * 7
我只是使用显式curried形式来绘制与monadic lambdas的平行线。
答案 1 :(得分:1)
我不太清楚我理解你的问题。 "临时结果"例如eval x
成为n
,而临时结果为#34}。 eval y
成为m
。对于safediv n m
,范围内都可以访问n
和m
,因此您可以引用它们,就像您可以引用您所在范围内的任何变量一样,例如嵌套let
表达式时。
请注意,价值(例如n
)是"递交"通过(\n -> ...)
的绑定(>>=
)定义(即Maybe
)到lambda (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
。例如,expr x
评估为Maybe a
,然后将其应用于>>=
,例如themaybe >>= lambda
。在下面的定义中,lambda对应于f
,因此您可以看到,如果eval x
评估为Just a
,它会将x
应用于f x
lambda(即Maybe a
)。 lambda本身的计算结果为>>= lambda
,这就是为什么你可以进一步链接/嵌套另一个 (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
m >>= f = case m of
Nothing -> Nothing
Just x -> f x
。
1=New York, 2=Paris, 3=London, 4=Moscow, 5=Boston, ..., 230=Tblisi