从我的previous question,我一直在试图找出一些单子代码。首先,这里是我使用一个状态机功能:Haskell“无法推论”,“非类型变量参数”
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
,我认为这是MonadError
后面的String
。如果我删除了类型声明,则代替Could not deduce
。我明白启用FlexibleContexts只是“修复”这个,但是有没有更简单的方法可以让我抛出错误?我宁愿不启用各种编译器扩展。
Full code here。
'FlexibleContexts'是一个非常无害的扩展。没必要害怕这一点。如果没有类型签名,它还会编译您是否禁用单态限制。 – 2013-03-19 17:06:14
如果不需要扩展,只是对扩展有点不利。我宁愿寻找替代方法,例如重构代码。解决方案1是FlexibleContexts。还有其他建议吗? – me2 2013-03-19 17:51:09
或多或少,你要得到的所有解决方案都将是“打开FlexibleContexts”。不要害怕扩展,他们会帮助你。而这一个并不神秘。这是专门让你做你想做的。没有更多,没有更多。 – Carl 2013-03-19 18:05:24