haskell当函数没有返回IO monad时如何打印?

时间:2014-05-24 02:31:51

标签: haskell io monads

我跟随它的类型和monad:

data Err a = Ok a | Bad String
  deriving (Read, Show, Eq, Ord)

instance Monad Err where
  return      = Ok
  fail        = Bad
  Ok a  >>= f = f a
  Bad s >>= f = Bad s

instance Functor Err where
  fmap = liftM

我的功能还有打印" asdf"屏幕并以错误结束(这是调试的临时解决方案):

runStatments :: [Stm] -> State -> Err State
runStatments [] state = Ok state
runStatments (s:_) state = case s of
  PrintStmt exp -> do {
    e <- evalExpression exp state;
    k <- Ok $putStrLn "asfd";
    Bad "damn!"
  }
  ...

问题是代码没有打印&#34; asdf&#34;在屏幕上......

对于这样的问题,什么是温和的解决方案?我已经尝试了liftIO等等,但我还没有编写可编译的程序......

1 个答案:

答案 0 :(得分:3)

你不能只是&#34; jam&#34; IO进入monad而没有在某些时候冒泡。你需要做的就是将Err monad包裹在IO monad周围,并将其称为monad transformer。

这样的东西
import Control.Monad
import Control.Monad.Trans

-- If you don't like `Either`, you can change it to
-- Err
data ErrT m a = ErrT {runErrT :: m (Either String a)}

instance (Monad m, Functor m) => Monad (ErrT m) where
  return = ErrT . return . Right
  (ErrT m) >>= f = ErrT $ do
      val <- m
      case val of
          Left err -> return  $ Left err
          Right a  -> runErrT $ f a

instance MonadTrans ErrT where
  lift = ErrT . liftM Right

然后你可以做这样的事情

test :: ErrT IO ()
test = lift $ putStrLn "Hello World"

main = runErrT test