Haskell 约束中的非类型变量参数:MonadError失败m

Haskell 约束中的非类型变量参数:MonadError失败m,haskell,monad-transformers,Haskell,Monad Transformers,我已定义自定义错误类型: data Failure = NetworkError Message | UserIsTooStupid Message | InvalidOperation Message | UnexpectedError Message type Message = String loadJSON :: (Aeson.FromJSON v, MonadIO m, MonadError F

我已定义自定义错误类型:

data Failure = NetworkError Message |
               UserIsTooStupid Message |
               InvalidOperation Message |
               UnexpectedError Message
type Message = String
loadJSON :: (Aeson.FromJSON v, MonadIO m, MonadError Failure m) => URI -> m v
loadJSON uri = do
    body <- liftIO $ getResponseBody =<< simpleHTTP (getRequest uri)
    case Aeson.decode body of
         Just json -> return json
         Nothing -> throwError $ SerialisationError "Couldn't deserialise from JSON"

type URI = String
我正在尝试与我的错误类型一起使用:

data Failure = NetworkError Message |
               UserIsTooStupid Message |
               InvalidOperation Message |
               UnexpectedError Message
type Message = String
loadJSON :: (Aeson.FromJSON v, MonadIO m, MonadError Failure m) => URI -> m v
loadJSON uri = do
    body <- liftIO $ getResponseBody =<< simpleHTTP (getRequest uri)
    case Aeson.decode body of
         Just json -> return json
         Nothing -> throwError $ SerialisationError "Couldn't deserialise from JSON"

type URI = String
GHC希望我打开
FlexibleContexts
语言扩展以使此代码正常工作。
FlexibleContexts
做了什么,在我的情况下真的有必要吗?我不喜欢在不知道是否需要语言扩展的情况下随意打开它们


如果我不使用类型签名,函数的编译效果很好,但我不希望这样做。

Haskell 98不允许出现类似于
MonadError Failure m
的约束,它们必须看起来像
MonadError a m
。然而,GHC增加了具有类似约束的能力,这就是扩展所做的。我理解对语言扩展持谨慎态度,但flexiblecontext是无害的


我相信在Haskell 98问世的时候,使用这种约束的类型理论还没有发展出来,但从那时起它已经发展起来了。扩展在使用该理论的类型检查器中打开一些额外的代码。如果你在谷歌上搜索一下,你可能会找到一篇关于它是如何工作的论文。

你能详细介绍一下语言扩展的功能吗?在什么意义上它是无害的?为什么Haskell 98不允许这样的类型签名?从某种意义上说,它是无害的,因为它不会改变不使用该扩展的程序的含义,并为使用该扩展的程序赋予“合理”的含义。其他一些扩展,例如
不连贯性
,被认为是潜在的有害扩展,因为利用它们的程序具有复杂的语义,因此它们很难推理。