作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
来 self 的 previous question ,我一直在尝试制定一些单子(monad)代码。首先,这是我正在使用的状态机函数:
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 只是“修复”了这个问题,但是我可以做一些更简单的事情来让我抛出错误吗?我宁愿不启用各种编译器扩展。
完整代码 here .
最佳答案
如果您绝对不想使用FlexibleContexts
或NoMonomorphismRestriction
,您可以制作question
和question'
更通用一点,使其在不打开模块中的扩展的情况下编译:
question :: (Error e, MonadError e m) => FSM m
question = FSM question'
question' :: (Error e, MonadError e m) => String -> m (String, FSM m)
question' xs
| last xs == '?' = throwError $ strMsg "Already a question"
| otherwise = return (xs ++ "?", question)
使用 strMsg
让它抛出一个通用的 Error
类型,并指定类型签名。
不过,我还是更喜欢启用 FlexibleContexts
。
关于 haskell "Could not deduce", "Non type-variable argument",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15505683/
我是一名优秀的程序员,十分优秀!