首页 > 解决方案 > 如何避免 MaybeT 中的提升以及为什么最终验证无效?

问题描述

我们如何避免——如果这样做有意义的话..——使用liftin MaybeT

wikibooks中的经典示例。

给定

isValid :: String -> Bool
isValid s = length s >= 8
            && any isAlpha s
            && any isNumber s
            && any isPunctuation s

我们有

getPassphrase :: MaybeT IO String
getPassphrase = do s <- lift getLine
                   guard (isValid s) -- Alternative provides guard.
                   return s

askPassphrase :: MaybeT IO ()
askPassphrase = do lift $ putStrLn "Insert your new passphrase:"
                   value <- getPassphrase
                   lift $ putStrLn "Storing in database..."

我试过的

我想我需要使用askand tell,所以我将代码转换如下:

getPassphrase :: MaybeT (ReaderT String IO) String
getPassphrase = do 
        s <- ask
        guard (isValid s) -- Alternative provides guard.
        return s

askPassphrase :: MaybeT (ReaderT String IO) ()
askPassphrase = do 
  -- _ <- tell "Insert your new passphrase:"
  value <-  getPassphrase
  -- _ <- tell "Storing in database..."
  return ()



main :: IO (Maybe ())
main =
  runReaderT (runMaybeT askPassphrase) "test123!"

该字符串"test123!"产生Just()while"test123"返回Nothing,因此 IMO它确实按预期工作,但我仍然必须包含 Writer。

如果我做

askPassphrase :: MaybeT (ReaderT String (WriterT String IO)) ()
askPassphrase = do 
  _ <- tell "Insert your new passphrase:"
  let value =  getPassphrase
  _ <- tell "Storing in database..."
  return ()



main :: IO ()
main =
  execWriterT (runReaderT (runMaybeT askPassphrase) "test123!") >>= putStrLn

它编译并运行但出现问题,因为任何字符串都被认为是有效的,我的意思是我总是"Insert your new passphrase:Storing in database..."在输出中看到。我错过了什么?

标签: haskellmonadsmonad-transformersmaybe

解决方案


我只需要使用:t命令找到我的函数的正确类型,然后指定它们,它们是

getPassphrase :: MaybeT (ReaderT String (WriterT String IO)) [Char]
getPassphrase = do

askPassphrase :: MaybeT (ReaderT String (WriterT String IO)) ()
askPassphrase = do 

并且lift可以避免!(在问题的第二部分ask已经没有了)lift

askPassphrase = do 
  tell "Insert your new passphrase:"
  value <-  getPassphrase
  tell "Storing in database..."

在线版本在这里


推荐阅读