module Generics.Pointless.Observe.Functors where
import Generics.Pointless.Combinators
import Generics.Pointless.Functors
import Debug.Observe
import Data.Typeable
import Prelude hiding (Functor(..))
instance Typeable One where
typeOf _ = (mkTyCon "One") `mkTyConApp` []
class FunctorO f where
functorOf :: Fix f -> String
watch :: Fix f -> x -> Rep f x -> String
fmapO :: Fix f -> (x -> ObserverM y) -> Rep f x -> ObserverM (Rep f y)
instance FunctorO Id where
functorOf _ = "Id"
watch _ _ _ = ""
fmapO _ f x = f x
instance (Typeable a,Observable a) => FunctorO (Const a) where
functorOf _ = "Const " ++ show (typeOf (_L::a))
watch _ _ _ = ""
fmapO _ f x = thunk x
instance (FunctorO f, FunctorO g) => FunctorO (f :+: g) where
functorOf _ = "(" ++ functorOf (_L::Fix f) ++ ":+:" ++ functorOf (_L::Fix g) ++ ")"
watch _ _ (Left _) = "Left"
watch _ _ (Right _) = "Right"
fmapO _ f (Left x) = fmapO (_L::Fix f) f x >>= return . Left
fmapO _ f (Right x) = fmapO (_L::Fix g) f x >>= return . Right
instance (FunctorO f, FunctorO g) => FunctorO (f :*: g) where
functorOf _ = "(" ++ functorOf (_L::Fix f) ++ ":*:" ++ functorOf (_L::Fix g) ++ ")"
watch _ _ _ = ""
fmapO _ f (x,y) = do x' <- fmapO (_L :: Fix f) f x
y' <- fmapO (_L::Fix g) f y
return (x',y')
instance (FunctorO g, FunctorO h) => FunctorO (g :@: h) where
functorOf _ = "(" ++ functorOf (_L::Fix g) ++ ":@:" ++ functorOf (_L::Fix h) ++ ")"
watch _ (x::x) a = watch (_L::Fix g) (_L::Rep h x) a
fmapO _ f x = fmapO (_L::Fix g) (fmapO (_L::Fix h) f) x
omap :: FunctorO (PF a) => a -> (x -> ObserverM y) -> F a x -> ObserverM (F a y)
omap (_::a) f = fmapO (_L::Fix (PF a)) f
instance Observable One where
observer = observeBase
instance Observable I where
observer FixId = send "" (fmapO (_L :: Fix Id) thunk FixId)
instance (Typeable a,Observable a) => Observable (K a) where
observer (FixConst a) = send "" (fmapO (_L::Fix (Const a)) thk a >>= return . FixConst)
where thk = thunk :: a -> ObserverM a
instance (FunctorO (PF a),FunctorO (PF b)) => Observable (a :+!: b) where
observer (FixSum f) = send "" (fmapO (_L::Fix (PF a :+: PF b)) thk f >>= return . FixSum)
where thk = thunk :: a :+!: b -> ObserverM (a :+!: b)
instance (FunctorO (PF a), FunctorO (PF b)) => Observable (a :*!: b) where
observer (FixProd f) = send "" (fmapO (_L::Fix (PF a :*: PF b)) thk f >>= return . FixProd)
where thk = thunk :: a :*!: b -> ObserverM (a :*!: b)
instance (FunctorO (PF a), FunctorO (PF b)) => Observable (a :@!: b) where
observer (FixComp f) = send "" (fmapO (_L::Fix (PF a :@: PF b)) thk f >>= return . FixComp)
where thk = thunk :: a :@!: b -> ObserverM (a :@!: b)
instance (Functor f, FunctorO f) => Observable (Fix f) where
observer (Fix x) = send (watch (_L::Fix f) (_L::Fix f) x) (fmapO (_L::Fix f) thk x >>= return . Fix)
where thk = thunk :: Fix f -> ObserverM (Fix f)