【问题标题】:How does this particular use of MaybeT work?MaybeT 的这种特殊用途是如何工作的?
【发布时间】:2014-04-17 17:53:26
【问题描述】:

我正在尝试了解 monad 转换器,并且正在阅读 haskell wiki 上的 this page

我很困惑的代码如下:

isValid :: String -> Bool
isValid s = length s >= 5

getValidPassword :: MaybeT IO String
getValidPassword = do s <- lift getLine
                      guard (isValid s)
                      return s

askPassword :: MaybeT IO ()
askPassword = do lift $ putStrLn "Insert your new password:"
                 value <- getValidPassword
                 lift $ putStrLn "Storing in database..."

到目前为止一切顺利。我可以运行它并且它有效。但是现在,将askPassword 更改为:

askPassword :: MaybeT IO ()
askPassword = do lift $ putStrLn "Insert your new password:"
                 value <- msum $ repeat getValidPassword
                 lift $ putStrLn "Storing in database..."

如果不满足有效性条件,这将反复等待我提供新的输入。我有点迷失它是如何做到的。 repeat 永远重复这个动作,而msum 只是foldr mplus mzero,这意味着它沿着列表走并将值“添加”在一起。

为什么当我输入错误时这不立即返回(返回值将是 Nothing)。我想我没有看到决定何时停止和何时继续的逻辑嵌入在哪里。谢谢你的帮助。

【问题讨论】:

    标签: haskell


    【解决方案1】:

    好吧,Maybemsum 应该在第一次成功尝试时停止,而不是第一次失败。

    【讨论】:

      【解决方案2】:

      之所以有效,是因为 MaybeT 的 mplus 在其第二个参数中是非严格的:

      mplus (return () :: MaybeT m ()) undefined
      

      等价于

      return ()
      

      这是the definition of mplus for MaybeT 的结果,如下所示:

      instance (Monad m) => MonadPlus (MaybeT m) where
        mzero = MaybeT (return Nothing)
        mplus x y = MaybeT $ do v <- runMaybeT x
                                case v of
                                  Nothing -> runMaybeT y
                                  Just _  -> return v
      

      如你所见,mplus的第二个参数y不会被执行,除非第一个参数x没有返回结果。

      因此,从repeat getPassword 获得的无限操作列表中的msum 只会执行到第一个操作成功。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-10-15
        • 2020-12-23
        • 2011-08-08
        • 2012-07-08
        • 2011-11-02
        • 1970-01-01
        • 2013-03-21
        相关资源
        最近更新 更多