packages feed

inch-0.1.0: examples/Cost.hs

{-# OPTIONS_GHC -F -pgmF inch #-}
{-# LANGUAGE RankNTypes, GADTs, KindSignatures, ScopedTypeVariables,
             NPlusKPatterns #-}

{-
  A library for time complexity analysis, based on

    Nils Anders Danielsson. 2008. Lightweight semiformal time
    complexity analysis for purely functional data structures.

    In Proceedings of the 35th annual ACM SIGPLAN-SIGACT symposium on
    Principles of Programming Languages (POPL '08). ACM.
-}

module Cost (Cost, weaken, force, returnCost, bindCost, weakenBy,
                 tick, returnW, joinCost, mapCost) where

-- Cost is a monad indexed by the number of time steps required to
-- deliver a value in WHNF. 

-- Note that the Hide constructor is not exported, so clients cannot
-- violate the abstraction barrier, though they must still annotate
-- code appropriately (not misusing force, for example).

data Cost :: Num -> * -> * where
  Hide :: forall (n :: Nat) a . a -> Cost n a

instance Show a => Show (Cost 0 a) where
  show (Hide x) = show x

weaken :: forall (m n :: Nat) a . m <= n => Cost m a -> Cost n a
weaken (Hide a) = Hide a

force :: forall (n :: Nat) a . Cost n a -> a
force (Hide a) = a

returnCost :: a -> Cost 0 a
returnCost = Hide

bindCost :: forall (m n :: Nat) a b . Cost m a ->
                (a -> Cost n b) -> Cost (m+n) b
bindCost x f = weaken (f (force x))


-- Given the above primitives, we define some useful derived combinators:

weakenBy :: forall (n :: Nat) a . pi (m :: Nat) . Cost n a -> Cost (m + n) a
weakenBy {m} = weaken

tick :: forall (n :: Nat) a . Cost n a -> Cost (n + 1) a
tick = weakenBy {1}

returnW :: forall (n :: Nat) a . a -> Cost n a
returnW x = weaken (returnCost x)

joinCost :: forall (m n :: Nat) a . Cost m (Cost n a) -> Cost (m + n) a
joinCost x = bindCost x id

mapCost :: forall (n :: Nat) a b . (a -> b) -> Cost n a -> Cost n b
mapCost f x = bindCost x (\ x -> returnW (f x))