## Implements

`Setoid`

, `Semigroup`

, `Functor`

, `Bifunctor`

, `Apply`

, `Chain`

,`Traversable`

, `Extend`

`Pair a b`

`Pair`

allows the ability to represent two 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 two 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`

, `merge`

and`fanout`

. Using those helpers in conjunction with the ability to`bimap`

functions over a given `Pair`

s values.

```
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/pointfree/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
```

`Setoid`

, `Semigroup`

, `Functor`

, `Bifunctor`

, `Apply`

, `Chain`

,`Traversable`

, `Extend`

`Pair :: (a, b) -> Pair a b`

In order to construct a `Pair`

, two values of any type are required by the constructor. The types of the arguments can, and often do, vary. None of the constructors in crocks are curried by default, so both arguments must be provided at the same time in order to construct the `Pair`

.

Once both arguments are provided, the constructor will return a new `Pair`

instance with the first argument in the left portion and the second argument in the right position.

```
import Pair from 'crocks/Pair'
Pair(34, false)
//=> Pair Number Boolean
Pair(34, Pair(true, 'string'))
//=> Pair Number (Pair Boolean String)
```

`Pair a b ~> c -> Boolean`

Used to compare the underlying values of two `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`

.

```
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
```

`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`

instancewrapping the result of combining the underlying `Semigroup`

instances.

```
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/Pair/fanout'
import flip from 'crocks/combinators/flip'
import getProp from 'crocks/Maybe/getProp'
import map from 'crocks/pointfree/map'
import mapReduce from 'crocks/helpers/mapReduce'
import option from 'crocks/pointfree/option'
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), getProp(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 )
```

`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`

can be used instead.

```
import Pair from 'crocks/Pair'
import compose from 'crocks/helpers/compose'
import map from 'crocks/pointfree/map'
import merge from 'crocks/pointfree/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 }
```

`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`

can be used to apply these transformations, `bimap`

allows for independent transformations on both sides, in parallel.

`bimap`

takes two 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`

. If the need arises to map the first portion exclusively, use `bimap`

passing the mapping function to the first argument and an `identity`

to the second.

```
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/pointfree/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
```

`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.

```
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 )
```

`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 anadditional requirement, is that instances of the same `Semigroup`

must occupy the first position of the source `Pair`

and the `Pair`

returned by the function.

```
const Pair = require('crocks/Pair')
const setProp = require('crocks/helpers/setProp')
const omit = require('crocks/helpers/omit')
// addTmp :: (String, a, Object) -> Pair [ String ] Object
const addTmp = (key, value, x) =>
Pair([ key ], setProp(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 setProp('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 }
```

```
Apply f => Pair a (f b) ~> (c -> f c) -> f (Pair a b)
Applicative f => Pair a (f b) ~> TypeRep f -> 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`

by passing it an`identity`

function (`x => x`

).

```
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")
```

```
Apply f => Pair a b ~> ((d -> f d), (b -> f c)) -> f (Pair a c)
Applicative f => Pair a b ~> (TypeRep f, (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`

.

The `traverse`

method 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`

.

```
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
```

`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.

```
import Pair from 'crocks/Pair'
import extend from 'crocks/pointfree/extend'
import merge from 'crocks/pointfree/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" })
```

`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 two 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`

functions can be used in one or both arguments.

```
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")
```

`Pair a b ~> () -> a`

`fst`

is one of two 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`

is the other projection function provided and is used to extract the value in the second position.

```
import Pair from 'crocks/Pair'
Pair('left', 'right')
.fst()
//=> "left"
```

`Pair a b ~> () -> b`

`snd`

is one of two 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`

is the other projection function provided and is used to extract the value in the first position.

```
import Pair from 'crocks/Pair'
Pair('left', 'right')
.snd()
//=> "right"
```

`Pair a b ~> () -> [ a, b ]`

While both `fst`

and `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.

```
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 }
```

`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`

or [`fanout`

][fanout] helper functions.

```
import Sum from 'crocks/Sum'
import compose from 'crocks/helpers/compose'
import fanout from 'crocks/Pair/fanout'
import merge from 'crocks/pointfree/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
```

`crocks/Pair/branch`

`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.

```
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/pointfree/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 }
```

`crocks/Pair/fanout`

```
fanout :: (a -> b) -> (a -> c) -> (a -> Pair b c)
fanout :: Arrow a b -> Arrow a c -> Arrow a (Pair b c)
fanout :: Monad m => Star a (m b) -> Star a (m c) -> Star a (m (Pair b c))
```

There are may times that you need to keep some running or persistent state while performing a given computation. A common way to do this is to take the input to the computation and branch it into a `Pair`

and perform different operations on each version of the input. This is such a common pattern that it warrants the `fanout`

function to take care of the initial split and mapping. Just provide a pair of either simple functions or a pair of one of the computation types (`Arrow`

or `Star`

). You will get back something of the same type that is configured to split it's input into a pair and than apply the first Function/ADT to the first portion of the underlying `Pair`

and the second on the second.

```
import compose from 'crocks/helpers/compose'
import fanout from 'crocks/Pair/fanout'
import getProp from 'crocks/Maybe/getProp'
import liftA2 from 'crocks/helpers/liftA2'
import map from 'crocks/pointfree/map'
import Maybe from 'crocks/Maybe'
import merge from 'crocks/Pair/merge'
import sequence from 'crocks/pointfree/sequence'
// Person :: { first: String, last: String }
// people :: [Person]
const people = [
{ first: 'Ziggy', last: 'Stardust' },
{ first: 'Lizard', last: 'King' }
]
// concat :: String -> String -> String
const concat = a => b => `${a} ${b}`
// join :: String -> [a] -> String
const join = sep => arr => arr.join(sep)
// getName :: Person -> String
const getName = compose(
merge(liftA2(concat)),
fanout(getProp('first'), getProp('last'))
)
// getPersons :: [Person] -> String
const getPersons = compose(
map(join(', ')),
sequence(Maybe),
map(getName)
)
getPersons(people)
//=> Just "Ziggy Stardust, Lizard King"
```

`crocks/Pair/toPairs`

`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`

.

```
import compose from 'crocks/helpers/compose'
import map from 'crocks/pointfree/map'
import merge from 'crocks/pointfree/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"
```

`crocks/Pair/fst`

`fst :: Pair a b -> a`

The `fst`

pointfree function is used extract the leftmost value of a `Pair`

by invoking the `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`

.

```
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/pointfree/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
```

`crocks/Pair/snd`

`snd :: Pair a b -> b`

The `snd`

pointfree function is used extract the rightmost value of a `Pair`

by invoking the `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`

.

```
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
```

`crocks/Pair/writerToPair`

```
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 or flatten a `Pair`

of `Writer`

into an `Pair`

when chained, `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 two 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`

.

```
import Pair from 'crocks/Pair'
import Sum from 'crocks/Sum'
import Writer from 'crocks/Writer'
import fanout from 'crocks/helpers/fanout'
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", "three"])
fanout(Sum, x => appendItem(x)([ x ]), 1)
.chain(writerToPair)
```

Contribute on Github! Edit this section.