{-# LANGUAGE FlexibleContexts #-} module Task09 where import Control.Applicative import Control.Monad.Reader import Data.Map.Strict ( Map ) import qualified Data.Map.Strict as Map type Varname = String data AExpr = Con Integer | Var Varname | Add AExpr AExpr | Mul AExpr AExpr deriving ( Eq, Show, Read ) type Assignment = Map Varname Integer value :: MonadReader Assignment m => String -> m Integer value v = reader (Map.findWithDefault 0 v) evala :: MonadReader Assignment m => AExpr -> m Integer evala (Con x) = pure x evala (Var x) = value x evala (Add x y) = liftA2 (+) (evala x) (evala y) evala (Mul x y) = liftA2 (*) (evala x) (evala y) data BExpr = Equal AExpr AExpr | LEQ AExpr AExpr | And BExpr BExpr | Not BExpr deriving ( Eq, Show, Read ) evalb :: MonadReader Assignment m => BExpr -> m Bool evalb (Equal x y) = liftA2 (==) (evala x) (evala y) evalb (LEQ x y) = liftA2 (<=) (evala x) (evala y) evalb (And x y) = liftA2 (&&) (evalb x) (evalb y) evalb (Not x) = fmap not (evalb x) data LAExpr = LCon Integer | LVar Varname | LAdd LAExpr LAExpr | LMul LAExpr LAExpr | Let Varname LAExpr LAExpr deriving ( Eq, Show, Read ) evalla :: MonadReader Assignment m => LAExpr -> m Integer evalla (LCon x) = pure x evalla (LVar x) = reader (Map.findWithDefault 0 x) evalla (LAdd x y) = liftA2 (+) (evalla x) (evalla y) evalla (LMul x y) = liftA2 (*) (evalla x) (evalla y) evalla (Let var val expr) = evalla val >>= \v -> local (Map.insert var v) (evalla expr)