首页 文章

Monads,>> =和“嵌套的lambdas”

提问于
浏览
1

我觉得我在读完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组合两个结果 .

我还没有理解 nm 中来自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 aNothing 时,绑定运算符不关心具有签名的函数 (a->maybe a) - 返回 Nothing .

Pattern 2 - 当 Maybe aJust x 时,绑定运算符关心该函数并应用函数ie( f x ,函数 fJust x 应用值 x )并返回值为 Maybe b 的结果值 .

这里 ab 可以是不同的类型 . 例如 a 可以是整数 b 可以是 String .

现在,如果我们在给定的除法示例中应用bind的定义,

eval (Val n)   = Just n
eval (Div x y) = eval x >>= (\n ->
                  eval y >>= (\m ->
                  safediv n m))

eval xeval (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 回答

  • 1

    我担心如果你不理解词法范围和词法闭包的基础知识,那么你将很难理解嵌套lambda中的这种“状态”管理,特别是在desugared monad代码的情况下 .

    所以你的问题的答案实际上并不在于你所要求的,而是在你的理解中缺少一些先决条件 .

    考虑

    > let f = \x -> \y -> y * 2 + x * 7
    > let f' = f 3
    

    现在 f' 包含类似于闭包的东西 - 它是第一个lambda的主体,其中 x 的值被记住为 3 . 依次将值传递给 f' ,也就是"fills in the placeholder"`y,之后x的记忆值和y的现在可用值是(根据需要)用于评估表达式2y 7x .

    > f' 4
    29
    

    Monads只是使用这样的结构来记住以前的monadic步骤中的值 . 当然,通常你会使用 do 语法糖来隐藏这种lambda管道 .


    附:如果它可能不明显,这两行是等价的:

    > let f = \x -> \y -> y * 2 + x * 7
    > let f x y = y * 2 + x * 7
    

    我只是使用明确的curried形式来绘制与monadic lambdas的平行 .

  • 4

    我不太清楚我理解你的问题 . 例如 eval x 的"temporary result"变为 neval y 的"temporary result"变为 m . 对于 safediv n m ,范围内都可以访问 nm ,因此您可以引用它们,就像您可以引用您所在范围内的任何变量一样,例如:当你嵌套 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 的原因 .

    (>>=)   :: Maybe a -> (a -> Maybe b) -> Maybe b
     m >>= f =  case m of
                   Nothing -> Nothing
                   Just x  -> f x
    

相关问题