What is the FlexibleContexts extension good for? Could you please explain it using a simple example?

I was trying to understand what the FlexibleContexts extension is doing by searching for web pages that would explain it to mere mortals (people who have read LYHFGG, for example, like me) but I did not find any such resource.

Therefore I ask the experts on the topic: Could you please explain what this extension does, why it exists, and give one or two simple examples how and why one should use it?

Furthermore, If I am reading someone else's code which uses this extension, then what should I know about the extension in order to understand the code written using this extension?


Without FlexibleContexts all typeclass constraints on function definitions must have type variables. For example:

add :: Num a => a -> a -> a 
add = (+)

Where a is the type variable. With FlexibleContexts enabled you can have any type inside a typeclass.

intAdd :: Num Int => Int -> Int -> Int 
intAdd = (+)

This example is pretty contrived but it is the simplest I can think of. FlexibleContexts is usually only used with MultiParamTypeClasses. Here is an example:

class Shower a b where
  myShow :: a -> b

doSomething :: Shower a String => a -> String
doSomething = myShow

Here you can see we say that we only want a Shower a String. Without FlexibleContexts String would have to be a type variable instead of a concrete type.


Commonly it's used with the MultiParamTypeClasses extension, for example when using the mtl library you might write

doSomethingWithState :: MonadState MyState m => m ()
doSomethingWithState = do
    current <- get
    let something1 = computeSomething1 current
        something2 = computeSomething2 current something1
    put something2

And similarly with MonadReader and MonadWriter, along with other similar typeclasses. Without FlexibleContexts you can't use this constraint.

(Note that this answer was based on @DiegoNolan's but rewritten to use an existing library that should make sense to LYAH readers).