diff --git a/docs/src/pages/docs/crocks/Pair.md b/docs/src/pages/docs/crocks/Pair.md
new file mode 100644
index 000000000..7b76f5b5a
--- /dev/null
+++ b/docs/src/pages/docs/crocks/Pair.md
@@ -0,0 +1,1021 @@
+---
+title: "Pair"
+description: "Canonical Product Type"
+layout: "guide"
+functions: ["branch", "fst", "merge", "snd", "topairs", "writertopair"]
+weight: 100
+---
+
+```haskell
+Pair a b
+```
+
+`Pair` allows the ability to represent (2) distinct values of different types.
+Much like how `Either` is known as canonical Sum Type and defines the basis for
+all other Sum Types that ship with `crocks`, `Pair` is known as the canonical
+Product Type and also at the heart of all Product Types in `crocks`.
+
+As `Pair` is a `Bifunctor`, it can vary in each of the (2) types it represents.
+When used as a normal `Functor`, `Pair` will always have a bias for the far
+right or second value, matching the pattern of the other ADTs in `crocks`. When
+mapped with a function, the function will only be applied to the second value,
+and will leave the first value untouched.
+
+`Pair` also provides the ability to use `ap` and `chain`, but in order to
+combine the resulting instances in a predictable, repeatable fashion the first
+values in the `Pair`s must be `Semigroup` instances of the same type. When
+applied, `ap` and `chain` will concatenate the `Semigroup`s providing the result
+of the concatenation in the first position of the resulting `Pair`.
+
+A helpful benefit of the `Bifunctor` aspects `Pair` allows for defining parallel
+computations. There are many functions that ship with `crocks` that allow for
+parallelization such as [`branch`](#branch), [`merge`](#merge-pointfree) and
+`fanout`. Using those helpers in conjunction with the ability to
+[`bimap`](#bimap) functions over a given `Pair`s values.
+
+```javascript
+import Pair from 'crocks/Pair'
+import Sum from 'crocks/Sum'
+import bimap from 'crocks/pointfree/bimap'
+import branch from 'crocks/Pair/branch'
+import compose from 'crocks/helpers/compose'
+import mreduce from 'crocks/helpers/mreduce'
+import merge from 'crocks/Pair/merge'
+
+// negate :: a -> Boolean
+const negate =
+ x => !x
+
+// inc :: Number -> Number
+const inc =
+ x => x + 1
+
+// length :: Array -> Number
+const length =
+ x => x.length
+
+// divide :: Number -> Number
+const divide =
+ (x, y) => x / y
+
+Pair(76, false)
+ .bimap(inc, negate)
+//=> Pair(77, true)
+
+// average :: [ Number ] -> Number
+const average = compose(
+ merge(divide),
+ bimap(mreduce(Sum), length),
+ branch
+)
+
+average([ 9, 77, 34 ])
+//=> 40
+```
+
+
+
+## Implements
+`Setoid`, `Semigroup`, `Functor`, `Bifunctor`, `Apply`, `Chain`,
+`Traversable`, `Extend`
+
+
+
+
+
+## Instance Methods
+
+#### equals
+
+```haskell
+Pair a b ~> c -> Boolean
+```
+
+Used to compare the underlying values of (2) `Pair` instances for equality by
+value. `equals` takes any given argument and returns `true` if the passed
+arguments is a `Pair` with an underlying values both in the first and second are
+equal to the underlying values in the first and second of the `Maybe` the
+method is being called on. If the passed argument is not a `Maybe` or the
+underlying values are not equal, `equals` will return `false`.
+
+```javascript
+import Pair from 'crocks/Pair'
+import equals from 'crocks/pointfree/equals'
+
+Pair({ num: 33 }, 'string')
+ .equals(Pair({ num: 33 }, 'string'))
+//=> true
+
+Pair({ num: 33 }, 'string')
+ .equals(Pair({ num: 10 }, 'string'))
+//=> false
+
+Pair({ num: 33 }, 'string')
+ .equals(Pair({ num: 33 }, 'different'))
+//=> false
+
+equals(Pair([ 1, 2 ], ''), [ 1, 2 ])
+//=> false
+```
+
+#### concat
+
+```haskell
+Semigroup s, t => Pair s t ~> Pair s t -> Pair s t
+```
+
+When both underlying values of a given `Pair` are fixed to a `Semigroup`,
+`concat` can be used to concatenate another `Pair` instance with underlying
+`Semigroup`s of the same type and structure. Expecting a `Maybe` wrapping a
+`Semigroup` of the same type, `concat` will give back a new `Pair` instance
+wrapping the result of combining the underlying `Semigroup` instances.
+
+```javascript
+import Pair from 'crocks/Pair'
+import Maybe from 'crocks/Maybe'
+import Sum from 'crocks/Sum'
+
+import compose from 'crocks/helpers/compose'
+import concat from 'crocks/pointfree/concat'
+import fanout from 'crocks/helpers/fanout'
+import flip from 'crocks/combinators/flip'
+import map from 'crocks/pointfree/map'
+import mapReduce from 'crocks/helpers/mapReduce'
+import option from 'crocks/pointfree/option'
+import prop from 'crocks/Maybe/prop'
+
+Pair(Sum(3), [ 3 ])
+ .concat(Pair(Sum(10), [ 10 ]))
+//=> Pair( Sum 13, [ 3, 10 ] )
+
+// Person :: { name: String, age: Number }
+// peeps :: [ Person ]
+const peeps = [
+ { name: 'Haskell', age: 82 },
+ { name: 'Heinrich', age: 81 },
+ { name: 'Maria', age: 93 }
+]
+
+// mapProp :: (String, (a -> b)) -> Object -> Maybe b
+const mapProp = (key, fn) =>
+ compose(map(fn), prop(key))
+
+// Combined :: Pair (Maybe [ String ]) (Maybe Sum)
+// splitPerson :: Person -> Combined
+const splitPerson = fanout(
+ mapProp('name', x => [ x ]),
+ mapProp('age', Sum)
+)
+
+// empty :: Combined
+const empty =
+ Pair(Maybe([]), Maybe(Sum.empty()))
+
+// combine :: [ Person ] -> Combined
+const combine = mapReduce(
+ splitPerson,
+ flip(concat),
+ empty
+)
+
+combine(peeps)
+ .bimap(option([]), option(Sum(0)))
+//=> Pair( [ "Haskell", "Heinrich", "Maria" ], Sum 256 )
+```
+
+#### map
+
+```haskell
+Pair c a ~> (a -> b) -> Pair c b
+```
+
+Used to apply transformations to values to the second portion of a given `Pair`
+instance. `map` takes a function that it will lift into the context of the
+`Pair` and apply to it second value in the `Pair`, returning a new `Pair`
+instance. The new instance will contain the result of mapping in the second,
+leaving the value in the first untouched. If you need to map the first value,
+[`bimap`](#bimap) can be used instead.
+
+```javascript
+import Pair from 'crocks/Pair'
+
+import compose from 'crocks/helpers/compose'
+import map from 'crocks/pointfree/map'
+import merge from 'crocks/Pair/merge'
+import objOf from 'crocks/helpers/objOf'
+
+// length :: String -> Number
+const length =
+ x => x.length
+
+// add10 :: Number -> Number
+const add10 =
+ x => x + 10
+
+// keyedLength :: Pair String String -> Object
+const keyedLength =
+ compose(merge(objOf), map(length))
+
+Pair('number', 32)
+ .map(add10)
+//=> Pair("number", 42)
+
+keyedLength(
+ Pair('text', 'This is some text')
+)
+//=> { text: 17 }
+```
+
+#### bimap
+
+```haskell
+Pair a b ~> ((a -> c), (b -> d)) -> Pair c d
+```
+
+The types and values that make up a `Pair` can vary independently in both the
+first and second portions of the `Pair`. While [`map`](#map) can be used to
+apply these transformations, `bimap` allows for independent transformations
+on both sides, in parallel.
+
+`bimap` takes (2) mapping functions as its arguments. The first function is used
+to map the first, while the second maps the second. `Pair` only provides a
+means to map the second's value exclusively using [`map`](#map). If the need
+arises to map the first portion exclusively, use `bimap` passing the mapping
+function to the first argument and an [`identity`][identity] to the second.
+
+```javascript
+import Pair from 'crocks/Pair'
+import Sum from 'crocks/Sum'
+
+import compose from 'crocks/helpers/compose'
+import bimap from 'crocks/pointfree/bimap'
+import branch from 'crocks/Pair/branch'
+import identity from 'crocks/combinators/identity'
+import merge from 'crocks/Pair/merge'
+import mreduce from 'crocks/helpers/mreduce'
+
+// add10 :: Number -> Number
+const add10 =
+ x => x + 10
+
+// divide :: (Number, Number) -> Number
+const divide =
+ (x, y) => x / y
+
+// length :: [ Number ] -> Number
+const length =
+ x => x.length
+
+// average :: [ Number ] -> Number
+const average = compose(
+ merge(divide),
+ bimap(mreduce(Sum), length),
+ branch
+)
+
+Pair(35, 'number')
+ .bimap(add10, identity)
+//=> Pair( 45, 'number' )
+
+average([ 2, 3, 4 ])
+//=> 3
+```
+
+#### ap
+
+```haskell
+Semigroup s => Pair s (a -> b) ~> Pair s a -> Pair s b
+```
+
+Short for apply, `ap` is used to apply a `Pair` instance containing a value on
+its second portion to another `Pair` instance that contains a function in its
+second portion. The result of this application provides a new `Pair` instance
+containing the result in the second portion. `ap` requires that it is called on
+an instance that wraps a curried polyadic function in the second.
+
+An additional constraint when using `ap` is that the `Pair` must contain a
+`Semigroup` instance in its first. This is required for both the `Pair` with
+the function and the `Pair` with the value to be applied. With both `Semigroups`
+being of the same type.
+
+```javascript
+import Pair from 'crocks/Pair'
+import liftA2 from 'crocks/helpers/liftA2'
+
+// add :: Number -> Number -> Number
+const add =
+ x => y => x + y
+
+// NumberRec :: Pair [ Number ] Number
+
+// twentyThree :: NumberRec
+const twentyThree =
+ Pair([ 23 ], 23)
+
+// seventySeven :: NumberRec
+const seventySeven =
+ Pair([ 77 ], 77)
+
+// combine :: NumberRec -> NumberRec -> NumberRec
+const combine =
+ liftA2(add)
+
+twentyThree
+ .map(add)
+ .ap(seventySeven)
+// Pair( [ 23, 77 ], 100 )
+
+combine(twentyThree, seventySeven)
+// Pair( [ 23, 77 ], 100 )
+```
+
+#### chain
+
+```haskell
+Semigroup s => Pair s a ~> (a -> Pair s b) -> Pair s b
+```
+
+Combining a sequential series of transformations that allows for custom
+accumulation in addition to transforming a value. `chain` requires a `Pair`
+returning function that contains a `Semigroup` in its first position. As an
+additional requirement, is that instances of the same `Semigroup` must occupy
+the first position of the source `Pair` and the `Pair` returned by the function.
+
+```javascript
+const Pair = require('crocks/Pair')
+
+const assoc = require('crocks/helpers/assoc')
+const omit = require('crocks/helpers/omit')
+
+// addTmp :: (String, a, Object) -> Pair [ String ] Object
+const addTmp = (key, value, x) =>
+ Pair([ key ], assoc(key, value, x))
+
+// add :: Object -> Pair [ String ] Object
+const add = data => {
+ const { a, b } = data
+ return addTmp('sum', a + b, data)
+}
+
+// multiply :: Object -> Pair [ String ] Object
+const multiply = data => {
+ const { a, b } = data
+ return addTmp('product', a * b, data)
+}
+
+// calc :: Object -> Object
+const calc = data => {
+ const { product, sum } = data
+ return assoc('result', product - sum, data)
+}
+
+// flow :: Object -> Object
+const flow = x =>
+ Pair([], x)
+ .chain(add)
+ .chain(multiply)
+ .map(calc)
+ .merge(omit)
+
+flow({ a: 34, b: 76 })
+//=> { a: 34, b: 76, result: 2474 }
+
+flow({ a: 10, b: 5 })
+//=> { a: 10, b: 5, result: 35 }
+```
+
+#### sequence
+
+```haskell
+Applicative TypeRep t, Apply f => Pair a (f b) ~> (t | (b -> f b)) -> f (Pair a b)
+```
+
+When an instance of `Pair` wraps an `Apply` instance in its second position,
+`sequence` can be used to swap the type sequence. `sequence` requires either an
+`Applicative TypeRep` or an `Apply` returning function is provided for its
+argument.
+
+While it is not a requirement that the first position be occupied by a
+`Semigroup`, in having an instance there sequencing back on a data structure
+with multiple items can allow for accumulation then sequencing back.
+
+`sequence` can be derived from [`traverse`](#traverse) by passing it an
+[`identity`][identity] function (`x => x`).
+
+```javascript
+import Pair from 'crocks/Pair'
+import Sum from 'crocks/Sum'
+
+import bimap from 'crocks/pointfree/bimap'
+import compose from 'crocks/helpers/compose'
+import concat from 'crocks/pointfree/concat'
+import flip from 'crocks/combinators/flip'
+import mapReduce from 'crocks/helpers/mapReduce'
+import sequence from 'crocks/pointfree/sequence'
+
+// pair :: Pair Number [ String ]
+const pair =
+ Pair(1, [ 'a', 'b', 'c' ])
+
+// empty :: () -> Pair Sum String
+const empty =
+ () => Pair(Sum.empty(), '')
+
+// seqArray :: Traversable t => t [ a ] -> [ t a ]
+const seqArray =
+ sequence(Array)
+
+// toUpper :: String -> String
+const toUpper =
+ x => x.toUpperCase()
+
+// combine :: [ Pair Number String ] -> Pair Sum String
+const combine = mapReduce(
+ bimap(Sum, toUpper),
+ flip(concat),
+ empty()
+)
+
+// flow :: Pair Number [ String ] -> Pair Sum String
+const flow =
+ compose(combine, seqArray)
+
+seqArray(pair)
+//=> [ Pair(1, "a"), Pair(1, "b"), Pair(1, "c") ]
+
+flow(pair)
+//=> Pair(Sum 3, "ABC")
+```
+
+#### traverse
+
+```haskell
+Applicative TypeRep t, Apply f => Pair a b ~> ((t | (b -> f b)), (b -> f c)) -> f (Pair a c)
+```
+
+Used to apply the "effect" of an `Apply` to a value in the second position of
+a `Pair`, `traverse` combines both the "effects" of the `Apply` and the `Pair`
+by returning a new instance of the `Apply`, wrapping the result of the
+`Apply`s "effect" on the value in the second position of the `Pair`.
+
+`traverse` requires either an `Applicative TypeRep` or an `Apply` returning
+function as its first argument and a function that is used to apply the "effect"
+of the target `Apply` to the value in the second position of the `Pair`. The
+"effect" will only be applied to second value and leaves the first value
+untouched. Both arguments must return an instance of the target `Apply`.
+
+```javascript
+import Maybe from 'crocks/Maybe'
+import Pair from 'crocks/Pair'
+
+import identity from 'crocks/combinators/identity'
+import safe from 'crocks/Maybe/safe'
+import traverse from 'crocks/pointfree/traverse'
+
+const { Just, Nothing } = Maybe
+
+// isOdd :: Integer -> Boolean
+const isOdd =
+ x => !!(x % 2)
+
+// safeOdd :: Traversable t => t Integer -> Maybe (t Integer)
+const safeOdd =
+ traverse(Maybe, safe(isOdd))
+
+// seqMaybe :: Traversable t => t (Maybe a) -> Maybe (t a)
+const seqMaybe =
+ traverse(Maybe.of, identity)
+
+// odd :: Pair [ Number ] Integer
+const odd =
+ Pair([ 10 ], 23)
+
+// even :: Pair String Integer
+const even =
+ Pair('nope', 42)
+
+safeOdd(odd)
+//=> Just Pair( [ 10 ], 23 )
+
+safeOdd(even)
+//=> Nothing
+
+seqMaybe(Pair(true, Just('good')))
+//=> Just Pair( true, "good" )
+
+seqMaybe(Pair(false, Nothing()))
+//=> Nothing
+```
+
+#### extend
+
+```haskell
+Pair a b ~> (Pair a b -> c) -> Pair a c
+```
+
+Used map the second position of a given `Pair` instance by taking the entire
+`Pair` into consideration. `extend` takes a function the receives a `Pair` as
+its input and returns a new `Pair` with the result of that function in the
+second position, while leaving the value in the first position untouched.
+
+```javascript
+import Pair from 'crocks/Pair'
+
+import extend from 'crocks/pointfree/extend'
+import merge from 'crocks/Pair/merge'
+import objOf from 'crocks/helpers/objOf'
+
+// name :: Pair String String
+const name =
+ Pair('name', 'Thomas')
+
+// mergeObj :: Pair String a -> Object
+const mergeObj =
+ merge(objOf)
+
+// makeObj :: Pair String a -> Pair String Object
+const makeObj =
+ extend(mergeObj)
+
+makeObj(name)
+//=> Pair("name", { name: "Thomas" })
+```
+
+#### swap
+
+```haskell
+Pair a b ~> ((a -> c), (b -> d)) -> Pair d c
+```
+
+Used to map the value of a `Pair`s first position into the second position and
+the second position into the first, `swap` takes (2) functions as its arguments.
+The first function is used to map the value in the first position to the second,
+while the second 'maps the second into the first'. If no mapping is required on
+either side, then [`identity`][identity] functions can be used in one or both arguments.
+
+```javascript
+import Pair from 'crocks/Pair'
+
+import identity from 'crocks/combinators/identity'
+import swap from 'crocks/pointfree/swap'
+
+// toString :: a -> String
+const toString =
+ x => x.toString()
+
+// swapMap :: Pair a String -> Pair Number String
+const swapMap =
+ swap(toString, parseInt)
+
+// m :: Pair Number String
+const m =
+ Pair(76, '105')
+
+m.swap(identity, identity)
+//=> Pair("105", 76)
+
+swapMap(m)
+//=> Pair(105, "76")
+```
+
+#### fst
+
+```haskell
+Pair a b ~> () -> a
+```
+
+`fst` is one of (2) projection methods used to extract the values contained in
+a given `Pair` instance. `fst` takes nothing as its input and will unwrap and
+provide the value in the first position, throwing away the value in the second.
+[`snd`](#snd) is the other projection function provided and is used to extract
+the value in the second position.
+
+```javascript
+import Pair from 'crocks/Pair'
+
+Pair('left', 'right')
+ .fst()
+//=> "left"
+```
+
+#### snd
+
+```haskell
+Pair a b ~> () -> b
+```
+
+`snd` is one of (2) projection methods used to extract the values contained in
+a given `Pair` instance. `snd` takes nothing as its input and will unwrap and
+provide the value in the second position, throwing away the value in the first.
+[`fst`](#fst) is the other projection function provided and is used to extract
+the value in the first position.
+
+```javascript
+import Pair from 'crocks/Pair'
+
+Pair('left', 'right')
+ .snd()
+//=> "right"
+```
+
+#### toArray
+
+```haskell
+Pair a b ~> () -> [ a, b ]
+```
+
+While both [`fst`](#fst) and [`snd`](#snd) can be used to extract specific
+values out of the structure of `Pair`, `toArray` extracts values but
+maintains the structure. Taking nothing as its input, `toArray` will return an
+`Array` of two values. The first value in the `Pair` will occupy the [0] index,
+while the [1] index will house the second.
+
+```javascript
+import Pair from 'crocks/Pair'
+import compose from 'crocks/helpers/compose'
+
+// toArray :: Pair a b -> [ a, b ]
+const toArray =
+ x => x.toArray()
+
+// toObject :: [ a, b ] -> Object
+const toObject =
+ ([ left, right ]) => ({ left, right })
+
+// pairToObject :: Pair a b -> Object
+const pairToObject =
+ compose(toObject, toArray)
+
+// m :: Pair String Number
+const m =
+ Pair('a', 1)
+
+m.toArray()
+//=> [ 'a', 1 ]
+
+pairToObject(m)
+//=> { left: 'a', right: 1 }
+```
+
+#### merge
+
+```haskell
+Pair a b ~> ((a, b) -> c) -> c
+```
+
+Acting as a means to fold a given `Pair` over a binary operation, `merge` takes
+a binary function as its sole argument. Using the function, `merge` will unwrap
+each of its values and apply them to the function in order from first to second.
+The result of the provided function is then provided as the overall result
+for `merge`.
+
+This method comes in handy when using a `Pair` as a means to run parallel
+computations and combine their results into a final answer. Typically this
+method works hand in hand with the either the [`branch`](#branch) or
+[`fanout`][fanout] helper functions.
+
+```javascript
+import Sum from 'crocks/Sum'
+
+import compose from 'crocks/helpers/compose'
+import fanout from 'crocks/helpers/fanout'
+import merge from 'crocks/Pair/merge'
+import mreduce from 'crocks/helpers/mreduce'
+
+// length :: [ a ] -> Integer
+const length =
+ x => x.length
+
+// divide :: (Number, Number) -> Number
+const divide =
+ (x, y) => x / y
+
+// average :: [ Number ] -> Number
+const average = compose(
+ merge(divide),
+ fanout(mreduce(Sum), length)
+)
+
+// nums :: [ Number ]
+const nums =
+ [ 23, 96, 90, 4, 21 ]
+
+average(nums)
+// 46.8
+```
+
+
+
+
+
+## Helper Functions
+
+#### branch
+
+`crocks/Pair/branch`
+
+```haskell
+branch :: a -> Pair a a
+```
+
+Typically the starting point for handling parallel computations on a single
+value, `branch` takes a single value of any type as its only argument. `branch`
+then returns a `Pair` with the reference or value in both the first and second
+positions.
+
+Using `branch` can simplify how computations that depend on the same value are
+constructed and encoded by removing the need to keep the original value in some
+state that needs to be passed from function to function.
+
+```javascript
+import assign from 'crocks/helpers/assign'
+import bimap from 'crocks/pointfree/bimap'
+import branch from 'crocks/Pair/branch'
+import compose from 'crocks/helpers/compose'
+import curry from 'crocks/helpers/curry'
+import objOf from 'crocks/helpers/objOf'
+import merge from 'crocks/Pair/merge'
+
+// add10 :: Number -> Number
+const add10 =
+ x => x + 10
+
+// applyChange :: (a -> b) -> a -> Object
+const applyChange = fn =>
+ compose(objOf('current'), fn)
+
+// createUndo :: (a -> b) -> a -> Object
+const createUndo = curry(fn =>
+ compose(
+ merge(assign),
+ bimap(objOf('orig'), applyChange(fn)),
+ branch
+ )
+)
+
+// applyAdd10 :: Number -> Object
+const applyAdd10 =
+ createUndo(add10)
+
+applyAdd10(5)
+// { current: 15, orig: 5 }
+```
+
+#### toPairs
+
+`crocks/Pair/toPairs`
+
+```haskell
+toPairs :: Object -> List (Pair String a)
+```
+
+When dealing with `Object`s, sometimes it makes more sense to work in a
+`Foldable` structure like a `List` of key-value `Pair`s. `toPairs` provides a
+means to take an object and give you back a `List` of `Pairs` that have a
+`String` that represents the key in the `fst` and the value for that key in the
+`snd`. The primitive values are copied, while non-primitive values are
+references. Like most of the `Object` functions in `crocks`, any keys with
+`undefined` values will be omitted from the result. `crocks` provides an inverse
+to this function named [`fromPairs`][frompairs].
+
+```javascript
+import compose from 'crocks/helpers/compose'
+import map from 'crocks/pointfree/map'
+import merge from 'crocks/Pair/merge'
+import toPairs from 'crocks/Pair/toPairs'
+
+// record :: Object
+const record = {
+ firstName: 'Joey',
+ lastName: 'Fella',
+ age: 34
+}
+
+// joinField :: (String, a) -> String
+const joinField = (key, value) =>
+ `${key}:${value}`
+
+// joinRecord :: List String -> String
+const joinRecord = list =>
+ list.toArray()
+ .join('|')
+
+// buildRecord :: Object -> String
+const buildRecord = compose(
+ joinRecord,
+ map(merge(joinField)),
+ toPairs
+)
+
+buildRecord(record)
+//=> "firstName:Joey|lastName:Fella|age:34"
+```
+
+
+
+
+
+## Pointfree Functions
+
+#### fst (pointfree)
+
+`crocks/Pair/fst`
+
+```haskell
+fst :: Pair a b -> a
+```
+
+The `fst` pointfree function is used extract the leftmost value of a `Pair` by
+invoking the [`fst`](#fst) method on a given instance, returning the result.
+`fst` takes a `Pair` as its only argument and returns the value wrapped in the
+leftmost portion of the provided `Pair`.
+
+```javascript
+import Pair from 'crocks/Pair'
+
+import flip from 'crocks/combinators/flip'
+import fst from 'crocks/Pair/fst'
+import ifElse from 'crocks/logic/ifElse'
+import merge from 'crocks/Pair/merge'
+import snd from 'crocks/Pair/snd'
+
+// lte :: (Number, Number) -> Boolean
+const lte =
+ (y, x) => x <= y
+
+// min :: Pair Number Number -> Number
+const min = ifElse(
+ merge(flip(lte)),
+ fst,
+ snd
+)
+
+min(Pair(1, 2))
+//=> 1
+
+min(Pair(45, 22))
+//=> 22
+
+min(Pair(100, 100))
+//=> 100
+```
+
+#### merge (pointfree)
+
+`crocks/Pair/merge`
+
+```haskell
+merge :: ((a, b) -> c) -> Pair a b -> c
+```
+
+The pointfree `merge` function allows the ability to fold out a new value, using
+a binary function to combine the two values into one. This function takes (2)
+arguments, with the first being a binary function used to combine a `Pair`s
+values and the second is the instance of `Pair` for the function to be applied.
+Like the method on `Pair`, this function will return the result of the provided
+binary function.
+
+```javascript
+import Pair from 'crocks/Pair'
+
+import assoc from 'crocks/helpers/assoc'
+import compose from 'crocks/helpers/compose'
+import curry from 'crocks/helpers/curry'
+import map from 'crocks/pointfree/map'
+import merge from 'crocks/Pair/merge'
+
+// mergeObj :: Pair String a -> Object -> Object
+const mergeObj =
+ merge(assoc)
+
+// inc :: Number -> Number
+const inc =
+ x => x + 1
+
+// incAssign :: Pair String Number -> Object -> Object
+const incAssign = curry(
+ compose(mergeObj, map(inc))
+)
+
+incAssign(Pair('apples', 5), {})
+// { apples: 6 }
+
+incAssign(
+ Pair('num', 57),
+ { string: 'a string' }
+)
+// { string: 'a string', num: 58 }
+```
+
+#### snd (pointfree)
+
+`crocks/Pair/snd`
+
+```haskell
+snd :: Pair a b -> b
+```
+
+The `snd` pointfree function is used extract the rightmost value of a `Pair` by
+invoking the [`snd`](#snd) method on a given instance, returning the result.
+`snd` takes a `Pair` as its only argument and returns the value wrapped in the
+rightmost portion of the provided `Pair`.
+
+```javascript
+import Pair from 'crocks/Pair'
+import Unit from 'crocks/Unit'
+
+import chain from 'crocks/pointfree/chain'
+import compose from 'crocks/helpers/compose'
+import map from 'crocks/pointfree/map'
+import snd from 'crocks/Pair/snd'
+
+// Box :: a -> Pair () a
+const Box =
+ x => Pair(Unit(), x)
+
+// unbox :: Pair a b -> b
+const unbox =
+ snd
+
+// add :: Number -> Number -> Number
+const add =
+ x => y => x + y
+
+// doubleBoxed :: Number -> Pair () Number
+const doubleBoxed =
+ m => Box(m * 2)
+
+// flow :: Number -> Number
+const flow = compose(
+ unbox,
+ chain(doubleBoxed),
+ map(add(10)),
+ Box
+)
+
+flow(10)
+//=> 40
+```
+
+
+
+
+
+## Transformation Functions
+
+#### writerToPair
+
+`crocks/Pair/writerToPair`
+
+```haskell
+writerToPair :: Monoid m => Writer m a -> Pair m a
+writerToPair :: Monoid m => (a -> Writer m b) -> a -> Pair m b
+```
+
+Used to transform a `Writer` instance to a `Pair` instance,
+`writerToPair` will take a given `Writer` and provide a new `Pair` with
+the `log` portion of the `Writer` in the first position and the `resultant`
+in the second.
+
+Like all `crocks` transformation functions, `writerToPair` has (2) possible
+signatures and will behave differently when passed either a `Writer` instance
+or a function that returns an instance of `Writer`. When passed the instance,
+a `Pair` instance is returned. When passed a `Writer` returning function,
+a function will be returned that takes a given value and returns an `Pair`.
+
+```javascript
+import Pair from 'crocks/Pair'
+import Sum from 'crocks/Sum'
+import Writer from 'crocks/Writer'
+
+import writerToPair from 'crocks/Pair/writerToPair'
+
+// SumWriter :: Writer Sum a
+const SumWriter =
+ Writer(Sum)
+
+// appendItem :: a -> [ a ] -> SumWriter [ a ]
+const appendItem = item => xs =>
+ SumWriter(1, xs.concat([ item ]))
+
+SumWriter(0, [])
+ .chain(appendItem('one'))
+ .chain(appendItem('two'))
+ .chain(appendItem('three'))
+//=> Writer (Sum 3) [ "one", "two", "three" ]
+
+writerToPair(SumWriter(2, 'result'))
+//=> Pair(Sum 2, 'result')
+
+Pair(Sum.empty(), [])
+ .chain(writerToPair(appendItem('one')))
+ .chain(writerToPair(appendItem('two')))
+ .chain(writerToPair(appendItem('three')))
+//=> Pair(Sum 3, [ "one", "two", "threimport
+```
+
+
+
+[fanout]: ../functions/helpers.html#fanout
+[frompairs]: ../functions/helpers.html#frompairs
+[identity]: ../functions/combinators.html#identity
diff --git a/docs/src/pages/docs/crocks/index.md b/docs/src/pages/docs/crocks/index.md
index 2f3752904..e832dd6e5 100644
--- a/docs/src/pages/docs/crocks/index.md
+++ b/docs/src/pages/docs/crocks/index.md
@@ -26,7 +26,7 @@ but what they do from type to type may vary.
| `IO` | `of` | `ap`, `chain`, `map`, `of`, `run` |
| `List` | `empty`, `fromArray`, `of` | `ap`, `chain`, `concat`, `cons`, `empty`, `equals`, `filter`, `head`, `map`, `of`, `reduce`, `reduceRight`, `reject`, `sequence`, `tail`, `toArray`, `traverse`, `valueOf` |
| [`Maybe`][maybe] | [`Nothing`][maybe-nothing], [`Just`][maybe-just], [`of`][maybe-of], [`zero`][maybe-zero] | [`alt`][maybe-alt], [`ap`][maybe-ap], [`chain`][maybe-chain], [`coalesce`][maybe-coalesce], [`concat`][maybe-concat], [`equals`][maybe-equals], [`either`][maybe-either], [`map`][maybe-map], [`of`][maybe-of], [`option`][maybe-option], [`sequence`][maybe-sequence], [`traverse`][maybe-traverse], [`zero`][maybe-zero] |
-| `Pair` | --- | `ap`, `bimap`, `chain`, `concat`, `equals`, `extend`, `fst`, `map`, `merge`, `of`, `sequence`, `snd`, `swap`, `traverse`, `toArray` |
+| [`Pair`][pair] | --- | [`ap`][pair-ap], [`bimap`][pair-bimap], [`chain`][pair-chain], [`concat`][pair-concat], [`equals`][pair-equals], [`extend`][pair-extend], [`fst`][pair-fst], [`map`][pair-map], [`merge`][pair-merge], [`sequence`][pair-sequence], [`snd`][pair-snd], [`swap`][pair-swap], [`traverse`][pair-traverse], [`toArray`][pair-toarray] |
| [`Pred`][pred] * | [`empty`][pred-empty] | [`concat`][pred-concat], [`contramap`][pred-contra], [`runWith`][pred-run], [`valueOf`][pred-value] |
| [`Reader`][reader] | [`ask`][reader-ask], [`of`][reader-of] | [`ap`][reader-ap], [`chain`][reader-chain], [`map`][reader-map], [`runWith`][reader-run] |
| [`ReaderT`][readert] | [`ask`][readert-ask], [`lift`][readert-lift], [`liftFn`][readert-liftfn], [`of`][readert-of] | [`ap`][readert-ap], [`chain`][readert-chain], [`map`][readert-map], [`runWith`][readert-run] |
@@ -82,6 +82,22 @@ but what they do from type to type may vary.
[equiv-compare]: Equiv.html#comparewith
[equiv-value]: Equiv.html#valueof
+[pair]: Pair.html
+[pair-ap]: Pair.html#ap
+[pair-bimap]: Pair.html#bimap
+[pair-chain]: Pair.html#chain
+[pair-concat]: Pair.html#concat
+[pair-equals]: Pair.html#equals
+[pair-extend]: Pair.html#extend
+[pair-fst]: Pair.html#fst
+[pair-map]: Pair.html#map
+[pair-merge]: Pair.html#merge
+[pair-sequence]: Pair.html#sequence
+[pair-snd]: Pair.html#snd
+[pair-swap]: Pair.html#swap
+[pair-traverse]: Pair.html#traverse
+[pair-toarray]: Pair.html#toarray
+
[pred]: Pred.html
[pred-empty]: Pred.html#empty
[pred-concat]: Pred.html#concat
diff --git a/docs/src/pages/docs/functions/helpers.md b/docs/src/pages/docs/functions/helpers.md
index 457a7bfbd..dbab0a0ef 100644
--- a/docs/src/pages/docs/functions/helpers.md
+++ b/docs/src/pages/docs/functions/helpers.md
@@ -57,23 +57,6 @@ if you need to constrain to more than (2) arguments, then you will want to reach
for [`nAry`](#nary). `binary` is basically syntactic sugar for `nAry(2, fn)`.
Also related is [`unary`](#unary), which constrains to (1) argument.
-#### branch
-
-`crocks/Pair/branch`
-
-```haskell
-branch :: a -> Pair a a
-```
-When you want to branch a computation into two parts, this is the function you
-want to reach for. All it does is let you pass in any `a` and will return you a
-`Pair` that has your value on both the first and second parameter. This allows
-you to work on the value in two separate computation paths. Be advised that this
-is Javascript and if `a` is an object type (`Object`, `Array`, `Date`, etc) they
-will reference each other.
-
-**Pro-Tip**: `Pair` provides a `merge` function that will let you fold the two
-values into a single value.
-
#### compose
`crocks/helpers/compose`
@@ -336,7 +319,7 @@ to the first portion of the underlying `Pair` and the second on the second.
fromPairs :: Foldable f => f (Pair String a) -> Object
```
-As an inverse to [`toPairs`](#topairs), `fromPairs` takes either an `Array` or
+As an inverse to [`toPairs`][topairs], `fromPairs` takes either an `Array` or
`List` of key-value `Pair`s and constructs an `Object` from it. The `Pair` must
contain a `String` in the `fst` and any type of value in the `snd`. The `fst`
will become the key for the value in the `snd`. All primitive values are copied
@@ -962,23 +945,6 @@ is passed along to the next step of your flow. This function does not guarantee
immutability for reference types (`Objects`, `Arrays`, etc), you will need to
exercise some discipline here to not mutate.
-#### toPairs
-
-`crocks/Pair/toPairs`
-
-```haskell
-toPairs :: Object -> List (Pair String a)
-```
-
-When dealing with `Object`s, sometimes it makes more sense to work in a
-`Foldable` structure like a `List` of key-value `Pair`s. `toPairs` provides a
-means to take an object and give you back a `List` of `Pairs` that have a
-`String` that represents the key in the `fst` and the value for that key in the
-`snd`. The primitive values are copied, while non-primitive values are
-references. Like most of the `Object` functions in `crocks`, any keys with
-`undefined` values will be omitted from the result. `crocks` provides an inverse
-to this function named [`fromPairs`](#frompairs).
-
#### tryCatch
`crocks/Result/tryCatch`
@@ -1024,3 +990,4 @@ represent some special value for a given type. This pointed use is the heart and
soul of the infamous `Maybe` type.
[safe]: ../crocks/Maybe.html#safe
+[topairs]: ../crocks/Pair.html#topairs
diff --git a/docs/src/pages/docs/functions/index.md b/docs/src/pages/docs/functions/index.md
index bf1fb90d6..307312429 100644
--- a/docs/src/pages/docs/functions/index.md
+++ b/docs/src/pages/docs/functions/index.md
@@ -67,7 +67,7 @@ need to account for for the rest of your flow.
| [`defaultTo`][defaultto] | `a -> b -> a` | `crocks/helpers/defaultTo` |
| [`dissoc`][dissoc] | `String -> Object -> Object` | `crocks/helpers/dissoc` |
| [`fanout`][fanout] | `(a -> b) -> (a -> c) -> (a -> Pair b c)` | `crocks/helpers/fanout` |
-| [`find`][find] | `Foldable f => ((a -> Boolean) | Pred) -> f a -> Maybe a` | `crocks/helpers/find` |
+| [`find`][find] | Foldable f => ((a -> Boolean) | Pred) -> f a -> Maybe a
| `crocks/helpers/find` |
| [`fromPairs`][frompairs] | `Foldable f => f (Pair String a) -> Object` | `crocks/helpers/fromPairs` |
| [`liftA2`][lifta2] | `Applicative m => (a -> b -> c) -> m a -> m b -> m c` | `crocks/helpers/liftA2` |
| [`liftA3`][lifta3] | `Applicative m => (a -> b -> c -> d) -> m a -> m b -> m c -> m d` | `crocks/helpers/liftA3` |
@@ -131,7 +131,7 @@ type: `Pred a` and vice-versa
[assign]: helpers.html#assign
[assoc]: helpers.html#assoc
[binary]: helpers.html#binary
-[branch]: helpers.html#branch
+[branch]: ../crocks/Pair.html#branch
[compose]: helpers.html#compose
[composek]: helpers.html#composek
[composep]: helpers.html#composep
@@ -170,7 +170,7 @@ type: `Pred a` and vice-versa
[safeafter]: ../crocks/Maybe.html#safeafter
[safelift]: ../crocks/Maybe.html#safelift
[tap]: helpers.html#tap
-[topairs]: helpers.html#topairs
+[topairs]: ../crocks/Pair.html#topairs
[trycatch]: helpers.html#trycatch
[unary]: helpers.html#unary
[unit]: helpers.html#unit
diff --git a/docs/src/pages/docs/functions/pointfree-functions.md b/docs/src/pages/docs/functions/pointfree-functions.md
index d39886c45..608bb1adb 100644
--- a/docs/src/pages/docs/functions/pointfree-functions.md
+++ b/docs/src/pages/docs/functions/pointfree-functions.md
@@ -68,11 +68,11 @@ accepted Datatype):
| `filter` | ((a -> Boolean) | Pred a) -> m a -> m a
| `crocks/pointfree` |
| `first` | `m (a -> b) -> m (Pair a c -> Pair b c)` | `crocks/pointfree` |
| `fold` | `Semigroup s => m s -> s` | `crocks/pointfree` |
-| `fst` | `m a b -> a` | `crocks/Pair` |
+| [`fst`][fst] | `m a b -> a` | `crocks/Pair` |
| `head` | `m a -> Maybe a` | `crocks/pointfree` |
| `log` | `m a b -> a` | `crocks/Writer` |
| `map` | `(a -> b) -> m a -> m b` | `crocks/pointfree` |
-| `merge` | `(a -> b -> c) -> m a b -> c` | `crocks/Pair` |
+| [`merge`][merge] | `(a -> b -> c) -> m a b -> c` | `crocks/Pair` |
| `option` | `a -> m a -> a` | `crocks/pointfree` |
| `promap` | `(c -> a) -> (b -> d) -> m a b -> m c d` | `crocks/pointfree` |
| `read` | `m a b -> Pair a b` | `crocks/Writer` |
@@ -83,7 +83,7 @@ accepted Datatype):
| `runWith` | `a -> m -> b` | `crocks/pointfree` |
| `second` | `m (a -> b) -> m (Pair c a -> Pair c b)` | `crocks/pointfree` |
| `sequence` | Applicative TypeRep t, Apply f => (t | (b -> f b)) -> m (f a) -> f (m a)
| `crocks/pointfree` |
-| `snd` | `m a b -> b` | `crocks/Pair` |
+| [`snd`][snd] | `m a b -> b` | `crocks/Pair` |
| `swap` | `(c -> d) -> (a -> b) -> m c a -> m b d` | `crocks/pointfree` |
| `tail` | `m a -> Maybe (m a)` | `crocks/pointfree` |
| `traverse` | Applicative TypeRep t, Apply f => (t | (c -> f c)) -> (a -> f b) -> m (f a) -> f (m b)
| `crocks/pointfree` |
@@ -93,29 +93,29 @@ accepted Datatype):
| Function | Datatypes |
|---|:---|
| `alt` | [`Async`][async-alt], `Either`, [`Maybe`][maybe-alt], `Result` |
-| `ap` | `Array`, [`Async`][async-ap], [`Const`][const-ap], `Either`, `Identity`, `IO`, `List`, [`Maybe`][maybe-ap], `Pair`, [`Reader`][reader-ap], `Result`, [`State`][state-ap], `Unit`, `Writer` |
-| `bimap` | [`Async`][async-bimap], `Either`, `Pair`, `Result` |
+| `ap` | `Array`, [`Async`][async-ap], [`Const`][const-ap], `Either`, `Identity`, `IO`, `List`, [`Maybe`][maybe-ap], [`Pair`][pair-ap], [`Reader`][reader-ap], `Result`, [`State`][state-ap], `Unit`, `Writer` |
+| `bimap` | [`Async`][async-bimap], `Either`, [`Pair`][pair-bimap], `Result` |
| `both` | [`Arrow`][arrow-both], `Function`, `Star` |
-| `chain` | `Array`, [`Async`][async-chain], [`Const`][const-chain], `Either`, `Identity`, `IO`, `List`, [`Maybe`][maybe-chain], `Pair`, [`Reader`][reader-chain], `Result`, [`State`][state-chain], `Unit`, `Writer` |
+| `chain` | `Array`, [`Async`][async-chain], [`Const`][const-chain], `Either`, `Identity`, `IO`, `List`, [`Maybe`][maybe-chain], [`Pair`][pair-chain], [`Reader`][reader-chain], `Result`, [`State`][state-chain], `Unit`, `Writer` |
| `coalesce` | [`Async`][async-coalesce], `Either`, [`Maybe`][maybe-coalesce], `Result` |
| `compareWith` | [`Equiv`][equiv-compare] |
-| `concat` | [`All`][all-concat], [`Any`][any-concat], `Array`, [`Assign`][assign-concat], [`Const`][const-concat], `Either`, [`Endo`][endo-concat], [`Equiv`][equiv-concat], [`First`][first-concat], `Identity`, [`Last`][last-concat], `List`, [`Max`][max-concat], [`Maybe`][maybe-concat], [`Min`][min-concat], `Pair`, [`Pred`][pred-concat], [`Prod`][prod-concat], `Result`, `String`, [`Sum`][sum-concat], `Unit` |
+| `concat` | [`All`][all-concat], [`Any`][any-concat], `Array`, [`Assign`][assign-concat], [`Const`][const-concat], `Either`, [`Endo`][endo-concat], [`Equiv`][equiv-concat], [`First`][first-concat], `Identity`, [`Last`][last-concat], `List`, [`Max`][max-concat], [`Maybe`][maybe-concat], [`Min`][min-concat], [`Pair`][pair-concat], [`Pred`][pred-concat], [`Prod`][prod-concat], `Result`, `String`, [`Sum`][sum-concat], `Unit` |
| `cons` | `Array`, `List` |
| `contramap` | [`Arrow`][arrow-contra], [`Equiv`][equiv-contra], [`Pred`][pred-contra], `Star` |
| `either` | `Either`, [`Maybe`][maybe-either], `Result` |
| `empty` | [`All`][all-empty], [`Any`][any-empty], `Array`, [`Assign`][assign-empty], [`Endo`][endo-empty], [`Equiv`][equiv-empty], [`First`][first-empty], [`Last`][last-empty], `List`, [`Max`][max-empty], [`Min`][min-empty], `Object`, [`Pred`][pred-empty], [`Prod`][prod-empty], `String`, [`Sum`][sum-empty], `Unit` |
-| `equals` | [`All`][all-equals], [`Any`][any-equals], `Array`, [`Assign`][assign-equals], `Boolean`, [`Const`][const-equals], `Either`, [`First`][first-equals], [`Last`][last-equals], `List`, [`Max`][max-equals], [`Maybe`][maybe-equals], [`Min`][min-equals], `Number`, `Object`, `Pair`, [`Prod`][prod-equals], `Result`, `String`, [`Sum`][sum-equals], `Unit`, `Writer` |
+| `equals` | [`All`][all-equals], [`Any`][any-equals], `Array`, [`Assign`][assign-equals], `Boolean`, [`Const`][const-equals], `Either`, [`First`][first-equals], [`Last`][last-equals], `List`, [`Max`][max-equals], [`Maybe`][maybe-equals], [`Min`][min-equals], `Number`, `Object`, [`Pair`][pair-equals], [`Prod`][prod-equals], `Result`, `String`, [`Sum`][sum-equals], `Unit`, `Writer` |
| [`evalWith`][eval] | [`State`][state-eval] |
| [`execWith`][exec] | [`State`][state-exec] |
-| `extend` | `Pair` |
+| `extend` | [`Pair`][pair-extend] |
| `filter` | `Array`, `List`, `Object` |
| `first` | [`Arrow`][arrow-first], `Function`, `Star` |
| `fold` | `Array`, `List` |
-| `fst` | `Pair` |
+| [`fst`][fst] | [`Pair`][pair-fst] |
| `head` | `Array`, `List`, `String` |
| `log` | `Writer` |
-| `map` | [`Async`][async-map], `Array`, [`Arrow`][arrow-map], [`Const`][const-map], `Either`, `Function`, `Identity`, `IO`, `List`, [`Maybe`][maybe-map], `Object`, `Pair`, [`Reader`][reader-map], `Result`, `Star`, [`State`][state-map], `Unit`, `Writer` |
-| `merge` | `Pair` |
+| `map` | [`Async`][async-map], `Array`, [`Arrow`][arrow-map], [`Const`][const-map], `Either`, `Function`, `Identity`, `IO`, `List`, [`Maybe`][maybe-map], `Object`, [`Pair`][pair-map], [`Reader`][reader-map], `Result`, `Star`, [`State`][state-map], `Unit`, `Writer` |
+| [`merge`][merge] | [`Pair`][pair-merge] |
| `option` | [`First`][first-option], [`Last`][last-option], [`Maybe`][maybe-option] |
| `promap` | [`Arrow`][arrow-pro], `Star` |
| `read` | `Writer` |
@@ -125,11 +125,11 @@ accepted Datatype):
| `run` | `IO` |
| `runWith` | [`Arrow`][arrow-run], [`Endo`][endo-run], [`Pred`][pred-run], [`Reader`][reader-run], `Star`, [`State`][state-run] |
| `second` | [`Arrow`][arrow-second], `Function`, `Star` |
-| `sequence` | `Array`, `Either`, `Identity`, `List`, [`Maybe`][maybe-sequence], `Pair`, `Result` |
-| `snd` | `Pair` |
-| `swap` | [`Async`][async-swap], `Either`, `Pair`, `Result` |
+| `sequence` | `Array`, `Either`, `Identity`, `List`, [`Maybe`][maybe-sequence], [`Pair`][pair-sequence], `Result` |
+| [`snd`][snd] | [`Pair`][pair-snd] |
+| `swap` | [`Async`][async-swap], `Either`, [`Pair`][pair-swap], `Result` |
| `tail` | `Array`, `List`, `String` |
-| `traverse` | `Array`, `Either`, `Identity`, `List`, [`Maybe`][maybe-traverse], `Pair`, `Result` |
+| `traverse` | `Array`, `Either`, `Identity`, `List`, [`Maybe`][maybe-traverse], [`Pair`][pair-traverse], `Result` |
| `valueOf` | [`All`][all-value], [`Any`][any-value], [`Assign`][assign-value], [`Const`][const-value], [`Endo`][endo-value], [`Equiv`][equiv-value], [`First`][first-value], `Identity`, [`Last`][last-value], [`Max`][max-value], [`Min`][min-value], [`Pred`][pred-value], [`Prod`][prod-value], [`Sum`][sum-value], `Unit`, `Writer` |
[all-concat]: ../monoids/All.html#concat
@@ -215,6 +215,20 @@ accepted Datatype):
[min-equals]: ../monoids/Min.html#equals
[min-value]: ../monoids/Min.html#valueof
+[pair-ap]: ../crocks/Pair.html#ap
+[pair-bimap]: ../crocks/Pair.html#bimap
+[pair-concat]: ../crocks/Pair.html#concat
+[pair-chain]: ../crocks/Pair.html#chain
+[pair-equals]: ../crocks/Pair.html#equals
+[pair-extend]: ../crocks/Pair.html#extend
+[pair-fst]: ../crocks/Pair.html#fst
+[pair-map]: ../crocks/Pair.html#map
+[pair-merge]: ../crocks/Pair.html#merge
+[pair-sequence]: ../crocks/Pair.html#sequence
+[pair-snd]: ../crocks/Pair.html#snd
+[pair-swap]: ../crocks/Pair.html#swap
+[pair-traverse]: ../crocks/Pair.html#traverse
+
[pred-concat]: ../crocks/Pred.html#concat
[pred-contra]: ../crocks/Pred.html#contramap
[pred-empty]: ../crocks/Pred.html#empty
@@ -245,3 +259,7 @@ accepted Datatype):
[exec]: ../crocks/State.html#execwith-pointfree
[eval]: ../crocks/State.html#evalwith-pointfree
+
+[fst]: ../crocks/Pair.html#fst-pointfree
+[merge]: ../crocks/Pair.html#merge-pointfree
+[snd]: ../crocks/Pair.html#snd-pointfree