packages feed

rest-rewrite-0.2.0: src/Language/REST/OCAlgebra.hs

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Language.REST.OCAlgebra where

data OCAlgebra c a m = OCAlgebra
  {
    isSat  :: c -> m Bool
  , refine :: c -> a -> a -> c
  , top    :: c

  -- For explore optimizations, if not required just make it return 2nd param
  , union  :: c -> c -> c
  -- If not required return False
  , notStrongerThan :: c -> c -> m Bool
  }

fuelOC :: (Monad m) => Int -> OCAlgebra Int a m
fuelOC initFuel = OCAlgebra isSat' refine' initFuel union' notStrongerThan'
  where
    isSat'  c             = return $ c >= 0
    refine' c _ _         = c - 1
    union'  c c'          = max c c'
    notStrongerThan' c c' = return $ c >= c'

contramap :: forall c a b m .
     (b -> a)
  -> OCAlgebra c a m
  -> OCAlgebra c b m
contramap f aoc = aoc{refine = refine'}
  where
    refine' :: c -> b -> b -> c
    refine' c t1 t2 = refine aoc c (f t1) (f t2)

bimapConstraints :: forall c d a m .
     (c -> d)
  -> (d -> c)
  -> OCAlgebra c a m
  -> OCAlgebra d a m
bimapConstraints to from aoc = OCAlgebra isSat' refine' (to (top aoc)) union' notStrongerThan'
  where
    isSat' :: d -> m Bool
    isSat' c = isSat aoc (from c)

    refine' :: d -> a -> a -> d
    refine' c t1 t2 = to $ refine aoc (from c) t1 t2

    union' :: d -> d -> d
    union' c1 c2 = to $ union aoc (from c1) (from c2)

    notStrongerThan' :: d -> d -> m Bool
    notStrongerThan' c1 c2 = notStrongerThan aoc (from c1) (from c2)