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

标签 haskell types error-handling monads

我定义了一个自定义错误类型,我想将其与错误单子(monad)一起使用。为了举例,这里有一个虚拟的:

newtype CustomError = CustomError String
instance Error CustomError where
  strMsg = CustomError

我想定义一个 throwCustomError 函数,其工作方式类似于 throwError,但它不只是抛出给定的字符串,而是使用它来创建一个 CustomError,然后抛出那个。这个定义有效:

-- | 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 告诉我“没有因使用 throwError 而产生的 (MonadError CustomError m0) 实例”。我不太明白为什么这个定义与另一个定义不等价;据我所知,它们的含义相同。

<小时/>

退后一步:我是否应该定义这个函数?或者当我想抛出错误时我应该只写 throwError $ strMsg "foo" 吗? (目前我的代码中有 throwError "foo" ,所以我需要以任何方式更改这些行。)

最佳答案

由于您正在使用 Error monad,你已经依赖扩展了,最值得注意的是 MultiParamTypeClassesFunctionalDependencies ,所以我不确定尝试保持代码无扩展是否有任何意义。

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

关于haskell - 定义一个函数时不使用任何语言扩展,但必须使用语言扩展来声明其类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9223338/

相关文章:

haskell - 有状态版本的 map (Haskell)

Haskell 复杂函数组合

php - 即使session_start()已经在最前面,“session_start(): Cannot send session cache limiter - headers already sent”仍会继续出现

python - 在不中断程序的情况下在 Python 中发出警告

error-handling - 尝试附加自动命名的数据库文件****失败

haskell:调试 <<loop>> 异常

haskell - 定义增量环境而不会遇到重叠实例

types - 为什么我的类型定义在声明为变体时被拒绝为循环,但在其他情况下被接受?

Haskell 单子(monad) IO

haskell - 列表理解和类型问题 (Haskell)