https://github.com/mlms13/bs-nonempty
NonEmpty type with Array and List implementations for ReasonML and OCaml
https://github.com/mlms13/bs-nonempty
bucklescript collections functional-programming list nonemptylist ocaml reasonml
Last synced: 6 months ago
JSON representation
NonEmpty type with Array and List implementations for ReasonML and OCaml
- Host: GitHub
- URL: https://github.com/mlms13/bs-nonempty
- Owner: mlms13
- License: mit
- Created: 2018-09-03T23:11:44.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2018-10-23T04:40:45.000Z (almost 7 years ago)
- Last Synced: 2025-04-09T19:09:54.819Z (6 months ago)
- Topics: bucklescript, collections, functional-programming, list, nonemptylist, ocaml, reasonml
- Language: OCaml
- Homepage:
- Size: 86.9 KB
- Stars: 5
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# bs-nonempty
This small library provides implementations of `NonEmptyList` and `NonEmptyArray`: collection structures that guarantee you'll have at least one value. Additionally, you can build on top of the `NonEmptyBase` module to make a `NonEmpty*` version of your own collection type.
## Installation
**Install via npm:**
`npm install --save bs-nonempty`
**Update your bsconfig.json**
```
"bs-dependencies": [
"bs-nonempty"
],
```## Usage
The following demonstrates the API for using this library with `List`, but from these examples, it should be pretty easy to figure out how the `NonEmptyArray` version works.
**Construct a NonEmptyList**
For constructing a new `NonEmptyList.t`, you can use `make`, `pure`, `cons`, and `fromT`. You can turn your `NonEmptyList.t` into a `list` using `toT`. The signatures of those functions look like:
```reason
let make: ('a, list('a)) => NonEmptyList.t('a);
``````reason
let pure: ('a) => NonEmptyList.t('a);
let cons: ('a, NonEmptyList.t('a)) => NonEmptyList.t('a);
``````reason
let fromT: list('a) => option(NonEmptyList.t('a));
let toT: NonEmptyList.t('a) => list('a);
```You can use those functions like this:
```reason
/* "import" from NonEmptyList */
let (make, pure, cons, head, tail, fromT, toT) =
NonEmptyList(make, pure, cons, head, tail, fromT, toT);let myNel = pure(3);
head(myNel); /* 3 -- Note that this is not Some(3) */
tail(myNel); /* [] */make(3, [2, 1]) == cons(3, cons(2, pure(1)));
toT(make(3, [2, 1])) == [3, 2, 1];fromT(["A"]) == Some(make("A", [])) == Some(pure("A"));
fromT([]) == None;
```**Map, fold (reduce), and more**
```reason
let map: ('a => 'b, NonEmptyList.t('a)) => NonEmptyList.t('b);
let fold_left: (('a, 'b) => 'a, 'a, NonEmptyList.t('b)) => 'a;
let foldl1: (('a, 'a) => 'a, NonEmptyList.t('a)) => 'a;let myNel = make(0, [1, 2, 3, 4]);
map(string_of_int, myNel); /* == make("0", ["1", "2", "3", "4"]) */
fold_left((+), 0, myNel); /* 10 */
foldl1((+), myNel); /* 10 */
``````reason
let append: (NonEmptyList.t('a), NonEmptyList.t('a)) => NonEmptyList.t('a);
let join: (NonEmptyList.t(NonEmptyList.t('a))) => NonEmptyList.t('a);
let reverse: NonEmptyList.t('a) => NonEmptyList.t('a);
let length: NonEmptyList.t('a) => int;
```## Typeclasses
Note: If "semigroup" is a word that freaks you out, you can ignore this entire section. You already know more than enough to use this library. But if you're already familiar with `bs-abstract`, the following might come in handy.
`NonEmpty` is built on top of the great work in [bs-abstract](https://github.com/Risto-Stevcev/bs-abstract). Every `NonEmpty*` implementation (currently List and Array) is a member of the following typeclasses (which can be accessed like `NonEmptyList.Functor.map`):
- [MAGMA_ANY](https://github.com/Risto-Stevcev/bs-abstract/blob/v0.16.0/src/interfaces/Interface.re#L18-L21) and [SEMIGROUP_ANY](https://github.com/Risto-Stevcev/bs-abstract/blob/v0.16.0/src/interfaces/Interface.re#L25) with infix `append` (e.g. `NonEmptyList.Infix.(<:>)`)
- [FUNCTOR](https://github.com/Risto-Stevcev/bs-abstract/blob/v0.16.0/src/interfaces/Interface.re#L78-L81) with infix `map` (e.g. `NonEmptyList.Infix.(<$>)`)
- [APPLY](https://github.com/Risto-Stevcev/bs-abstract/blob/v0.16.0/src/interfaces/Interface.re#L83-L86) and [APPLICATIVE](https://github.com/Risto-Stevcev/bs-abstract/blob/v0.16.0/src/interfaces/Interface.re#L88-L91) with infix `apply` (e.g. `NonEmptyList.Infix.(<*>)`)
- [MONAD](https://github.com/Risto-Stevcev/bs-abstract/blob/v0.16.0/src/interfaces/Interface.re#L93-L96) with infix `flat_map` (e.g. `NonEmptyList.Infix.(>>=)`)Additionally, to roll your own `NonEmpty*` type, the underlying container type needs to be a member of [MONOID_ANY](https://github.com/Risto-Stevcev/bs-abstract/blob/v0.16.0/src/interfaces/Interface.re#L33-L36), [APPLICATIVE](https://github.com/Risto-Stevcev/bs-abstract/blob/v0.16.0/src/interfaces/Interface.re#L88-L91), and [FOLDABLE](https://github.com/Risto-Stevcev/bs-abstract/blob/v0.16.0/src/interfaces/Interface.re#L113-L122) (as well as provide implementations for `head`, `tail`, and `length` functions). See the implementations of `NonEmptyList` and `NonEmptyArray` for examples.
## Contributing
1. Fork and clone this repository
2. `npm install` to grab `bs-abstract` and any dev dependencies
3. Add features (and tests!) as appropriate
4. `npm run test`Here are some things worth contributing:
- `fold_right` implementation so we can be a member of `FOLDABLE`
- `EQ` if the underlying `'a` is a member of `EQ`
- `TRAVERSABLE` if the underlying `'a` is a member of `APPLICATIVE`
- docblock comments so we can automate the documentation
- Any extra utility functions or `NonEmptyOtherCollectionType` implementations## License
Released under the MIT license. See `LICENSE`.