compdata-0.8.1.0: examples/Examples/Thunk.hs
{-# LANGUAGE TemplateHaskell, TypeOperators, MultiParamTypeClasses,
FlexibleInstances, FlexibleContexts, UndecidableInstances, ConstraintKinds #-}
--------------------------------------------------------------------------------
-- |
-- Module : Examples.Thunk
-- Copyright : (c) 2011 Patrick Bahr, Tom Hvitved
-- License : BSD3
-- Maintainer : Tom Hvitved <hvitved@diku.dk>
-- Stability : experimental
-- Portability : non-portable (GHC Extensions)
--
-- This example illustrates how the ''Data.Comp.Thunk'' package can be
-- used to implement a non-strict language (or a partially non-strict
-- language).
--
--------------------------------------------------------------------------------
module Examples.Thunk where
import Data.Comp
import Data.Comp.Thunk
import Data.Comp.Derive
import Data.Comp.Show()
import Examples.Common hiding (Value(..), Sig, iConst, iPair)
-- Signature for values, strict pairs
data Value a = Const Int | Pair !a !a
-- Signature for the simple expression language
type Sig = Op :+: Value
-- Derive boilerplate code using Template Haskell
$(derive [makeFunctor, makeTraversable, makeFoldable,
makeEqF, makeShowF, smartConstructors, makeHaskellStrict]
[''Value])
-- Monadic term evaluation algebra
class EvalT f m v where
evalAlgT :: Monad m => AlgT m f v
$(derive [liftSum] [''EvalT])
-- Lift the monadic evaluation algebra to a monadic catamorphism
evalT :: (Traversable v, Functor f, EvalT f m v, Monad m) => Term f -> m (Term v)
evalT = nf . cata evalAlgT
instance (Value :<: m :+: v) => EvalT Value m v where
-- make pairs strict in both components
-- evalAlgT x@Pair{} = strict x
-- or explicitly:
-- evalAlgT (Pair x y) = thunk $ liftM2 iPair (dethunk' x) (dethunk' )y
-- evalAlgT x = inject x
-- or only partially strict
evalAlgT = haskellStrict'
instance (Value :<: m :+: v, Value :<: v) => EvalT Op m v where
evalAlgT (Add x y) = thunk $ do
Const n1 <- whnfPr x
Const n2 <- whnfPr y
return $ iConst $ n1 + n2
evalAlgT (Mult x y) = thunk $ do
Const n1 <- whnfPr x
Const n2 <- whnfPr y
return $ iConst $ n1 * n2
evalAlgT (Fst v) = thunk $ do
Pair x _ <- whnfPr v
return x
evalAlgT (Snd v) = thunk $ do
Pair _ y <- whnfPr v
return y
{-instance Monad (Either String) where
Left msg >>= _ = Left msg
Right x >>= f = f x
return = Right
fail = Left-}
evalTEx :: Either String (Term Value)
evalTEx = evalT (iSnd (iFst (iConst 5) `iPair` iConst 4) :: Term Sig)