packages feed

compdata-param-0.9.2: examples/Examples/Graph.hs

{-# LANGUAGE TypeOperators, MultiParamTypeClasses, TemplateHaskell,
  FlexibleInstances, FlexibleContexts, UndecidableInstances #-}
--------------------------------------------------------------------------------
-- |
-- Module      :  Examples.Param.Graph
-- Copyright   :  (c) 2011 Patrick Bahr, Tom Hvitved
-- License     :  BSD3
-- Maintainer  :  Tom Hvitved <hvitved@diku.dk>
-- Stability   :  experimental
-- Portability :  non-portable (GHC Extensions)
--
-- Graph representation. The example is taken from (Fegaras and Sheard,
-- Revisiting Catamorphisms over Datatypes with Embedded Functions, '96).
--
--------------------------------------------------------------------------------

module Examples.Graph where

import Data.Comp.Param
import Data.Comp.Param.Derive
import Data.Comp.Param.Show ()
import Data.Comp.Param.Equality ()

data N p a b = N p [b] -- Node
data R a b = R (a -> b) -- Recursion
data S a b = S (a -> b) b -- Sharing

$(derive [makeDifunctor, makeShowD, makeEqD, makeOrdD, smartConstructors]
         [''N, ''R, ''S])
$(derive [makeDitraversable] [''N])

type Graph p = Term (N p :+: R :+: S)

class FlatG f p where
  flatGAlg :: Alg f [p]

$(derive [liftSum] [''FlatG])

flatG :: (Difunctor f, FlatG f p) => Term f -> [p]
flatG = cata flatGAlg

instance FlatG (N p) p where
  flatGAlg (N p ps) = p : concat ps

instance FlatG R p where
  flatGAlg (R f) = f []

instance FlatG S p where
  flatGAlg (S f g) = f g

class SumG f where
  sumGAlg :: Alg f Int

$(derive [liftSum] [''SumG])

sumG :: (Difunctor f, SumG f) => Term f -> Int
sumG = cata sumGAlg

instance SumG (N Int) where
  sumGAlg (N p ps) = p + sum ps

instance SumG R where
  sumGAlg (R f) = f 0

instance SumG S where
  sumGAlg (S f g) = f g

g :: Graph Int
g = Term $ iR (\x -> iS (\z -> iN (0 :: Int) [z,iR $ \y -> iN (1 :: Int) [y,z]])
                        (iN (2 :: Int) [x]))

f :: [Int]
f = flatG g

n :: Int
n = sumG g