Skip to content

Commit

Permalink
Add tupleToArray point free function (#354)
Browse files Browse the repository at this point in the history
* add tuple to array and spec
  • Loading branch information
jasminabasurita authored and dalefrancis88 committed Dec 3, 2018
1 parent e1d2484 commit 46f57ec
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 3 deletions.
10 changes: 10 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,16 @@
"contributions": [
"code"
]
},
{
"login": "jasminabasurita",
"name": "Jasmina Jacquelina",
"avatar_url": "https://avatars2.githubusercontent.com/u/4014487?v=4",
"profile": "http://jazzy.codes",
"contributions": [
"doc",
"code"
]
}
],
"repoType": "github"
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ Thanks goes to these wonderful people ([emoji key][emojis]):
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| [<img src="https://avatars0.githubusercontent.com/u/8260207?v=4" width="100px;"/><br /><sub><b>Karthik Iyengar</b></sub>](https://github.com/karthikiyengar)<br />[👀](#review-karthikiyengar "Reviewed Pull Requests") [💻](https://github.com/evilsoft/crocks/commits?author=karthikiyengar "Code") [📖](https://github.com/evilsoft/crocks/commits?author=karthikiyengar "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/7376957?v=4" width="100px;"/><br /><sub><b>Jon Whelan</b></sub>](https://github.com/jonwhelan)<br />[🐛](https://github.com/evilsoft/crocks/issues?q=author%3Ajonwhelan "Bug reports") [💻](https://github.com/evilsoft/crocks/commits?author=jonwhelan "Code") | [<img src="https://avatars0.githubusercontent.com/u/1466420?v=4" width="100px;"/><br /><sub><b>Benny Powers</b></sub>](http://bennypowers.com)<br />[📖](https://github.com/evilsoft/crocks/commits?author=bennypowers "Documentation") [💻](https://github.com/evilsoft/crocks/commits?author=bennypowers "Code") [👀](#review-bennypowers "Reviewed Pull Requests") | [<img src="https://avatars0.githubusercontent.com/u/1909325?v=4" width="100px;"/><br /><sub><b>Dale Francis</b></sub>](https://github.com/dalefrancis88)<br />[💻](https://github.com/evilsoft/crocks/commits?author=dalefrancis88 "Code") [👀](#review-dalefrancis88 "Reviewed Pull Requests") | [<img src="https://avatars1.githubusercontent.com/u/7926867?v=4" width="100px;"/><br /><sub><b>Premith</b></sub>](https://github.com/premithk)<br />[📖](https://github.com/evilsoft/crocks/commits?author=premithk "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/6302673?v=4" width="100px;"/><br /><sub><b>Dipen Bagia</b></sub>](https://github.com/dbagia)<br />[💡](#example-dbagia "Examples") | [<img src="https://avatars3.githubusercontent.com/u/5243925?v=4" width="100px;"/><br /><sub><b>Andrew Jones</b></sub>](https://github.com/ximenean)<br />[📖](https://github.com/evilsoft/crocks/commits?author=ximenean "Documentation") |
| [<img src="https://avatars0.githubusercontent.com/u/4858051?v=4" width="100px;"/><br /><sub><b>W. K. Seymour III</b></sub>](https://github.com/wayneseymour)<br />[📖](https://github.com/evilsoft/crocks/commits?author=wayneseymour "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/11702749?v=4" width="100px;"/><br /><sub><b>Eliseu Benedito Codinhoto</b></sub>](https://youtube.com/euprogramadoroficial)<br />[📖](https://github.com/evilsoft/crocks/commits?author=zeucxb "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/12712867?v=4" width="100px;"/><br /><sub><b>NiallArkEnergy</b></sub>](https://github.com/NiallArkEnergy)<br />[💻](https://github.com/evilsoft/crocks/commits?author=NiallArkEnergy "Code") [📖](https://github.com/evilsoft/crocks/commits?author=NiallArkEnergy "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/3265934?v=4" width="100px;"/><br /><sub><b>vidyu</b></sub>](https://github.com/vidyu)<br />[📖](https://github.com/evilsoft/crocks/commits?author=vidyu "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/780521?v=4" width="100px;"/><br /><sub><b>Michael Wolfenden</b></sub>](http://michael-wolfenden.github.io)<br />[📖](https://github.com/evilsoft/crocks/commits?author=michael-wolfenden "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/14071356?v=4" width="100px;"/><br /><sub><b>Johan Codinha</b></sub>](https://github.com/JohanCodinha)<br />[🐛](https://github.com/evilsoft/crocks/issues?q=author%3AJohanCodinha "Bug reports") | [<img src="https://avatars0.githubusercontent.com/u/450220?v=4" width="100px;"/><br /><sub><b>Matt Ross</b></sub>](http://www.mattross.io)<br />[💻](https://github.com/evilsoft/crocks/commits?author=amsross "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/4014487?v=4" width="100px;"/><br /><sub><b>Jasmina Jacquelina</b></sub>](http://jazzy.codes)<br />[📖](https://github.com/evilsoft/crocks/commits?author=jasminabasurita "Documentation") [💻](https://github.com/evilsoft/crocks/commits?author=jasminabasurita "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->

### Course/Videos
Expand Down
39 changes: 38 additions & 1 deletion docs/src/pages/docs/crocks/Tuple.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Tuple"
description: "Tuple Crock"
layout: "guide"
functions: ["nmap"]
functions: ["nmap", "tupletoarray"]
weight: 150
---

Expand Down Expand Up @@ -474,3 +474,40 @@ trimap(add(10), toUpper, add(10), triple)
```

</article>

<article id="topic-transformation">

## Transformation Functions

#### tupleToArray

`crocks/Tuple/tupleToArray`

```haskell
tupleToArray :: Tuple a -> [ a ]
tupleToArray :: (a -> Tuple b) -> a -> [ b ]
```

Used to transform a given `Tuple` instance to an `Array` instance.

Like all `crocks` transformation functions, `tupleToArray` has two possible
signatures and will behave differently when passed either
a `Tuple` instance or a function that returns an instance
of `Tuple`. When passed the instance, a transformed `Array` is
returned. When passed a `Tuple` returning function, a function will
be returned that takes a given value and returns an `Array`.

```javascript
import Tuple from 'crocks/Tuple'
import tupleToArray from 'crocks/Tuple/tupleToArray'
import constant from 'crocks/combinators/constant'

const Triple = Tuple(3)

const triple = Triple( 1, { key: 'value' }, 'string' )

tupleToArray(triple) // => [ 1, { key: 'value' }, 'string' ]

tupleToArray(constant(triple))() // => [ 1, { key: 'value' }, 'string' ]
```
</article>
5 changes: 4 additions & 1 deletion docs/src/pages/docs/functions/transformation-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Transformation Functions"
description: "Transformation Functions API"
layout: "notopic"
functions: ["arraytolist", "asyncToPromise", "eithertoasync", "eithertofirst", "eithertolast", "eithertomaybe", "eithertoresult", "firsttoasync", "firsttoeither", "firsttolast", "firsttomaybe", "firsttoresult", "lasttoasync", "lasttoeither", "lasttofirst", "lasttomaybe", "lasttoresult", "listtoarray", "maybetoasync", "maybetoeither", "maybetofirst","maybetolast", "maybetoresult", "resulttoasync", "resulttoeither", "resulttofirst", "resulttolast", "resulttomaybe", "writertopair"]
functions: ["arraytolist", "asyncToPromise", "eithertoasync", "eithertofirst", "eithertolast", "eithertomaybe", "eithertoresult", "firsttoasync", "firsttoeither", "firsttolast", "firsttomaybe", "firsttoresult", "lasttoasync", "lasttoeither", "lasttofirst", "lasttomaybe", "lasttoresult", "listtoarray", "maybetoasync", "maybetoeither", "maybetofirst","maybetolast", "maybetoresult", "resulttoasync", "resulttoeither", "resulttofirst", "resulttolast", "resulttomaybe", "tupletoarray", "writertopair"]
weight: 60
---

Expand Down Expand Up @@ -165,6 +165,7 @@ bad
| [`resultToFirst`][result-first] | `Result e a -> First a` | `(a -> Result e b) -> a -> First b` | `crocks/First` |
| [`resultToLast`][result-last] | `Result e a -> Last a` | `(a -> Result e b) -> a -> Last b` | `crocks/Last` |
| [`resultToMaybe`][result-maybe] | `Result e a -> Maybe a` | `(a -> Result e b) -> a -> Maybe b` | `crocks/Maybe` |
| [`tupleToArray`][tuple-array] | `Tuple a -> [ a ]` | `(a -> Tuple b) -> a -> [ b ]` | `crocks/Tuple` |
| `writerToPair` | `Writer m a -> Pair m a` | `(a -> Writer m b) -> a -> Pair m b` | `crocks/Pair` |

[async-promise]: ../crocks/Async.html#asynctopromise
Expand Down Expand Up @@ -195,6 +196,8 @@ bad
[maybe-last]: ../monoids/Last.html#maybetolast
[result-last]: ../monoids/Last.html#resulttolast

[tuple-array]: ../crocks/Tuple.html#tupletoarray

[maybe]: ../crocks/Maybe.html
[nothing]: ../crocks/Maybe.html#nothing
[either]: ../crocks/Either.html
Expand Down
5 changes: 4 additions & 1 deletion src/Tuple/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ function _Tuple(n) {
throw new TypeError('Tuple: First argument must be an integer')
}

const tupleLength = constant(n)

const type =
constant(_type(n))

Expand All @@ -30,6 +32,7 @@ function _Tuple(n) {

const withProps = fn => {
fn.type = type
fn.tupleLength = tupleLength
fn['@@type'] = typeString
fn['@@implements'] = _implements([ 'map', 'concat', 'equals' ])
return fn
Expand Down Expand Up @@ -156,7 +159,7 @@ function _Tuple(n) {
return {
inspect, toString: inspect, merge,
project, mapAll, toArray,
type, equals,
tupleLength, type, equals,
map: map('map'),
concat: concat('concat'),
[fl.map]: map(fl.map),
Expand Down
18 changes: 18 additions & 0 deletions src/Tuple/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,24 @@ test('Tuple equals properties (Setoid)', t => {
t.end()
})

test('Tuple length functionality', t => {
const a = Tuple(2)({ deep: 'equals' }, [ 1 ])
const b = Tuple(3)({ deep: 'equals' }, [ 1 ], 8)
const c = Tuple(4)(1, 'space kitten', 'rainbow', 'unicorn')
const d = Tuple(2)
const e = Tuple(3)
const f = Tuple(4)

t.equal(a.tupleLength(), 2, 'returns tuple length when length is 2')
t.equal(b.tupleLength(), 3, 'returns tuple length when length is 3')
t.equal(c.tupleLength(), 4, 'returns tuple length when length is 4')
t.equal(d.tupleLength(), 2, 'returns tuple length when length is 2 and Tuple contains no data')
t.equal(e.tupleLength(), 3, 'returns tuple length when length is 3 and Tuple contains no data')
t.equal(f.tupleLength(), 4, 'returns tuple length when length is 4 and Tuple contains no data')

t.end()
})

test('Tuple merge', t => {
const m = Tuple(3)(1, 2, 3)
t.ok(isFunction(m.merge), 'provides a merge function')
Expand Down
30 changes: 30 additions & 0 deletions src/Tuple/tupleToArray.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/** @license ISC License (c) copyright 2018 original and current authors */
/** @author Jasmina Jacquelina (jasminabasurita) */

const curry = require('../core/curry')
const isFunction = require('../core/isFunction')

// tupleToArray : Tuple a -> [ a ]
// tupleToArray : (a -> Tuple b) -> a -> [ b ]
function tupleToArray(tuple) {
if(isFunction(tuple)) {
return function(x) {
const m = tuple(x)

if(!isFunction(m.tupleLength)) {
throw new TypeError('tupleToArray: Tuple returning function required')
}

return m.toArray()
}
}

if(isFunction(tuple.tupleLength)) {
return tuple.toArray()
}

throw new TypeError('tupleToArray: Tuple or Tuple returning function required')
}

module.exports = curry(tupleToArray)

125 changes: 125 additions & 0 deletions src/Tuple/tupleToArray.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
const test = require('tape')
const helpers = require('../test/helpers')

const bindFunc = helpers.bindFunc

const Tuple = require('.')

const List = require('../core/List')
const isArray = require('../core/isArray')
const isFunction = require('../core/isFunction')

const identity = x => x

const tupleToArray = require('./tupleToArray')

test('tupleToArray transform', t => {
const f = bindFunc(tupleToArray)

t.ok(isFunction(tupleToArray), 'is a function')

t.throws(f(undefined), TypeError, 'throws if arg is undefined')
t.throws(f(null), TypeError, 'throws if arg is null')
t.throws(f(0), TypeError, 'throws if arg is a falsey number')
t.throws(f(1), TypeError, 'throws if arg is a truthy number')
t.throws(f(''), TypeError, 'throws if arg is a falsey string')
t.throws(f('string'), TypeError, 'throws if arg is a truthy string')
t.throws(f(false), TypeError, 'throws if arg is false')
t.throws(f(true), TypeError, 'throws if arg is true')
t.throws(f({}), TypeError, 'throws if arg is an object')
t.throws(f(List.fromArray([ 1,2,3 ])), TypeError, 'throws if arg is a different crock')

t.end()
})

test('tupleToArray with 3-Tuple', t => {
const data = [ 24, { triple: 'tuple' }, '56' ]
const Triple = Tuple(3)
const triple = Triple(...data)

const a = tupleToArray(triple)

t.ok(isArray(a), 'returns an Array from Tuple')
t.same(a, data, 'preserves the structure of underlying data')

t.end()
})

test('tupleToArray with 4-Tuple', t => {
const data = [ 24, { triple: 'tuple' }, '56', [ 1 ] ]
const Tuple4 = Tuple(4)
const tuple = Tuple4(...data)

const a = tupleToArray(tuple)

t.ok(isArray(a), 'returns an Array from Tuple')
t.same(a, data, 'preserves the structure of underlying data')

t.end()
})

test('tupleToArray with 5-Tuple', t => {
const data = [ 25, { triple: 'tuple' }, '56', [ 1 ], 80 ]
const Tuple5 = Tuple(5)
const tuple = Tuple5(...data)

const a = tupleToArray(tuple)

t.ok(isArray(a), 'returns an Array from Tuple')
t.same(a, data, 'preserves the structure of underlying data')

t.end()
})

test('tupleToArray with 6-Tuple', t => {
const data = [ 25, { triple: 'tuple' }, '66', [ 1 ], 80, 2 ]
const Tuple6 = Tuple(6)
const tuple = Tuple6(...data)

const a = tupleToArray(tuple)

t.ok(isArray(a), 'returns an Array from Tuple')
t.same(a, data, 'preserves the structure of underlying data')

t.end()
})

test('tupleToArray with 7-Tuple', t => {
const data = [ 25, { triple: 'tuple' }, '77', [ 1 ], 80, 2, 3 ]
const Tuple7 = Tuple(7)
const tuple = Tuple7(...data)

const a = tupleToArray(tuple)

t.ok(isArray(a), 'returns an Array from Tuple')
t.same(a, data, 'preserves the structure of underlying data')

t.end()
})

test('tupleToArray with Tuple returning function', t => {
const f = bindFunc(tupleToArray(identity))

t.throws(f(undefined), TypeError, 'throws if function returns undefined')
t.throws(f(null), TypeError, 'throws if function returns null')
t.throws(f(0), TypeError, 'throws if function returns a falsey number')
t.throws(f(1), TypeError, 'throws if function returns a truthy number')
t.throws(f(''), TypeError, 'throws if function returns a falsey string')
t.throws(f('string'), TypeError, 'throws if function returns a truthy string')
t.throws(f(false), TypeError, 'throws if function returns false')
t.throws(f(true), TypeError, 'throws if function returns true')
t.throws(f({}), TypeError, 'throws if function returns an object')
t.throws(f([]), TypeError, 'throws if function returns an array')

const data = [ 24, { triple: 'tuple' }, '56' ]
const Triple = Tuple(3)
const triple = Triple(...data)

const m = tupleToArray(identity, triple)

t.ok(isArray(m), 'returns an Array from a function returning a Tuple')
t.same(m, data, 'preserves the structure of underlying data')

t.end()
})

1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ const transforms = {
resultToFirst: require('./First/resultToFirst'),
resultToLast: require('./Last/resultToLast'),
resultToMaybe: require('./Maybe/resultToMaybe'),
tupleToArray: require('./Tuple/tupleToArray'),
writerToPair: require('./Pair/writerToPair')
}

Expand Down
2 changes: 2 additions & 0 deletions src/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ const resultToEither = require('./Either/resultToEither')
const resultToFirst = require('./First/resultToFirst')
const resultToLast = require('./Last/resultToLast')
const resultToMaybe = require('./Maybe/resultToMaybe')
const tupleToArray = require('./Tuple/tupleToArray')
const writerToPair = require('./Pair/writerToPair')

test('entry', t => {
Expand Down Expand Up @@ -438,6 +439,7 @@ test('entry', t => {
t.equal(crocks.resultToFirst, resultToFirst, 'provides the resultToFirst transform')
t.equal(crocks.resultToLast, resultToLast, 'provides the resultToLast transform')
t.equal(crocks.resultToMaybe, resultToMaybe, 'provides the resultToMaybe transform')
t.equal(crocks.tupleToArray, tupleToArray, 'provides the tupleToArray transform')
t.equal(crocks.writerToPair, writerToPair, 'provides the writerToPair transform')

t.end()
Expand Down

0 comments on commit 46f57ec

Please sign in to comment.