    sig Monad where
      type t : * -> *
      return : a -> t a
      bind   : t a -> (a -> t b) -> t b
    
    return : { M : Monad } -> a -> M.t a
    return x = M.return x
    
    (>>=) : { M : Monad } -> M.t a -> (a -> M.t b) -> M.t b
    (>>=) x f = M.bind x f
    
    map : { M : Monad } -> M.t a -> (a -> b) -> Mt. b
    map m f = m >>= (\ x -> return (f x))
    
    join : { M : Monad } -> M.t (M.t a) -> M.t a
    join m = m >>= id
    
    unless : { M : Monad } -> Bool -> M.t () -> M.t ()
    unless True  _ = return ()
    unless False m = m
    
    implicit struct MonadOpen where
      type t a = Option a
      return = Some
      bind (Some x) f = f x
      bind None     _ = None
    
    implicit struct MonadList where
      type t a = List a
      return x = [x]
      bind x f = concat (map f x)
