Take the 2-minute tour ×

I've just been trying to wrap my head around free monads; as a learning aid, I've managed to write a Show instance for the following Free type:

{-# LANGUAGE FlexibleContexts, UndecidableInstances #-}

-- Free monad datatype

instance Functor f => Monad (Free f) where
    return = Return
    Return a >>= f = f a

-- Show instance for Free; requires FlexibleContexts and
-- UndecidableInstances
instance (Show (f (Free f a)), Show a) => Show (Free f a) where
    show (Return x) = "Return (" ++ show x ++ ")"
    show (Roll ffx) = "Roll (" ++ show ffx ++ ")"

-- Identity functor with Show instance
newtype Identity a = Id a deriving (Eq, Ord)

instance Show a => Show (Identity a) where
    show (Id x) = "Id (" ++ show x ++ ")"

instance Functor (Identity) where
    fmap f (Id x)= Id (f x)

-- Example computation in the Free monad
example1 :: Free Identity String
example1 = do x <- return "Hello"
              y <- return "World"
              return (x ++ " " ++ y)

The use of UndecidableInstances bothers me somewhat; is there a way to do without it? All that Google yields is this blog post by Edward Kmett, which comfortingly has basically the same Show class definition as I do.

share|improve this question
UndecidableInstances isn't really worrisome. Basically all it does is tell the compiler 'trust me, instance chasing will terminate'. If you got it wrong, the context stack will still stop the compiler from being stuck in an infinite loop. –  Daniel Fischer Jun 4 '12 at 1:05
add comment

1 Answer

up vote 10 down vote accepted

You actually can eliminate the UndecidableInstance requirement for Show here, though you can't do the same thing for Read or Eq.

The trick is to replace the contents of your functor with something you can show more directly, but that you don't tell anyone else about. Consequently, we'll limit our exports to just:

{-# LANGUAGE FlexibleContexts #-}

module Free (Free(..)) where

and bang out a data type for things we can only show.

newtype Showable = Showable (Int -> ShowS)

showable :: Show a => a -> Showable
showable a = Showable $ \d -> showsPrec d a

instance Show Showable where
    showsPrec d (Showable f) = f d

Now, if we never tell anyone about Showable, the only instances for Show (f Showable) will be instances that were polymorphic in the argument to a, constrained at most up to a Show instance. This is sound reasoning as long as the end user isn't actively trying to subvert your code using other extensions. Some hinkiness is possible with the addition of functional dependencies and/or overlapping/undecidable instances but only things that subvert intent, nothing that can cause you to crash.

With that out of the way we can build a decidable Show instance.


instance (Functor f, Show (f Showable), Show a) => Show (Free f a) where
  showsPrec d (Pure a)  = showParen (d > 10) $ showString "Pure " . showsPrec 10 a
  showsPrec d (Free as) = showParen (d > 10) $ showString "Free " . showsPrec 10 (fmap showable as)

The implementation given here doesn't eliminate the need for FlexibleContexts, but you can eliminate that too -- if you really feel the need for Haskell 98 compatibility -- by writing a couple of additional class layers.

I use this trick in a couple of packages -- including my ad package -- to reduce the need for undecidable instances.

share|improve this answer
add comment

Your Answer


