Я определил пользовательский тип ошибки:
data Failure = NetworkError Message |
UserIsTooStupid Message |
InvalidOperation Message |
UnexpectedError Message
type Message = String
Я пытаюсь использовать MonadError
с моим типом ошибки:
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
Другими словами, эта функция может возвращать любую монаду, которая удовлетворяет как MonadIO
, так и MonadError
, но единственный тип ошибки, которую он может выбросить, - Failure
.
Это не скомпилируется с сообщением об ошибке:
Non type-variable argument in the constraint: MonadError Failure m
(Use -XFlexibleContexts to permit this)
In the type signature for `loadJSON':
loadJSON :: (Aeson.FromJSON v, MonadIO m, MonadError Failure m) =>
URI -> m v
GHC хочет, чтобы я включил расширение языка FlexibleContexts
, чтобы этот код работал. Что делает FlexibleContexts
, и действительно ли это необходимо в моем случае? Я предпочитаю не включать языковые расширения волей-неволей, не зная, нужны ли они мне.
Функция компилируется отлично, если я не могу оставить подпись типа, но я не хочу этого делать.