
It is easy to read an environment in applicative style, ie: type Env = [(String, Int)] data Term = Add Term Term | Number Int | Var String deriving Show eval :: Term -> Env -> Int eval (Add a b) = (+) <$> eval a <*> eval b eval (Var name) = fetch name eval (Number i) = pure i fetch :: String -> Env -> Int fetch name = fromJust . lookup name But can the eval function change the Env being passed, as to implement a "let" operation, without using monads? I tried I lot but ultimately I resorted to (>>=) in the function monad: bind f k = \r -> k (f r) r I do not think so, because in applicative style each operand can have an effect (reading the environment) but can not affect other operands (including the next ones), i.e., there is no notion of sequencing in applicatives Is this reasoning right?