Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non type-variable argument in the constraint: MonadError Failure m

I have defined a custom error type:

data Failure = NetworkError Message |
               UserIsTooStupid Message |
               InvalidOperation Message |
               UnexpectedError Message
type Message = String

I am trying to use MonadError with my error type:

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

In other words, this function can return any monad which satisfies both MonadIO and MonadError, but the only type of error it can throw is Failure.

This fails to compile, with the error message:

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 wants me to turn on the FlexibleContexts language extension to make this code work. What does FlexibleContexts do, and is it really necessary in my case? I prefer not to turn on language extensions willy-nilly without knowing whether I need them.

The function compiles fine if I leave off the type signature, but I prefer not to do that.

like image 500
Benjamin Hodgson Avatar asked Apr 01 '14 20:04

Benjamin Hodgson


1 Answers

Haskell 98 doesn't allow constraints that looks like MonadError Failure m, they have to look like MonadError a m. The ability to have constraints like that was added to GHC however, which is what that extension does. I understand being wary of language extensions, but FlexibleContexts is pretty harmless.

I believe at the time Haskell 98 came out, the type theory to use constraints like that hadn't been developed, but since then it has. The extension turns on some extra code in the type checker which uses that theory. If you google around a little you might be able to find a paper on how it works.

like image 141
Dan Avatar answered Oct 12 '22 13:10

Dan