首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >也许是单体建筑

也许是单体建筑
EN

Stack Overflow用户
提问于 2014-10-07 16:11:44
回答 2查看 1K关注 0票数 2

我目前正在为Haskell的一个新元素而奋斗:Monad。因此,我是通过创建一个(>>=)操作符来介绍这个问题的,该操作符仅在不等于Nothing的情况下执行Maybe类型上的函数(以其实际整数值作为参数),否则返回Nothing

代码语言:javascript
复制
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
Nothing >>= _ = Nothing
(Just x) >>= f = f x

但是,我不太确定它的以下用法如何工作:

代码语言:javascript
复制
eval (Val n) = Just n
eval (Div x y) = eval x >>= (\n ->
    eval y >>= (\m ->
        safediv n m))

在我看来,(>>=)操作符只需要一个Maybe值和一个返回一个Maybe值的函数,但是在这个例子中,使用代码似乎需要2倍的Maybe值和一次函数。然而,我被告知,它计算x,将结果放入n,然后计算y,将结果放在y中,然后在这两个方面执行safediv函数。虽然我看不出(>>=)操作符是如何在这里发挥作用的;这是如何工作的呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-10-07 16:17:14

你可以这样读:

代码语言:javascript
复制
eval (Div x y) = eval x >>= (\n ->
    eval y >>= (\m ->
        safediv n m))

当你想做eval (Div x y)的时候

  • 第一eval x
    • if if Just n (使用第一个>>=)

    • 然后使用n并查看eval y (使用第一个>>=)。

      • 如果最后一个是Just m (第二个>>=)

      • 然后取m并做一个(第二个>>=)

      • savediv n m返回它的结果-您仍然拥有关闭的n

在任何其他caes中返回Nothing

所以在这里,(>>=)只会帮助你解构。

也许在do表单中更容易阅读和理解:

代码语言:javascript
复制
eval (Val n) = Just n
eval (Div x y) = do
    n <- eval x
    m <- eval y
    safediv n m

它只是(>>=)周围的语法糖

我们来查案吧:

  1. eval x = Nothingeval y = Nothing

代码语言:javascript
复制
eval x >>= (...) = Nothing >>= (...) = Nothing
  1. eval x = Nothingeval y = Just n

这也是一样的:

代码语言:javascript
复制
eval x >>= (...) = Nothing >>= (...) = Nothing
  1. eval x = Just neval y = Nothing

代码语言:javascript
复制
eval x >>= (\n -> eval y >>= (...))
= Just n >>= (\n -> eval y >>= (...)) 
= Just n >>= (\n -> Nothing)
= Nothing
  1. eval x = Just neval y = Just m

代码语言:javascript
复制
eval x >>= (\n -> Just m >>= (...))
= Just n >>= (\n -> Just m >>= (...)) 
= Just n >>= (\n -> Just m >>= (\m -> safediv n m))
= (first >>= for Just) = Just m >>= (\n -> safediv n m)
= (second >>= for Just) = safediv n m
票数 6
EN

Stack Overflow用户

发布于 2014-10-07 16:36:44

让我们进行元素追逐来说明它是如何工作的。如果我们有

代码语言:javascript
复制
eval (Div (Val 5) (Div (Val 0) (Val 1)))

然后我们就可以把它分解成

代码语言:javascript
复制
eval (Div (Val 5) (Div (Val 0) (Val 1)))
    = eval (Val 5) >>=
        (\n ->
            eval (Div (Val 0) (Val 1)) >>=
                (\m ->
                    safediv n m
                )
        )

-- eval (Val 5) = Just 5

    = Just 5 >>=
        (\n ->
            eval (Div (Val 0) (Val 1)) >>=
                (\m ->
                    safediv n m
                )
        )

-- Just x >>= f = f x

    = (\n ->
        eval (Div (Val 0) (Val 1)) >>=
            (\m ->
                safediv n m
            )
      ) 5

-- Substitute n = 5, since the 5 is the argument to the `\n ->` lamba

    = eval (Div (Val 0) (Val 1)) >>=
        (\m ->
            safediv 5 m
        )

现在我们需要绕道计算eval (Div (Val 0) (Val 1)).

代码语言:javascript
复制
eval (Div (Val 0) (Val 1))
    = eval (Val 0) >>=
        (\n ->
            eval (Val 1) >>=
                (\m ->
                    safediv n m
                )
        )

-- eval (Val 0) = Just 0
-- eval (Val 1) = Just 1

eval (Div (Val 0) (Val 1))
    = Just 0 >>=
        (\n ->
            Just 1 >>=
                (\m ->
                    safediv n m
                )
        )

-- Just x >>= f = f x

eval (Div (Val 0) (Val 1))
    = (\n ->
        (\m ->
            safediv n m
        ) 1
      ) 0

    = (\n -> safediv n 1) 0
    = safediv 0 1
    = Just 0

现在回到我们对eval的原始调用,在以下内容中替换Just 0

代码语言:javascript
复制
eval (Div (Val 5) (Div (Val 0) (Val 1)))
    = Just 0 >>= (\m -> safediv 5 m)

-- Just x >>= f = f x

eval (Div (Val 5) (Div (Val 0) (Val 1)))
    = safediv 5 0

-- safediv x 0 = Nothing

eval (Div (Val 5) (Div (Val 0) (Val 1)))
    = Nothing
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26240534

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档