packages feed

yaftee-0.1.0.0: src/Control/Monad/Yaftee/Eff.hs

{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE BlockArguments, LambdaCase #-}
{-# LAnGUAGE RankNTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Control.Monad.Yaftee.Eff (

	-- * TYPE

	E,

	-- * INJECTION

	eff, effBase, effh,

	-- * PROJECTION

	run, runM, 

	-- * HANDLE RELAY

	handleRelay, handleRelayS, interpose

	) where

import Control.Monad.Fix
import Control.Monad.HigherFreer qualified as HFreer
import Control.HigherOpenUnion qualified as Union
import Data.HigherFunctor qualified as HFunctor
import Data.FTCQueue qualified as Q

type E effs = HFreer.H (Union.U effs)

eff :: Union.Member (Union.FromFirst t) effs => t a -> E effs i o a
eff = (HFreer.:>>= Q.singleton HFreer.Pure) . Union.inj

effBase :: Union.Base (Union.FromFirst t) effs => t a -> E effs i o a
effBase = (HFreer.:>>= Q.singleton HFreer.Pure) . Union.injBase

effh :: Union.Member h effs => h (E effs) i o a -> E effs i o a
effh = (HFreer.:>>= Q.singleton HFreer.Pure) . Union.injh

run :: E '[] i o a -> a
run (HFreer.Pure x) = x
run _ = error "bad"

runM :: Monad m => E '[Union.FromFirst m] i o a -> m a
runM (HFreer.Pure x) = pure x
runM (u HFreer.:>>= q) = runM . (q HFreer.$) =<< Union.extract u

handleRelay :: forall f t effs i o a .
	HFunctor.Loose (Union.U effs) =>
	(forall x . x -> f x) -> (forall x . f x -> x) ->
	(forall x i' o' y . t x -> (x -> E effs i' o' (f y)) -> E effs i' o' (f y)) ->
	E ((Union.FromFirst t) ': effs) i o a -> E effs i o (f a)
handleRelay mk gx h = fix \go -> \case
	HFreer.Pure x -> HFreer.Pure $ mk x
	u HFreer.:>>= q -> case Union.decomp u of
		Left u' -> HFunctor.map (handleRelay mk gx h) mk u' HFreer.:>>=
			Q.singleton \x -> go $ q HFreer.$ gx x
		Right (Union.FromFirst x k) -> h x ((go HFreer.. q) . k)

handleRelayS :: forall f s t effs i o a .
	HFunctor.Loose (Union.U effs) =>
	(forall x . s -> x -> f s x) ->
	(forall x . f s x -> s) -> (forall x . f s x -> x) ->
	(forall x i' o' y .
		t x -> (x -> s -> E effs i' o' y) -> s -> E effs i' o' y) ->
	E ((Union.FromFirst t) ': effs) i o a -> s -> E effs i o (f s a)
handleRelayS mk gs gx h m s0 = ($ m) . ($ s0) $ fix \go s -> \case
	HFreer.Pure x -> HFreer.Pure $ mk s x
	u HFreer.:>>= q -> case Union.decomp u of
		Left u' -> HFunctor.map
				(flip (handleRelayS mk gs gx h) s) (s `mk`) u'
			HFreer.:>>= Q.singleton \xs ->
				go (gs xs) $ q HFreer.$ gx xs
		Right (Union.FromFirst x k) ->
			h x (\x' s' -> (go s' HFreer.. q) . k $ x') s

interpose :: forall eff effs i o a b .
	Union.Member (Union.FromFirst eff) effs =>
	(a -> E effs i o b) ->
	(forall v . eff v -> (v -> E effs i o b) -> E effs i o b) -> E effs i o a -> E effs i o b
interpose ret h = fix \go -> \case
	HFreer.Pure x -> ret x
	u HFreer.:>>= q -> case Union.prj u of
		Just (Union.FromFirst x k) -> h x ((go HFreer.. q) . k)
		_ -> u HFreer.:>>= Q.singleton (go HFreer.. q)