packages feed

functor-monad-0.1.1.0: src/FMonad/Cont/Exp.hs

{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE ScopedTypeVariables #-}
module FMonad.Cont.Exp(
  Cont(..)
) where

import FFunctor
import FMonad

import Data.Functor.Exp

-- | \"Continuation monad\" using 'Exp1'.
newtype Cont k f a = Cont { runCont :: ((f `Exp1` k) `Exp1` k) a }
    deriving Functor

flmap :: (f ~> g) -> Exp1 g h ~> Exp1 f h
flmap fg gh = Exp1 $ \f ar -> unExp1 gh (fg f) ar

instance FFunctor (Cont k) where
  ffmap gh (Cont gkk) = Cont $ flmap (flmap gh) gkk

unit :: Functor g => g ~> ((g `Exp1` k) `Exp1` k)
unit gx = Exp1 $ \gk ar -> unExp1 gk (ar <$> gx) id

instance FMonad (Cont k) where
  fpure :: Functor g => g ~> Cont k g
  fpure gx = Cont (unit gx)

  fbind :: forall g h a. (Functor g, Functor h) => (g ~> Cont k h) -> Cont k g a -> Cont k h a
  fbind rest (Cont gkk) =
    let hkkkk :: ((((h `Exp1` k) `Exp1` k) `Exp1` k) `Exp1` k) a
        hkkkk = flmap (flmap (runCont . rest)) gkk

        hkk = flmap unit hkkkk
    in Cont hkk