【问题标题】:Haskell "Could not deduce", "Non type-variable argument"Haskell“无法推断”,“非类型变量参数”
【发布时间】:2013-03-20 04:20:29
【问题描述】:

通过我的previous question,我一直在尝试编写一些单子代码。首先,这是我正在使用的状态机函数:

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 是一个非常无害的扩展。没有必要害怕这一点。如果没有类型签名,如果禁用单态限制,它也会编译。
  • 如果不需要扩展,对扩展有点不利。我宁愿寻找一种替代方法,例如重组代码。解决方案 1 是 Fl​​exibleContexts。还有其他建议吗?
  • 或多或少,您将获得的所有解决方案都将是“打开FlexibleContexts”。不要害怕扩展,它们会为您提供帮助。而这个并不神秘。它是专门让你做你想做的事。不多也不少。

标签: haskell types


【解决方案1】:

如果您绝对不想使用FlexibleContextsNoMonomorphismRestriction,您可以使questionquestion' 更通用一点,以便在不打开模块中的扩展的情况下使其编译:

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

【讨论】:

    【解决方案2】:

    细说大牛的回答,他的解决方案其实是避免FlexibleContexts的通用解决方案。

    任何时候你都有这样的约束:

    (SomeTypeConstructor SomeType) => ...
    

    ...其中SomeType 是触发FlexibleInstances 警告的具体类型,您始终可以通过对要在SomeType 上使用的操作进行类型分类来解决FlexibleContexts,例如:

    class IsSomeType t where
        get :: t -> SomeType
        set :: SomeType -> t -> t
    

    ...然后将IsSomeType 合并到您的约束中:

    (IsSomeType t, SomeTypeConstructor t) => ...
    

    ...并且只使用IsSomeType中的方法。

    【讨论】:

      猜你喜欢
      • 2016-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-10
      • 2017-08-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多