impl-0.2.0.0: example/Monad/Impl.hs
{-# language UndecidableInstances #-} -- Only needed for ++ idiom
module Monad.Impl (module X) where
import Data.Maybe
import Impl as X
import Control.Monad.Fail
import GHC.Err
instance Impl Functor where
type Methods Functor = [Required "fmap", Optional "constMap"]
impl f (arg #fmap -> fmap) (Arg' constMap') = case constMap' of
Nothing -> [d|instance Functor $f where fmap = $fmap|]
Just constMap -> [d|instance Functor $f where fmap = $fmap;(<$) = $constMap|]
instance Impl Applicative where
type Methods Applicative = '[Required "pure", Required "ap"] ++ Methods Functor
impl f (arg #pure -> pure) (arg #ap -> ap) fmap constMap
= concat <$> sequence
[impl @Functor f fmap constMap
,[d|instance Applicative $f where
pure = $pure
(<*>) = $ap |]
]
instance Impl Monad where
type Methods Monad = '[Required "return",Required "bind", Optional "fail", Optional "fmap", Optional "constMap"]
impl m (arg #return -> return)
(arg #bind -> bind)
(arg' #fail [|errorWithoutStackTrace|] -> fail)
(Arg' fmap')
constMap'
= concat <$> sequence
[impl @Applicative m
$$ #pure return
$$ #ap [|\mf ma -> $bind mf $ \f -> $bind ma $ \a -> $return (f a) |]
$$ #fmap (fromMaybe [|\f ma -> $bind ma $ \a -> $return (f a)|] fmap')
$ constMap'
,[d|instance Monad $m where
return = $return
(>>=) = $bind
fail = $fail |]
]