packages feed

HaRe-0.6: refactorer/PwPf/PointlessP/Functors.hs

{-# OPTIONS -fglasgow-exts -fallow-undecidable-instances #-}

module PointlessP.Functors where

import PointlessP.Combinators

-- Data types as fixed points of functors - PolyP style

class (Functor f) => FunctorOf f d | d -> f
    where inn' :: f d -> d
	  out' :: d -> f d

-- Bridge to data types as explicit fixed points

newtype (Functor f) => Mu f = Mu {unMu :: f (Mu f)}

instance (Functor f) => FunctorOf f (Mu f)
    where inn' = Mu
	  out' = unMu

--infixr 5 :+:
--infixr 6 :*:
--infixr 9 :@:

-- Functors

newtype Id x        = Id {unId :: x}
newtype Const t x   = Const {unConst :: t}
data (PSum g h) x    = Inl (g x) | Inr (h x)
data (PProd g h) x    = PProd (g x) (h x)
newtype (PApp g h) x = Comp {unComp :: g (h x)}

-- Maps

instance Functor Id
    where fmap f (Id x) = Id (f x)

instance Functor (Const t)
    where fmap f (Const x) = Const x

instance (Functor g, Functor h) => Functor (PSum g h)
    where fmap f (Inl x) = Inl (fmap f x)
	  fmap f (Inr x) = Inr (fmap f x)

instance (Functor g, Functor h) => Functor (PProd g h)
    where fmap f (PProd x y) = PProd (fmap f x) (fmap f y)

instance (Functor g, Functor h) => Functor (PApp g h)
    where fmap f (Comp x) = Comp (fmap (fmap f) x)

-- From functors to sums of products

class Rep a b | a -> b
    where to :: a -> b
	  from :: b -> a

instance Rep (Id x) x
    where to (Id x) = x
	  from x = Id x

instance Rep (Const t x) t
    where to (Const t) = t
	  from t = Const t

instance (Rep (g x) y, Rep (h x) z) => Rep ((PSum g h) x) (Either y z)
    where to (Inl a) = Left (to a)
	  to (Inr a) = Right (to a)
	  from (Left a) = Inl (from a)
	  from (Right a) = Inr (from a)

instance (Rep (g x) y, Rep (h x) z) => Rep ((PProd g h) x) (y, z)
    where to (PProd a b) = (to a, to b)
	  from (a, b) = PProd (from a) (from b)

instance (Functor g, Rep (h x) y, Rep (g y) z) => Rep ((PApp g h) x) z
    where to (Comp x) = to (fmap to x) 
	  from y = Comp (fmap from (from y))

-- We also need the (obvious) representation of type functors

instance Rep [a] [a]
    where to = id
	  from = id

-- The out and inn functions

out :: (FunctorOf f d, Rep (f d) fd) => d -> fd
out = to . out'

inn :: (FunctorOf f d, Rep (f d) fd) => fd -> d
inn = inn' . from

ouT :: (FunctorOf f d, Rep (f d) fd) => d -> d -> fd
ouT _ = to . out'

inN :: (FunctorOf f d, Rep (f d) fd) => d -> fd -> d
inN _ = inn' . from

-- Auxiliary definitions

instance FunctorOf (PSum (Const One) (PProd (Const a) Id)) [a] 
    where inn' (Inl (Const _))          = []
	  inn' (Inr (PProd (Const x) (Id xs))) = x:xs
	  out' []     = Inl (Const _L)
	  out' (x:xs) = Inr (PProd (Const x) (Id xs))

nil :: One -> [a]
nil = inn . inl

cons :: (a,[a]) -> [a]
cons = inn . inr

instance FunctorOf (PSum (Const One) Id) Int
    where inn' (Inl (Const _)) = 0
	  inn' (Inr (Id n)) = n+1
	  out' 0     = Inl (Const _L)
	  out' (n+1) = Inr (Id n)

zero :: One -> Int
zero = inn . inl

suck :: Int -> Int
suck = inn . inr 

instance FunctorOf (PSum (Const One) (Const One)) Bool
    where inn' (Inl _) = True
	  inn' (Inr _) = False
	  out' True  = Inl _L
	  out' False = Inr _L

true :: One -> Bool
true = inn . inl

false :: One -> Bool
false = inn . inr

fix :: (a->a) -> a
fix f = f (fix f)