Overview

There are type classes that control the flow of the program (e.g. whether the program should do X and then Y or should do X and Y at the same time).

Functor, Apply, and Bind Type Classes Explained in Pictures

We've linked to an article below that explains these abstract notions in a clear manner using pictures and the Maybe a data structure. However, since these concepts are explained in Haskell, which uses different terminology than Purescript, use the following table to map Haskell terminology to Purescript terminology:

Haskell TerminologyPurescript Terminology
fmap (function)map (function)
Applicative (type class)Apply (type class)
Array/[] (syntax sugar for List a)List a
map (Array function)see the implementation in Purescript
IO ()Effect Unit, which will be explained/used in a later part of this folder

Here's the link: Functors, Applicatives, and Monads in Pictures

Lists' Map Function in Purescript

Here's the map List function implemented in Purescript:

data List a = Nil | Cons a (List a)

instance Functor List where
  map :: forall a b. (a -> b) -> List a -> List b
  map f Nil = Nil
  map f (Cons head tail) = Cons (f head) (map f tail)

Functor, Apply, Applicative, Bind, Monad

In Short

ConceptArgument is NOT inside a Box / contextArgument is inside a Box / contextName
1-arg function applicationfunction argfunction <$> (Box arg)Functor
2+-arg function applicationfunction arg1 arg2function <$> (Box arg1) <*> (Box arg2)Applicative
function compositionaToB >>> bToCaToBoxB >=> bToBoxCMonad

Somewhat longer

These will be covered at a slower and clearer pace in the upcoming files. This is just an overview of them.

Typeclass"Plain English"FunctionInfixLawsUsage
FunctorMappablemap :: forall a b. (a -> b) -> f a -> f b<$>
(Left 4)
  • identity: map (\x -> x) fa == fa
  • composition: map (f <<< g) = map f <<< map g
Change a value, a, that's currently stored in some box-like type, f, using a function, (a -> b)
ApplyBoxed Mappableapply :: forall a b. f (a -> b) -> f a -> f b<*>
(Left 4)
  • Associative composition: (<<<) <$> f <*> g <*> h == f <*> (g <*> h)
Same as Functor except the function is now inside of the same box-like type.
ApplicativeLiftable
Parallel Computation
pure :: forall a. a -> f a
  • identity: (pure (\x -> x) <*> v == v)
  • composition: pure (<<<) <*> f <*> g <*> h == f <*> (g <*> h)
  • Homomorphism: (pure f) <*> (pure x) == pure (f x)
  • interchange: u <*> (pure y) == (pure (_ $ y)) <*> u
Put a value into a box
Run code in parallel
BindSequential Computationbind :: forall m a b. m a -> (a -> m b) -> m b>>=
(Left 1)
Associativity: (x >>= f) >>= g == x >>= (\x' -> f x' >>= g)Given an value of a box-like type, m, that contains a value, a, extract the a from m, and create a new m value that stores a new value, b.
Take m a and compute it via bind/>>= to produce a value, a. Then, use a to describe (but not run) a new computation, m b. When m b is computed (via a later bind/>>=), it will return b.
MonadFP Program
  • Left Identity: pure x >>= f = f x
  • Right Identity: x >>= pure = x
  • Applicative Superclass: apply = ap
The data structure used to run FP programs by executing code line-by-line, function-by-function, etc.

Simplest Monad Implementation

data Box a = Box a

instance Functor Box where
  map        f  (Box a) = Box (f a)

instance Apply Box where
  apply (Box f) (Box a) = Box (f a)

instance Bind Box where
  bind  (Box a) f       = f a

instance Applicative Box where
  pure a = Box a

instance Monad Box

Function Reduction

In these files, we will "evaluate" functions by using graph reductions: replacing the left-hand side (LHS) of the = sign (the function's call signature) with the right-hand side (RHS) of the = sign (the function's implementation / body). In other words...

someFunction arg1 arg2 arg3 = bodyOfFunction
| call signature (LHS)    | = | body (RHS) |