packages feed

effect-monad-0.7.0.0: examples/Counter.hs

{-# LANGUAGE RebindableSyntax, EmptyDataDecls, GADTs, TypeFamilies, UndecidableInstances, MultiParamTypeClasses, TypeOperators, ScopedTypeVariables, ImplicitParams #-}

import Prelude hiding (Monad(..),map)
import Control.Effect
import Control.Effect.Counter

import Debug.Trace

{-

The 'Counter' graded monad is useful for counting computations
of a particular kind (e.g., counting number of calls to a websocket)
or estimating resource usage (e.g., a websocket call is more expensive
than a disk write).

By default, zero counts are tracked, e.g.,

-}

foo :: Counter Z Int
foo = do x <- return 2
         y <- return 4
         return (x + y)

{- the 'tick' function lifts a value to be counted once, e.g. -}

-- foo2 :: Counter (S Z) Int
foo2 = do x <- tick 2
          y <- return 3
          return (x * y)

zero :: Counter Z Int
zero = do x <- return 2
          y <- return 4
          return (x + y)

{- This can be used for other cool things, like proving that 'map' has
 linear complexity of 'map' at the type-level!

For this we need sized lists:
-}

data Vector n a where
    Nil :: Vector Z a
    Cons :: a -> Vector n a -> Vector (S n) a

type family n :* m where
            Z     :* m = Z
            (S n) :* m = m :+ (n :* m)

map' :: (a -> Counter t b) -> Vector n a -> Counter (n :* t) (Vector n b)
map' f Nil         = return Nil
map' f (Cons x xs) = do x' <- f x
                        xs' <- map' f xs
                        return (Cons x' xs')











map :: (a -> Counter t b) -> Vector n a -> Counter (n :* t) (Vector n b)
map f Nil         = return Nil
map f (Cons x xs) = do x' <- f x
                       xs' <- map f xs
                       return (Cons x' xs')

class Bar n where
instance Bar Z where
instance Bar n => Bar (S n) where

data Listy n a where
    Nily :: Listy Z a
    Consy :: (Bar n) => a -> Listy n a -> Listy (S n) a

fooo :: Listy n a -> Int
fooo Nily = 0
fooo (Consy x (Consy y xs)) = 2 + (fooo xs)
fooo (Consy x xs) = 1 + (fooo xs)

{- The types show us that if the function counts 't' things, then applying 'map
to an n-vector counts 'tn' things -}

{- Example: web socket calls- how many do we do per instances #-}

call :: Int -> Counter (S Z) ()
call = undefined

singleCall = map call (Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil))))

doubleCall x = map (\n -> do {a <- call n; b <- call n; return ()}) x

doubleCallExample = doubleCall (Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil))))




{- are we definitely linear in the number of elements, even if we have closed over the vector? -}

class LT n m
instance LT Z (S n)
instance LT n m => LT (S n) (S m)

lineraMap :: LT t n => (a -> Counter t b) -> Vector n a -> Counter (n :* t) (Vector n b)
lineraMap = map