Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/hojberg/seidr
A collection of general purpose Sum Types and Monads built on top of hojberg/sums-up
https://github.com/hojberg/seidr
Last synced: 2 months ago
JSON representation
A collection of general purpose Sum Types and Monads built on top of hojberg/sums-up
- Host: GitHub
- URL: https://github.com/hojberg/seidr
- Owner: hojberg
- Created: 2019-02-12T17:16:59.000Z (almost 6 years ago)
- Default Branch: main
- Last Pushed: 2023-03-04T05:08:01.000Z (almost 2 years ago)
- Last Synced: 2024-04-13T16:20:36.915Z (8 months ago)
- Language: TypeScript
- Homepage:
- Size: 1.41 MB
- Stars: 9
- Watchers: 3
- Forks: 6
- Open Issues: 13
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Seidr
> In Old Norse, seiðr was a type of sorcery practiced in Norse society during
> the Late Scandinavian Iron Age. The practice of seiðr is believed to be a form
> of magic relating to both the telling and shaping of the future.A collection of general purpose Sum Types and monads built on top of [hojberg/sums-up](https://github.com/hojberg/sums-up)
## Maybe
```ts
import { Just, Nothing } from 'seidr';Just("Loki").caseOf({
Nothing: () => "N/A",
Just: name => `Hello ${name}`,
}); // => "Hello Loki"Nothing().caseOf({
Nothing: () => "N/A",
Just: name => `Hello ${name}`,
}); // => "N/A"// Map doesn't run on Nothing
Just("Loki").map(name => name.toUpperCase()); // => Just("LOKI")
Nothing().map(name => name.toUpperCase()); // => Nothing()// flatMap unnests a layer when the mapper returns a Maybe
Just("Loki").flatMap(name => Just(name.toUpperCase())); // => Just("LOKI")
Nothing().flatMap(name => Just(name.toUpperCase())); // => Nothing()
```## Result
```ts
import { Ok, Err } from 'seidr';Ok("Loki").caseOf({
Err: err => err,
Ok: name => `Hello ${name}`,
}); // => "Hello Loki"Err("oops").caseOf({
Err: err => err
Just: (name) => `Hello ${name}`,
}); // => "oops"// Map doesn't run on Err
Ok("Loki").map(name => name.toUpperCase()); // => Just("LOKI")
Err("oops").map(name => name.toUpperCase()); // => Err("oops")// flatMap unnests a layer when the mapper returns a Result
Ok("Loki").flatMap(name => Ok(name.toUpperCase())); // => Ok("LOKI")
Err("oops").flatMap(name => Ok(name.toUpperCase())); // => Err("oops")// Result and Maybe are not isomorphic as "oops" is lost when converting Err to Nothing
Ok("Loki").toMaybe(); // => Just("Loki")
Err("oops").toMaybe(); // => Nothing()
```## AsyncResult
An `AsyncResult` is a hybrid of a `Result` and a `Promise`,
with the type safety and convenience methods of the former, but the ability
to capture a not-necessarily-evaluated-yet value of the latter.An `AsyncResult` can be constructed from a `Promise` with an
appropriate function to convert the promise's `unknown` error value to an `L`.There are also `AsyncOk` and `AsyncErr` functions available as shorthand,
though in practice these are less frequently useful.```ts
import { AsyncResult, AsyncOk, AsyncErr } from 'seidr';////////////////////////////////////
// Constructing an AsyncResultconst myPromise: Promise<{ name: string }> = /* ... */;
AsyncResult.fromPromise(err => new Error(String(err)), myPromise);
// => AsyncResult////////////////////////////////////
// Using an AsyncResult// `caseOf` always returns a promise
AsyncOk("Loki").caseOf({
Err: err => err,
Ok: name => `Hello ${name}`,
}); // => Promise { : "Hello Loki" }AsyncErr("oops").caseOf({
Err: err => err,
Ok: (name) => `Hello ${name}`,
}); // => Promise { : "oops" }// `map` doesn't run on Err
AsyncOk("Loki").map(name => name.toUpperCase()); // => AsyncOk("LOKI")
AsyncErr("oops").map(name => name.toUpperCase()); // => AsyncErr("oops")// `flatMap` unnests a layer when the mapper returns a Result, AsyncResult or Promise
AsyncOk("Loki").flatMap(name => Ok(name.toUpperCase())); // => AsyncOk("LOKI")
AsyncOk("Loki").flatMap(name => AsyncOk(name.toUpperCase())); // => AsyncOk("LOKI")
AsyncOk("Loki").flatMap(async name => Ok(name.toUpperCase())); // => AsyncOk("LOKI")
AsyncErr("oops").flatMap(name => Ok(name.toUpperCase())); // => AsyncErr("oops")// `toPromise` returns promise that resolves on Ok or rejects on Err
// A `Promise` and an `AsyncResult` are isomorphic at runtime,
// as the error value isn't lost; only the type information is.
AsyncOk("Loki").toPromise(); // Promise { : "Loki" }
AsyncErr("oops").toPromise(); // Promise { : "oops" }
```## Effect
```ts
import { Effect } from 'seidr';const fooEff = Effect(() => "foo") // Effect("foo")
fooEff.unsafePerform() // => 'foo'
// Map doesn't run on Err
fooEff.map(val => val.toUpperCase()); // => Effect("FOO")// flatMap unnests a layer when the mapper returns an Effect
fooEffect.flatMap(val => Effect(() => val + 'bar'); // => Effect("foobar")
```## RemoteData
A sums-up implementation of the original pattern described by Kris Jenkins:
http://blog.jenkster.com/2016/06/how-elm-slays-a-ui-antipattern.htmlThis is a helpful sum type for modelling data being fetched from the network.
```typescript
type RemoteData = NotAsked | Loading | Failure | Success
``````typescript
import { RemoteData, NotAsked, Loading, Failure, Success } from 'seidr';NotAsked().caseOf({
NotAsked: () => "not asked",
_: () => "everything else",
}); // => "not asked"Loading().caseOf({
Loading: () => "loading",
_: () => "everything else",
}); // => "loading"Failure("oops").caseOf({
Failure: err => err
_: () => "everything else",
}); // => "oops"Success("Yay").caseOf({
Success: data => data
_: () => "everything else",
}); // => "yay"// Map only runs on Success
Succecss("Loki").map(name => name.toUpperCase()); // => Just("LOKI")
Failure("oops").map(name => name.toUpperCase()); // => Failure("oops")
Loading().map(name => name.toUpperCase()); // => Loading()
NotAsked().map(name => name.toUpperCase()); // => NotAsked()// flatMap unnests a layer when the mapper returns a Result when run on Success
Succecss("Loki").map(name => Success(name.toUpperCase())); // => Just("LOKI")
Failure("oops").map(name => Success(name.toUpperCase())); // => Failure("oops")
Loading().map(name => Success(name.toUpperCase())); // => Loading()
NotAsked().map(name => Success(name.toUpperCase())); // => NotAsked()
```