Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions src/Control/Applicative.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
module Control.Applicative
( Applicative
, pure
, liftA1
, when
, unless
, module Control.Apply
) where

import Control.Apply
import Data.Function (const)
import Data.Unit (Unit(), unit)

-- | The `Applicative` type class extends the [`Apply`](#apply) type class
-- | with a `pure` function, which can be used to create values of type `f a`
-- | from values of type `a`.
-- |
-- | Where [`Apply`](#apply) provides the ability to lift functions of two or
-- | more arguments to functions whose arguments are wrapped using `f`, and
-- | [`Functor`](#functor) provides the ability to lift functions of one
-- | argument, `pure` can be seen as the function which lifts functions of
-- | _zero_ arguments. That is, `Applicative` functors support a lifting
-- | operation for any number of function arguments.
-- |
-- | Instances must satisfy the following laws in addition to the `Apply`
-- | laws:
-- |
-- | - Identity: `(pure id) <*> 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`
class (Apply f) <= Applicative f where
pure :: forall a. a -> f a

instance applicativeFn :: Applicative ((->) r) where
pure = const

instance applicativeArray :: Applicative Array where
pure x = [x]

-- | `liftA1` provides a default implementation of `(<$>)` for any
-- | [`Applicative`](#applicative) functor, without using `(<$>)` as provided
-- | by the [`Functor`](#functor)-[`Applicative`](#applicative) superclass
-- | relationship.
-- |
-- | `liftA1` can therefore be used to write [`Functor`](#functor) instances
-- | as follows:
-- |
-- | ```purescript
-- | instance functorF :: Functor F where
-- | map = liftA1
-- | ```
liftA1 :: forall f a b. (Applicative f) => (a -> b) -> f a -> f b
liftA1 f = apply (pure f)

-- | Perform an applicative action when a condition is true.
when :: forall m. (Applicative m) => Boolean -> m Unit -> m Unit
when true m = m
when false _ = pure unit

-- | Perform an applicative action unless a condition is true.
unless :: forall m. (Applicative m) => Boolean -> m Unit -> m Unit
unless false m = m
unless true _ = pure unit
17 changes: 17 additions & 0 deletions src/Control/Apply.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* global exports */
"use strict";

// module Control.Apply

exports.applyArrayImpl = function (fs) {
return function (xs) {
var result = [];
var n = 0;
for (var j = 0; m = xs.length; j < m; j++) {
for (var i = 0, l = fs.length; i < l; i++) {
result[n++] = fs[i](xs[j]);
}
}
return result;
};
};
85 changes: 85 additions & 0 deletions src/Control/Apply.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
module Control.Apply
( Apply
, apply
, (<*>)
, (*>)
, (<*)
, liftA2
, liftA3
, liftA4
, liftA5
, module Data.Functor
) where

import Data.Category (id)
import Data.Function (const)
import Data.Functor

-- | The `Apply` class provides the `(<*>)` which is used to apply a function
-- | to an argument under a type constructor.
-- |
-- | `Apply` can be used to lift functions of two or more arguments to work on
-- | values wrapped with the type constructor `f`. It might also be understood
-- | in terms of the `lift2` function:
-- |
-- | ```purescript
-- | lift2 :: forall f a b c. (Apply f) => (a -> b -> c) -> f a -> f b -> f c
-- | lift2 f a b = f <$> a <*> b
-- | ```
-- |
-- | `(<*>)` is recovered from `lift2` as `lift2 ($)`. That is, `(<*>)` lifts
-- | the function application operator `($)` to arguments wrapped with the
-- | type constructor `f`.
-- |
-- | Instances must satisfy the following law in addition to the `Functor`
-- | laws:
-- |
-- | - Associative composition: `(<<<) <$> f <*> g <*> h = f <*> (g <*> h)`
-- |
-- | Formally, `Apply` represents a strong lax semi-monoidal endofunctor.
class (Functor f) <= Apply f where
apply :: forall a b. f (a -> b) -> f a -> f b

instance applyFn :: Apply ((->) r) where
apply f g x = f x (g x)

instance applyArray :: Apply Array where
apply = applyArrayImpl

foreign import applyArrayImpl :: forall a b. Array (a -> b) -> Array a -> Array b

infixl 4 <*>
infixl 4 <*
infixl 4 *>

-- | `(<*>)` is an alias for `apply`.
(<*>) :: forall f a b. (Apply f) => f (a -> b) -> f a -> f b
(<*>) = apply

-- | Combine two effectful actions, keeping only the result of the first.
(<*) :: forall a b f. (Apply f) => f a -> f b -> f a
(<*) a b = const <$> a <*> b

-- | Combine two effectful actions, keeping only the result of the second.
(*>) :: forall a b f. (Apply f) => f a -> f b -> f b
(*>) a b = const id <$> a <*> b

-- | Lift a function of two arguments to a function which accepts and returns
-- | values wrapped with the type constructor `f`.
liftA2 :: forall a b c f. (Apply f) => (a -> b -> c) -> f a -> f b -> f c
liftA2 f a b = f <$> a <*> b

-- | Lift a function of three arguments to a function which accepts and returns
-- | values wrapped with the type constructor `f`.
liftA3 :: forall a b c d f. (Apply f) => (a -> b -> c -> d) -> f a -> f b -> f c -> f d
liftA3 f a b c = f <$> a <*> b <*> c

-- | Lift a function of four arguments to a function which accepts and returns
-- | values wrapped with the type constructor `f`.
liftA4 :: forall a b c d e f. (Apply f) => (a -> b -> c -> d -> e) -> f a -> f b -> f c -> f d -> f e
liftA4 f a b c d = f <$> a <*> b <*> c <*> d

-- | Lift a function of five arguments to a function which accepts and returns
-- | values wrapped with the type constructor `f`.
liftA5 :: forall a b c d e f g. (Apply f) => (a -> b -> c -> d -> e -> g) -> f a -> f b -> f c -> f d -> f e -> f g
liftA5 f a b c d e = f <$> a <*> b <*> c <*> d <*> e
14 changes: 14 additions & 0 deletions src/Control/Bind.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* global exports */
"use strict";

// module Control.Bind

exports.bindArrayImpl = function (arr) {
return function (f) {
var result = [];
for (var i = 0, l = arr.length; i < l; i++) {
Array.prototype.push.apply(result, f(arr[i]));
}
return result;
};
};
96 changes: 96 additions & 0 deletions src/Control/Bind.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
module Control.Bind
( Bind
, bind
, (>>=)
, (=<<)
, (>=>)
, (<=<)
, join
, ifM
, module Control.Apply
) where

import Data.Category (id)
import Control.Apply

-- | The `Bind` type class extends the [`Apply`](#apply) type class with a
-- | "bind" operation `(>>=)` which composes computations in sequence, using
-- | the return value of one computation to determine the next computation.
-- |
-- | The `>>=` operator can also be expressed using `do` notation, as follows:
-- |
-- | ```purescript
-- | x >>= f = do y <- x
-- | f y
-- | ```
-- |
-- | where the function argument of `f` is given the name `y`.
-- |
-- | Instances must satisfy the following law in addition to the `Apply`
-- | laws:
-- |
-- | - Associativity: `(x >>= f) >>= g = x >>= (\k => f k >>= g)`
-- |
-- | Associativity tells us that we can regroup operations which use `do`
-- | notation so that we can unambiguously write, for example:
-- |
-- | ```purescript
-- | do x <- m1
-- | y <- m2 x
-- | m3 x y
-- | ```
class (Apply m) <= Bind m where
bind :: forall a b. m a -> (a -> m b) -> m b

instance bindFn :: Bind ((->) r) where
bind m f x = f (m x) x

instance bindArray :: Bind Array where
bind = bindArrayImpl

foreign import bindArrayImpl :: forall a b. Array a -> (a -> Array b) -> Array b

infixl 1 >>=
infixr 1 =<<
infixr 1 >=>
infixr 1 <=<

-- | `(>>=)` is an alias for `bind`.
(>>=) :: forall m a b. (Bind m) => m a -> (a -> m b) -> m b
(>>=) = bind

-- | A version of `(>>=)` with its arguments flipped.
(=<<) :: forall a b m. (Bind m) => (a -> m b) -> m a -> m b
(=<<) f m = m >>= f

-- | Forwards Kleisli composition.
-- |
-- | For example:
-- |
-- | ```purescript
-- | import Data.Array (head, tail)
-- |
-- | third = tail >=> tail >=> head
-- | ```
(>=>) :: forall a b c m. (Bind m) => (a -> m b) -> (b -> m c) -> a -> m c
(>=>) f g a = f a >>= g

-- | Backwards Kleisli composition.
(<=<) :: forall a b c m. (Bind m) => (b -> m c) -> (a -> m b) -> a -> m c
(<=<) f g a = f =<< g a

-- | Collapse two applications of a monadic type constructor into one.
join :: forall a m. (Bind m) => m (m a) -> m a
join = (>>= id)

-- | Execute a monadic action if a condition holds.
-- |
-- | For example:
-- |
-- | ```purescript
-- | main = ifM ((< 0.5) <$> random)
-- | (trace "Heads")
-- | (trace "Tails")
-- | ```
ifM :: forall a m. (Bind m) => m Boolean -> m a -> m a -> m a
ifM cond t f = cond >>= \cond' -> if cond' then t else f
58 changes: 58 additions & 0 deletions src/Control/Monad.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
module Control.Monad
( Monad
, liftM
, ap
, module Control.Applicative
, module Control.Bind
) where

import Control.Applicative
import Control.Bind

-- | The `Monad` type class combines the operations of the `Bind` and
-- | `Applicative` type classes. Therefore, `Monad` instances represent type
-- | constructors which support sequential composition, and also lifting of
-- | functions of arbitrary arity.
-- |
-- | Instances must satisfy the following laws in addition to the
-- | `Applicative` and `Bind` laws:
-- |
-- | - Left Identity: `pure x >>= f = f x`
-- | - Right Identity: `x >>= pure = x`
class (Applicative m, Bind m) <= Monad m

instance monadFn :: Monad ((->) r)
instance monadArray :: Monad Array

-- | `liftM` provides a default implementation of `(<$>)` for any
-- | [`Monad`](#monad), without using `(<$>)` as provided by the
-- | [`Functor`](#functor)-[`Monad`](#monad) superclass relationship.
-- |
-- | `liftM` can therefore be used to write [`Functor`](#functor) instances
-- | as follows:
-- |
-- | ```purescript
-- | instance functorF :: Functor F where
-- | map = liftM
-- | ```
liftM :: forall m a b. (Monad m) => (a -> b) -> m a -> m b
liftM f a = do
a' <- a
pure (f a')

-- | `ap` provides a default implementation of `(<*>)` for any
-- | [`Monad`](#monad), without using `(<*>)` as provided by the
-- | [`Apply`](#apply)-[`Monad`](#monad) superclass relationship.
-- |
-- | `ap` can therefore be used to write [`Apply`](#apply) instances as
-- | follows:
-- |
-- | ```purescript
-- | instance applyF :: Apply F where
-- | apply = ap
-- | ```
ap :: forall m a b. (Monad m) => m (a -> b) -> m a -> m b
ap f a = do
f' <- f
a' <- a
pure (f' a')
20 changes: 20 additions & 0 deletions src/Data/BooleanAlgebra.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* global exports */
"use strict";

// module Data.BooleanAlgebra

exports.conjBooleanImpl = function (b1) {
return function (b2) {
return b1 && b2;
};
};

exports.disjBooleanImpl = function (b1) {
return function (b2) {
return b1 || b2;
};
};

exports.notBooleanImpl = function (b) {
return !b;
};
Loading