Monad vs Monad变形金刚

4xx*_*4xx 4 monads haskell monad-transformers

"Monads允许程序员使用顺序构建块来构建计算",因此它允许我们组合一些计算.如果是这种情况,那么为什么以下代码无法运行?

import Control.Monad.Trans.State

gt :: State String String
gt = do
   name <- get
   putStrLn "HI" -- Here is the source of problem!
   put "T"
   return ("hh..." ++ name ++ "...!")


main= do
  print $ execState gt "W.."
  print $ evalState gt "W.."
Run Code Online (Sandbox Code Playgroud)
  • 为什么我们不能将不同的函数放在monad中(如上例所示)?

  • 为什么我们需要一个额外的层,即变换器来组合monad?

4ca*_*tle 8

Monad变换器将不同功能放入monad的机制.

monad只知道如何组合该monad能力范围内的计算.你不能在Statemonad中进行I/O ,但你可以在StateT s IO amonad中进行.但是,您需要liftIO在进行I/O的计算中使用.

import Control.Monad.Trans.State
import Control.Monad.IO.Class (liftIO)

gt :: StateT String IO String
gt = do
   name <- get
   liftIO $ putStrLn "HI"
   put "T"
   return ("hh..." ++ name ++ "...!")


main = do
  print =<< execStateT gt "W.."
  print =<< evalStateT gt "W.."
Run Code Online (Sandbox Code Playgroud)

  • [`execStateT`](http://hackage.haskell.org/package/transformers-0.5.4.0/docs/Control-Monad-Trans-State-Lazy.html#v:execStateT)和[`evalStateT`](http ://hackage.haskell.org/package/transformers-0.5.4.0/docs/Control-Monad-Trans-State-Lazy.html#v:evalStateT)这里都返回一个`IO String`,你可能想要打印他们里面的`String`.[`= <<`](http://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#v:-61--60--60-)调用左边的函数使用右边monad的内部值. (4认同)