packages feed

linear-free-0.1.1.0: src/Control/Linear/Monad/Free/Church.hs

{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

module Control.Linear.Monad.Free.Church (
  F (..),
  runF,
  improve,
  fromF,
  iter,
  iterM,
  toF,
  retract,
  hoistF,
  foldF,
  liftF,
) where

import qualified Control.Functor.Linear as Control
import Control.Linear.Monad.Free (Free (..), MonadFree (..))
import qualified Data.Functor.Linear as Data
import GHC.Num.Integer ()
import Prelude.Linear
import qualified Prelude.Linear as L

newtype F f a where
  F :: (forall r. (a %1 -> r) %1 -> (f r %1 -> r) -> r) %1 -> F f a

runF :: F f a %1 -> (a %1 -> r) %1 -> (f r %1 -> r) -> r
runF (F m) p b = m p b

instance Data.Functor f => Data.Functor (F f) where
  fmap f (F m) = F (\p b -> m (p . f) b)

instance Data.Functor f => Control.Functor (F f) where
  fmap f (F m) = F (\p b -> m (p . f) b)

instance Data.Functor f => Data.Applicative (F f) where
  {-# INLINE pure #-}
  pure x = F (\p _ -> p x)

  F f <*> F g = F (\p b -> f (\a -> g (p L.. a) b) b)

instance Data.Functor f => Control.Applicative (F f) where
  {-# INLINE pure #-}
  pure x = F (\p _ -> p x)

  F f <*> F g = F (\p b -> f (\a -> g (p L.. a) b) b)

instance Data.Functor f => Control.Monad (F f) where
  F m >>= f = F (\p b -> m (\x -> runF (f x) p b) b)

instance Control.Functor f => MonadFree f (F f) where
  wrap f = F (\p b -> b (Control.fmap (\(F m) -> m p b) f))

instance (Control.Functor f, Data.Traversable f) => Data.Traversable (F f) where
  traverse f m = runF m (Data.fmap Control.return . f) (Data.fmap wrap . Data.sequenceA)

improve ::
  forall f a.
  Control.Functor f =>
  (forall m. MonadFree f m => m a) %1 ->
  Free f a
improve f = fromF @_ @f f

fromF :: forall m f a. MonadFree f m => F f a %1 -> m a
fromF (F m) = m Control.return wrap

iter :: (f a %1 -> a) -> F f a %1 -> a
iter f (F m) = m id f

iterM :: Control.Applicative m => (f (m a) %1 -> m a) -> F f a %1 -> m a
iterM f (F m) = m Control.pure f

toF :: Control.Functor f => Free f a %1 -> F f a
toF (Pure x) = F (\p _ -> p x)
toF (Free f) = wrap (toF Control.<$> f)

retract :: Control.Monad m => F m a %1 -> m a
retract (F m) = m Control.pure Control.join

hoistF :: (forall x. f x %1 -> g x) -> F f a %1 -> F g a
hoistF f (F m) = F (\p b -> m p (\x -> b (f x)))

foldF :: Control.Monad m => (forall x. f x %1 -> m x) -> F f a %1 -> m a
foldF f (F m) = m Control.pure (\x -> Control.join $ f x)

liftF :: (Data.Functor f, MonadFree f m) => f a %1 -> m a
liftF x = wrap (Control.pure Data.<$> x)