Applicative
Usage
- Lift any value/function/etc. into a box-like type,
f
- Parallel Computation: Do all three simultaneously: X, Y, and Z.
(Note: Javascript is currently single-threaded, so this isn't entirely true. If it gets multi-thread support, that will change.)
Definition
See its docs: Applicative
class (Apply f) <= Applicative f where
pure :: forall a. a -> f a
data Box a = Box a
instance Functor Box where
map :: forall a b. (a -> b) -> Box a -> Box b
map f (Box a) = Box (f a)
instance Apply Box where
apply :: forall a b. Box (a -> b) -> Box a -> Box b
apply (Box f ) (Box a) = Box (f a)
instance Applicative Box where
pure :: forall a. a -> Box a
pure a = Box a
Laws
Identity
Definition: (pure (\x -> x) <*> v == v)
-- Start: 'v' == (Box 4)
(pure (\x -> x)) <*> (Box 4)
-- Replace pure call signature with body
( Box (\x -> x)) <*> (Box 4)
-- De-infix <*> to apply
apply (Box (\x -> x)) (Box 4)
-- Replace apply call signature with body
Box (\x -> x) 4)
-- Apply argument by replacing all 'x' with '4'
Box (\4 -> 4) )
-- Keep body of function
Box ( 4) )
-- Remove whitespace and parenthesis
Box 4
-- Check law
(Box 4) == (Box 4)
-- Law met!
true
Composition
Definition: pure (<<<) <*> f <*> g <*> h == f <*> (g <*> h)
TODO: prove the above law using Box
(a lot of work, so ignoring for now...)
Homomorphism
Definition: (pure f) <*> (pure x) == pure (f x)
TODO: prove the above law using Box
(a lot of work, so ignoring for now...)
Interchange
Definition: u <*> (pure y) == (pure (_ $ y)) <*> u
TODO: prove the above law using Box
(a lot of work, so ignoring for now...)
Derived Functions
- Define an instance of
Apply
andApplicative
and you get aFunctor
implementation for free!:liftA1
- Do a computation...
- if some condition is true:
when
- if some condition is false:
unless
- if some condition is true:
Note: when
/unless
is strict. For a lazy version, see purescript-call-by-name