Skip to content

Instantly share code, notes, and snippets.

@Rufflewind
Created October 8, 2015 08:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Rufflewind/5e4bdb58ca8a171907ec to your computer and use it in GitHub Desktop.
Save Rufflewind/5e4bdb58ca8a171907ec to your computer and use it in GitHub Desktop.

First-class type class instances

Type classes are rather fragile: it's really hard to make changes to a type class once because it can often break code downstream.

Type classes are in a sense like implicit parameters, with the additional constraint of coherency. If we think of them as such, then defining an instance such as

instance Monad Maybe where
  (>>=) = 
  (>>) = 
  return = 

is akin to having a particular anonymous variable blessed by the compiler

instance of ( Monad
              { (>>=) = 
              , (>>) = 
              , return = 
              } :: Monad Maybe )

What if we allowed functions that maps to instances?

defInst_Monad_simple :: Applicative m => (forall a b . m a -> (a -> m b) -> m b) -> Monad m
defInst_Monad_simple bind =
  Monad
  { (>>=) = bind
  , (>>) = \ m k -> m `bind` const k
  , return = pure
  }

instance of (defInst_Monad bindFunc_Maybe :: Monad Maybe)

What if we allowed multiple instances to be defined simultaneously?

defInst_Functor_Applicative_Monad ::  -> (Functor m, Applicative m, Monad m)
defInst_Functor_Applicative_Monad = 

instance of (defInst_Functor_Applicative_Monad  :: (Functor Maybe, Applicative Maybe, Monad Maybe))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment