Warning! It seems that you are using Dodona within another webpage, so not everything may work properly. Let your teacher know so that he can solve the problem by adjusting a setting in the learning environment. In the meantime, you can click this link to open Dodona in a new window.
Warning! The page was not fully loaded, probably because of a network issue. It could be that not all functionalities work as expected. Please try reloading the page.
Haskell exercise
Reader Monad
Sign in to hand in your solution and get feedback.
-- | Reader is een wrapper rondom een functie, zodat we een groot aantal
-- functies die op hetzelfde argument (de omgeving) toegepast worden, kunnen
-- combineren.
newtype Reader env a = Reader { runReader :: env -> a }
-- | Een Reader is een Monad.
instance Monad (Reader env) where
return = undefined
(>>=) = undefined
instance Applicative (Reader env) where
pure = undefined
(<*>) = undefined
instance Functor (Reader env) where
fmap = undefined
-- | Vraag de omgeving op - gelijkaardig aan "get" van State.
ask :: Reader env env
ask = undefined
-- | Voer een gegeven Reader uit binnen een lokaal gewijzigde omgeving.
local :: (env -> env') -> (Reader env' a -> Reader env a)
local = undefined
type Name = String
data Term = Add Term Term
| App Term Term
| Lam Name Term
| Var Name
| Con Int
deriving (Eq, Show)
-- Een omgeving werkt hier iets anders dan in de 'Monadische Interpreters'
-- oefeningenreeks. Een variabelenaam wordt gemapt op een closure. Een closure
-- is een (nog te berekenen) term, tesamen met de context (zelf een omgeving)
-- waarin die berekend moet worden.
type Env = [(String, Closure)]
data Closure = Closure Term Env deriving (Eq, Show)
-- Dit geeft ook een iets andere functie-waarde definitie. Een functie bestaat
-- uit een variabelenaam en een closure: dus een variabelenaam (die we moeten
-- "toekennen"), een term (de "body" die we moeten evalueren) en de context van
-- het moment van aanmaken.
data Value = Wrong
| Num Int
| Fun Name Closure
deriving (Eq, Show)
interp :: Term -> Reader Env Value
interp (Con x) = return $ Num x
interp (Add e1 e2) = do v1 <- interp e1
v2 <- interp e2
add v1 v2
interp (Lam v e) = do env <- ask
return $ Fun v (Closure e env)
interp (Var v) = do env <- ask
interpClosure (lookup v env)
interp (App e1 e2) = do v1 <- interp e1
app v1 e2
-- | Tel twee waarden op - als het getallen zijn.
add :: Value -> Value -> Reader Env Value
add = undefined
-- | Bereken de waarde van een closure - als de closure bestaat.
interpClosure :: Maybe Closure -> Reader Env Value
interpClosure = undefined
-- | Pas een waarde toe op een term - als het een lambda is.
app :: Value -> Term -> Reader Env Value
app = undefined
runInterpreter :: Term -> Value
runInterpreter e = runReader (interp e) ([])