我跟随它的类型和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
等等,但我还没有编写可编译的程序......
答案 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