packages feed

moffy-0.1.0.0: src/Control/Moffy/Run.hs

{-# LANGUAGE TupleSections #-}
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Control.Moffy.Run (
	-- * Type
	Sig, React, Handle, HandleSt, St,
	-- * Run
	interpret, interpretSt, interpretReact, interpretReactSt ) where

import Control.Monad.Freer.Par (pattern Pure, pattern (:=<<), app)
import Control.Moffy.Internal.Sig.Type (Sig(..), isig)
import Control.Moffy.Internal.React (Adjustable, adjust)
import Control.Moffy.Internal.React.Type (
	React, Rct(..), Handle, HandleSt, liftHandle, St,
	ThreadId, rootThreadId )

---------------------------------------------------------------------------

-- * SIG
-- * REACT

---------------------------------------------------------------------------
-- SIG
---------------------------------------------------------------------------

interpret :: (Monad m, Adjustable es es') =>
	Handle m es' -> (a -> m ()) -> Sig s es a r -> m r
interpret hdl vw rqs = fst <$> interpretSt (liftHandle hdl) vw rqs ()

interpretSt :: (Monad m, Adjustable es es') =>
	HandleSt st m es' -> (a -> m ()) -> Sig s es a r -> St st m r
interpretSt hdl vw = go where
	Sig r `go` st = interpretReactSt hdl r st >>= \(i, st') ->
		isig (pure . (, st')) ((. (`go` st')) . (>>) . vw) i

---------------------------------------------------------------------------
-- REACT
---------------------------------------------------------------------------

interpretReact :: (Monad m, Adjustable es es') =>
	Handle m es' -> React s es r -> m r
interpretReact hdl rqs = fst <$> interpretReactSt (liftHandle hdl) rqs ()

interpretReactSt :: (Monad m, Adjustable es es') =>
	HandleSt st m es' -> React s es r -> St st m r
interpretReactSt hdl (adjust -> r) = runSt hdl r rootThreadId

runSt :: Monad m => HandleSt st m es -> React s es r -> ThreadId -> St st m r
runSt _ (Pure x) _ st = pure (x, st)
runSt _ (_ :=<< Never) _ _ = error "never end"
runSt hdl (c :=<< GetThreadId) t st = runSt hdl (c `app` t) t st
runSt hdl (c :=<< Await rqs) t st =
	hdl rqs st >>= \(o, st') -> runSt hdl (c `app` o) t st'