-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #24 from VKTRenokh/develop
either
- Loading branch information
Showing
28 changed files
with
739 additions
and
216 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@victorenokh/maybe.ts": patch | ||
--- | ||
|
||
Rename filterOrElse method to ensureOrElse |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@victorenokh/maybe.ts": minor | ||
--- | ||
|
||
Implemented either monad, changed monads structure |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@victorenokh/maybe.ts": minor | ||
--- | ||
|
||
Added toMaybe, fromMaybe util functions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,151 +1,12 @@ | ||
# Maybe Monad In Typescript | ||
# @victorenokh/maybe.ts | ||
|
||
maybe monad implementation in typescript with great types and some utils | ||
# Installation | ||
To install the stable version: | ||
`npm i @victorenokh/maybe.ts` | ||
|
||
# Examples | ||
- [Maybe](./examples/maybe.md) | ||
- [Either](./examples/either.md) | ||
|
||
## .map() | ||
```ts | ||
maybe(42).map(num => num * 2).map(console.log) // Output: 84 | ||
``` | ||
## .tap() | ||
``` ts | ||
maybe(42).tap(console.log).map(num => num * 2).tap(console.log) // Output: 42 then 84 | ||
|
||
``` | ||
|
||
## .mapNullable() | ||
```ts | ||
const getOrNothing = (num) => num > 2 ? null : num | ||
|
||
const a = maybe(4).map(getOrNothing) // type is Maybe<number | null> | ||
const a = maybe(4).mapNullable(getOrNothing) // type is Maybe<number> | ||
``` | ||
|
||
## .asyncMap() | ||
```ts | ||
const sleep = (ms: number): Promise<number> => | ||
new Promise((res) => setTimeout(() => res(ms), ms)); | ||
|
||
maybe(1000) | ||
.asyncMap((ms) => sleep(ms)) | ||
.then((maybeTime) => { | ||
maybeTime.map(console.log); // 1000 after 1 second | ||
}); | ||
``` | ||
|
||
## .flatMap() | ||
```ts | ||
maybe(42).flatMap((num) => maybe(num + 5)).map(console.log) // 47 | ||
|
||
const getNumber = () => Math.random() > 0.5 ? 1 : undefined | ||
|
||
maybe(42) | ||
.flatMap((num) => | ||
undefinedToMaybe(getNumber()).map((secondNum) => secondNum + num), | ||
) | ||
.map(console.log) // 43 or nothing | ||
``` | ||
|
||
## .equals() | ||
```ts | ||
const a = maybe(24) | ||
const b = maybe(24) | ||
const c = maybe('Hello!') | ||
|
||
console.log(a.equals(b)) // true | ||
console.log(a.equals(c)) // false | ||
``` | ||
|
||
|
||
## .getOrElse() | ||
```ts | ||
const value = maybe<string>(null).getOrElse('default string') // value is 'default string' | ||
const value1 = maybe<string>('some string').getOrElse('default string') // value is 'some string' | ||
``` | ||
|
||
## .flatGetOrElse() | ||
```ts | ||
const value = maybe<number>(null).flatGetOrElse(maybe(42)) // value is 42 | ||
const value = maybe(53).flatGetOrElse(maybe(42)) // value is 42 | ||
``` | ||
|
||
## .merge() | ||
```ts | ||
const a = maybe('something') | ||
const b = maybe('something again') | ||
|
||
const merged = a.merge(b).map(console.log) // { left: "something", right: "something again" } | ||
``` | ||
if something doesn't have value | ||
```ts | ||
const a = maybe<string>(null) | ||
const b = maybe('something again') | ||
|
||
const merged = a.merge(b).map(console.log) // nothing happens | ||
``` | ||
|
||
## undefinedToMaybe() | ||
```ts | ||
const getNumberOrUndefined = () => Math.random() > 0.5 ? 5 : undefined | ||
|
||
const number = undefinedToMaybe(getNumberOrUndefined()) | ||
|
||
number.map(console.log) // 5 or nothing | ||
``` | ||
|
||
## merge() | ||
```ts | ||
const a = maybe(5) | ||
const b = maybe('hello') | ||
const c = maybe({someKey: 'someValue'}) | ||
|
||
const merged = merge(a, b, c) // type is Maybe<[number, string, {someKey: 'someValue'}]> | ||
|
||
merged.map(console.log) // [5, 'hello', { someKey: 'someValue' }] or if some maybe is nothing, nothing going to happen | ||
``` | ||
|
||
# mergeMap() | ||
```ts | ||
const add = (a: number, b: number) => a + b | ||
|
||
const a = maybe(5) | ||
const b = maybe(100) | ||
|
||
const final = mergeMap(a, b, add) | ||
|
||
final.map(console.log) // 105 or if some maybe is nothing, nothing going to happen | ||
``` | ||
|
||
# call() | ||
```ts | ||
const mfn = maybe(() => console.log('hello world')) | ||
|
||
mfn.map(call) // hello world | ||
``` | ||
|
||
# or() | ||
```ts | ||
const a = maybe<number>(null) | ||
const b = maybe(5) | ||
const c = maybe(6) | ||
|
||
const final = or(a, b, c) | ||
|
||
final.map(console.log) // 5 | ||
``` | ||
|
||
# fromThrowable() | ||
```ts | ||
const throwable = (num: number) => { | ||
if (num > 0.5) { | ||
throw new Error('number is greater than 0.5') | ||
} | ||
|
||
return ':)' | ||
} | ||
|
||
const something = fromThrowable(throwable) | ||
|
||
something(Math.random()).tap(console.log) // :) or nothing | ||
``` | ||
# License | ||
The MIT License (MIT) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# Either Examples | ||
## .map() | ||
```ts | ||
E.right(1) | ||
.map(double) | ||
.fold(() => {}, console.log) // Output: 2 | ||
``` | ||
|
||
## .flatMap() | ||
```ts | ||
const getMoreThan = ( | ||
num: number, | ||
): E.Either<string, number> => { | ||
const random = Math.random() | ||
|
||
if (random > num) { | ||
return E.left(`random is greater than ${num}`) | ||
} | ||
|
||
return E.right(random) | ||
} | ||
|
||
getMoreThan(0.5) | ||
.flatMap((num) => getMoreThan(num + 0.01)) | ||
.fold(console.error, console.log) // random number, or error in console | ||
``` | ||
|
||
## .isRight() | ||
```ts | ||
console.log(left('test').isRight()) // Output: false | ||
console.log(right('test').isRight()) // Output: true | ||
``` | ||
|
||
## .isLeft() | ||
```ts | ||
console.log(left('test').isLeft()) // Output: true | ||
console.log(right('test').isLeft()) // Output: false | ||
``` | ||
|
||
## .ensureOrElse() | ||
```ts | ||
const user = { | ||
has2Fa: true, | ||
name: '12', | ||
} | ||
|
||
const validate = (u: typeof user) => u.has2Fa | ||
const validateName = (u: typeof user) => u.name.length >= 3 | ||
|
||
const a: Either<string, typeof user> = right(user) | ||
|
||
const b = a | ||
.ensureOrElse(validate, () => 'user does not have 2 fa') | ||
.ensureOrElse( | ||
validateName, | ||
() => 'user name is too small', | ||
) | ||
|
||
b.fold( | ||
(e) => console.error(e), | ||
(b) => console.log(b), | ||
i) // Output: user name is too small | ||
``` | ||
|
||
## toMaybe() | ||
```ts | ||
toMaybe(left<string, number>('left')).tap(console.log) // nothing happens | ||
toMaybe(right<number, string>(50)).tap(console.log) // Output: 50 | ||
``` | ||
|
||
## fromMaybe() | ||
```ts | ||
fromMaybe(of(50), 'maybe is nothing').fold( | ||
console.error, | ||
console.log, | ||
) // Output: 50 | ||
|
||
fromMaybe(none<number>(), 'maybe is nothing').fold( | ||
console.error, | ||
console.log, | ||
) // Output: error maybe is nothing | ||
``` |
Oops, something went wrong.