"< - "和相关值

Und*_*ren 6 monads haskell

说我写了以下amazin代码:

func = do
  a <- Just 5
  return a
Run Code Online (Sandbox Code Playgroud)

我知道,这是毫无意义的.在这里,a5,并func返回Just 5.

现在我重写了我很棒的(但没有意义的)功能:

func' = do
  a <- Nothing
  return a
Run Code Online (Sandbox Code Playgroud)

这个函数返回了Nothing,但到底是a什么?没有什么可以从一个Nothing值中提取,但是当我做这样的事情时,程序不会抱怨:

func'' = do
  a <- Nothing
  b <- Just 5
  return $ a+b
Run Code Online (Sandbox Code Playgroud)

我只是很难看到实际发生的事情.什么是a?换句话说:<- 实际上做了什么?说它"从右侧提取值并将其绑定到左侧"显然过度简化了它.什么是我没有得到的?

谢谢 :)

Sar*_*rah 11

让我们试着去除最后一个例子的记号.

func'' = Nothing >>= (\a -> Just 5 >>= (\b -> return $ a+b))
Run Code Online (Sandbox Code Playgroud)

现在,让我们看看如何为Maybe定义>> =.它在前奏中:

instance  Monad Maybe  where
    (Just x) >>= k   =  k x
    Nothing  >>= k   =  Nothing
    return           =  Just
    fail s           =  Nothing
Run Code Online (Sandbox Code Playgroud)

所以Nothing >>= foo很简单Nothing


Pet*_*ter 6

答案在于以下Monad实例的定义Maybe:

instance Monad Maybe where
   (Just x) >>= k      = k x
   Nothing  >>= _      = Nothing
   (Just _) >>  k      = k
   Nothing  >>  _      = Nothing
   return              = Just
Run Code Online (Sandbox Code Playgroud)

您的func''翻译为:

Nothing >>= (\a -> (Just 5 >>= (\b -> return (a+b))))
Run Code Online (Sandbox Code Playgroud)

(>>=)你的定义可以看出,第一个Nothing只是通过线索到结果.


Vit*_*tus 5

我们来看看Maybemonad 的定义.

instance Monad Maybe where
  return = Just

  Just a  >>= f = f a
  Nothing >>= _ = Nothing
Run Code Online (Sandbox Code Playgroud)

并且do在你的函数中desugar -notation:

func' =
  Nothing >>= \a ->
  return a
Run Code Online (Sandbox Code Playgroud)

第一个参数>>=Nothing,从上面的定义我们可以看到,>>=只是忽略了第二个参数.所以我们得到:

func' = Nothing
Run Code Online (Sandbox Code Playgroud)

由于\a -> ...永远不会调用该函数,因此a永远不会被赋值.所以答案是:a甚至没有达成.


至于desugaring do-notation,这里有一个快速描绘它是如何完成的(我做了一个简化 - 处理fail,即不匹配的模式):

do {a; rest} ? a >> do rest
Run Code Online (Sandbox Code Playgroud)

注意,>>通常用>>=as实现a >>= \_ -> do rest(即第二个函数只是忽略参数).

do {p <- a; rest} ? a >>= \p -> do rest

do {let x = a; rest} ? let x = a in do rest
Run Code Online (Sandbox Code Playgroud)

最后:

do {a} = a
Run Code Online (Sandbox Code Playgroud)

这是一个例子:

main = do
  name <- getLine
  let msg = "Hello " ++ name
  putStrLn msg
  putStrLn "Good bye!"
Run Code Online (Sandbox Code Playgroud)

desugars:

main =
  getLine >>= \name ->
  let msg = "Hello " ++ name in
  putStrLn msg >>
  putStrLn "Good bye!"
Run Code Online (Sandbox Code Playgroud)

为了让那些好奇的人完整,这里是"正确"的翻译do {p <- a; rest}(直接来自Haskell报告):

do {pattern <- a; rest} ? let ok pattern = do rest
                              ok _       = fail "error message"
                          in  a >>= ok
Run Code Online (Sandbox Code Playgroud)