我已经定义了一个我想要与Error monad一起使用的自定义错误类型。为了举例,这是一个虚拟的:
newtype CustomError = CustomError String
instance Error CustomError where
strMsg = CustomError
我想定义一个throwCustomError
函数,它的作用类似于throwError
,但不是只抛出给定的字符串,而是使用它来创建CustomError
,然后抛出< EM>那。这个定义有效:
-- | Throws a 'CustomError' containing the given error message.
throwCustomError msg = throwError $ CustomError msg
但是,我想添加一个类型声明,主要是为了让Haddock在生成的文档中包含函数的描述。如果我在GHCI中使用:t
,它告诉我这个函数的类型是MonadError CustomError m => String -> m a
,这对我有意义,但是如果我写的话
throwCustomError :: MonadError CustomError m => String -> m a
GHC抱怨“非变量类型参数”,并告诉我必须使用-XFlexibleContexts
来允许它。为什么我必须使用语言扩展来声明这种类型的函数,当我可以定义这种类型的函数而不使用任何语言扩展?有没有办法在不使用语言扩展的情况下声明此函数的类型?
另外,我最初尝试将函数定义为
throwCustomError = throwError . CustomError
但是GHC告诉我“使用(MonadError CustomError m0)
时没有throwError
的实例”。我不太明白为什么这个定义不等同于另一个定义;就我所见,他们的意思都是一样的。
throwError $ strMsg "foo"
吗? (目前我的代码中都有throwError "foo"
,所以我需要改变这些行。)
答案 0 :(得分:1)
由于您使用的是Error
monad,因此您已经依赖于扩展程序,最明显的是MultiParamTypeClasses
和FunctionalDependencies
,所以我不确定是否有任何意义试图保持你的代码免费扩展。
有一些扩展有一些潜在的令人讨厌的副作用(例如IncoherentInstances
),并且肯定有必要将这些的使用保持在最低限度,但像FlexibleContexts
这样的扩展是完全无害的。