----------------------------------------------------------------------------- -- | -- Module : Control.AFSM.SMFunctor -- Copyright : (c) Hanzhong Xu, Meng Meng 2016, -- License : MIT License -- -- Maintainer : hanzh.xu@gmail.com -- Stability : experimental -- Portability : portable ----------------------------------------------------------------------------- -- {-# LANGUAGE InstanceSigs #-} module Control.AFSM.SMFunctor where -- import Prelude hiding ((.)) -- import Data.Functor. import Data.Functor.Compose import Control.Monad import Control.AFSM.CoreType import Control.AFSM.Util -- import Control.AFSM.Core class SMFunctor f where smexec :: SM s a b -> f a -> (SM s a b, f b) smfmap :: SM s a b -> f a -> f b smfmap sm a = snd $ smexec sm a instance SMFunctor [] where smexec sm [] = (sm, []) smexec (SM (TF f) s) (x:xs) = (sm'', b:bs) where (sm', b) = f s x (sm'', bs) = (smexec sm' xs) instance SMFunctor Maybe where smexec sm Nothing = (sm, Nothing) smexec (SM (TF f) s) (Just a) = (sm', Just b) where (sm', b) = f s a -- instance SMFunctor Identity where -- smexec sm a = (sm', Identity b) -- where (sm', b) = step sm (runIdentity a) instance SMFunctor ((->) r) where smexec sm@(SM (TF f) s) ra = (sm, rb) where rb r = snd $ f s (ra r) -- instance SMFunctor (SM s r) where -- smexec sm ra = (sm, absorbRSM ra sm) instance SMFunctor (Either a) where smexec sm (Left a) = (sm, Left a) smexec (SM (TF f) s) (Right b) = (sm', Right c) where (sm', c) = f s b instance SMFunctor ((,) a) where smexec (SM (TF f) s) (a, b) = (sm', (a, c)) where (sm', c) = f s b smexecSM :: SMFunctor f => SM s a b -> SM s (f a) (f b) smexecSM (SM (TF f0) s0') = newSM (f1 f0) s0' where f1 f0 s0 fa = (newSM (f1 f0') s0', fb) where ((SM (TF f0') s0'), fb) = smexec (newSM f0 s0) fa -- Advanced functions smexecSMA :: SMFunctor f => SM s a b -> SM (SM s a b) (f a) (f b) smexecSMA sm = newSM f sm where f sm fa = (newSM f sm', fb) where (sm', fb) = smexec sm fa -- newtype Compose f g a = Compose { getCompose :: f (g a) } instance (SMFunctor f, SMFunctor g) => SMFunctor (Compose f g) where smexec sm fga = (st sm'', Compose fgb) where sm' = smexecSMA sm (sm'', fgb) = smexec sm' $ getCompose fga -- SMMonad bindSM :: (Monad m, SMFunctor m) => m a -> SM s a (m b) -> (SM s a (m b), m b) bindSM ma sm = (sm', join mmb) where (sm', mmb) = smexec sm ma (>>>=) :: (Monad m, SMFunctor m) => m a -> SM s a (m b) -> m b (>>>=) ma sm = join $ smfmap sm ma {- -- require WrappedMonad. class SMMonad m where (>>>=) :: m a -> SM s a (m b) -> (SM s a (m b), m b) instance (Monad m, SMFunctor m) => SMMonad m where (>>>=) ma sm = (sm', join mmb) where (sm', mmb) = smfmap sm ma -}