从我之前的问题中,我一直在尝试制定一些单子代码。首先,这是我正在使用的状态机功能:
import Control.Monad
import Control.Monad.Error
newtype FSM m = FSM { unFSM :: String -> m (String, FSM m) }
fsm f [] = return []
fsm f (r:rs) = do
(xs, f') <- unFSM f r
liftM (xs:) (fsm f' rs)
现在,这编译得很好:
exclaim :: (Monad m) => FSM m
exclaim = FSM exclaim'
exclaim' xs = return (xs ++ "!", exclaim)
但这不是,因为类型声明:
question :: (MonadError String m) => FSM m
question = FSM question'
question' xs
| last xs == '?' = throwError "Already a question"
| otherwise = return (xs ++ "?", question)
错误是Non type-variable argument
,我认为是指String
之后MonadError
。如果我删除类型声明,我会得到Could not deduce
。我知道启用 FlexibleContexts 只是“修复”了这个问题,但是我可以做一些更简单的事情来让我抛出错误吗?我宁愿不启用各种编译器扩展。
完整代码在这里。