定义一个函数而不使用任何语言扩展,但必须使用语言扩展来声明其类型?

时间:2012-02-10 05:51:35

标签: haskell types error-handling monads

我已经定义了一个我想要与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",所以我需要改变这些行。)

1 个答案:

答案 0 :(得分:1)

由于您使用的是Error monad,因此您已经依赖于扩展程序,最明显的是MultiParamTypeClassesFunctionalDependencies,所以我不确定是否有任何意义试图保持你的代码免费扩展。

有一些扩展有一些潜在的令人讨厌的副作用(例如IncoherentInstances),并且肯定有必要将这些的使用保持在最低限度,但像FlexibleContexts这样的扩展是完全无害的。