我以下這個教程「由步驟單子變壓器步驟」WriterT單子變壓器
http://www.cs.virginia.edu/~wh5a/personal/Transformers.pdf
和從第2.5節
type Name = String
data Exp = Lit Integer
| Var Name
| Plus Exp Exp
| Abs Name Exp
| App Exp Exp
deriving (Show)
data Value = IntVal Integer
| FunVal Env Name Exp
deriving (Show)
type Env = Map.Map Name Value
type Eval5 a = ReaderT Env (ErrorT String
(WriterT [String] (StateT Integer Identity))) a
runEval5 :: Env -> Integer -> Eval5 a -> ((Either String a, [String]), Integer)
runEval5 env st ev =
runIdentity (runStateT (runWriterT (runErrorT (runReaderT ev env))) st)
eval5 :: Exp -> Eval4 Value
eval5 (Lit i) = do tick
return $ IntVal i
eval5 (Var n) = do tick
tell [n]
env <- ask
case Map.lookup n env of
Nothing -> throwError("unbound variable: " ++ n)
Just val -> return val
eval5 (Plus e1 e2) = do tick
e1' <- eval5 e1
e2' <- eval5 e2
case (e1', e2') of
(IntVal i1, IntVal i2) ->
return $ IntVal $ i1 + i2
_ -> throwError "type error in Plus"
eval5 (Abs n e) = do tick
env <- ask
return $ FunVal env n e
eval5 (App e1 e2) = do tick
val1 <- eval5 e1
val2 <- eval5 e2
case val1 of
FunVal env' n body ->
local (const $ Map.insert n val2 env')
$ eval5 body
_ -> throwError "type error in App"
在eval5函數的代碼失敗,該消息來編譯:
No instance for (MonadWriter [Name] Identity)
arising from a use of `tell'
Possible fix:
add an instance declaration for (MonadWriter [Name] Identity)
In a stmt of a 'do' block: tell [n]
In the expression:
do { tick;
tell [n];
env <- ask;
case Map.lookup n env of {
Nothing -> throwError ("unbound variable: " ++ n)
Just val -> return val } }
In an equation for `eval5':
eval5 (Var n)
= do { tick;
tell [n];
env <- ask;
.... }
GHC版本7.6.3
注意:你可能想[避免使用'WriterT [String]'](http://www.haskellforall.com/2014/02/streaming-logging.html)。 –
我幾天前就讀過這篇博文,感謝:-) –
不客氣! –