Haskell 未使用任何语言扩展定义函数,但必须使用语言扩展来声明其类型?
我已经定义了一个自定义的错误类型,我想与错误monad一起使用。举个例子,这里有一个虚拟的:Haskell 未使用任何语言扩展定义函数,但必须使用语言扩展来声明其类型?,haskell,types,error-handling,monads,Haskell,Types,Error Handling,Monads,我已经定义了一个自定义的错误类型,我想与错误monad一起使用。举个例子,这里有一个虚拟的: newtype CustomError = CustomError String instance Error CustomError where strMsg = CustomError 我想定义一个类似于throwError的throwCustomError函数,但它不只是抛出给定的字符串,而是使用它创建一个CustomError,然后抛出它。这一定义适用于: -- | Throws a 'C
newtype CustomError = CustomError String
instance Error CustomError where
strMsg = CustomError
我想定义一个类似于throwError
的throwCustomError
函数,但它不只是抛出给定的字符串,而是使用它创建一个CustomError
,然后抛出它。这一定义适用于:
-- | Throws a 'CustomError' containing the given error message.
throwCustomError msg = throwError $ CustomError msg
但是,我想添加一个类型声明,主要是为了让Haddock在生成的文档中包含函数的描述。如果我在GHCI中使用:t
,它会告诉我该函数的类型是MonadError CustomError m=>String->ma
,这对我来说是有意义的,但如果我编写
throwCustomError :: MonadError CustomError m => String -> m a
GHC抱怨“非变量类型参数”,并告诉我必须使用-XFlexibleContexts
来允许它。为什么我必须使用语言扩展来声明这种类型的函数,而我可以在不使用任何语言扩展的情况下定义这种类型的函数?有没有一种方法可以在不使用语言扩展的情况下声明此函数的类型
另一方面,我最初尝试将函数定义为
throwCustomError = throwError . CustomError
但GHC告诉我,“没有任何实例表明使用投掷器产生的(MonadError CustomError m0)
”。我不太明白为什么这个定义不等同于另一个定义;就我所知,它们都是同一个意思
退一步:我甚至应该费心定义这个函数吗?或者当我想抛出错误时,我应该只写throwerr$strMsg“foo”
?(目前我的代码中有throwError“foo”
,因此我需要以任何方式更改这些行。)由于您使用的是错误
monad,您已经依赖扩展,最明显的是多ramtypeclass
和函数依赖性
,所以我不确定让你的代码扩展免费有什么意义
有一些扩展具有一些潜在的不良副作用(例如,不连贯性
),将它们的使用保持在最低限度当然是有意义的,但是像FlexibleContexts
这样的扩展是完全无害的。您的最后一个示例嗅到了单态限制的味道。尝试禁用它或添加类型签名。目前,我在编译代码时不必使用任何-X
选项,这是我想要保留的。我不太关心通过Haskell平台中的库“免费”获得的扩展。奇怪的是,我试过{-#LANGUAGE FlexibleContexts}
,但似乎不起作用,但我刚才又试了一次,结果成功了。