Applicative
Posted on January 1, 2020
Tags: functional
class (Functor fun) => Applicative fun where
pure :: a -> fun a
(<*>) :: fun (a -> b) -> fun a -> fun b
1 Map vs Applicative
- Notice Applicative is like fmap but gives higher precision than fmap.
fmap (*2) [1,2,3,4]
<*> [(+3) (*4) (*3) (+5)] [1,2,3,4]
2 Closures
-- untyped lambda calculus values are functions
data Value = FunVal (Value -> Value)
-- we write expressions where variables take string-based names, but we'll
-- also just assume that nobody ever shadows names to avoid having to do
-- capture-avoiding substitutions
type Name = String
data Expr
= Var Name
| App Expr Expr
| Abs Name Expr
-- We model the environment as function from strings to values,
-- notably ignoring any kind of smooth lookup failures
type Env = Name -> Value
-- The empty environment
env0 :: Env
= error "Nope!"
env0 _
-- Augmenting the environment with a value, "closing over" it!
addEnv :: Name -> Value -> Env -> Env
| nm' == nm = v
addEnv nm v e nm' | otherwise = e nm
-- And finally the interpreter itself
interp :: Env -> Expr -> Value
Var name) = e name -- variable lookup in the env
interp e (App ef ex) =
interp e (let FunVal f = interp e ef
= interp e ex
x in f x -- application to lambda terms
Abs name expr) =
interp e (-- augmentation of a local (lexical) environment
FunVal (\value -> interp (addEnv name value e) expr)