All Projects → mikechabot → maybe-baby

mikechabot / maybe-baby

Licence: MIT license
Minimize defensive coding. A JavaScript implementation of the Maybe monad.

Programming Languages

javascript
184084 projects - #8 most used programming language
typescript
32286 projects

Labels

Projects that are alternatives of or similar to maybe-baby

future.scala
Stack-safe asynchronous programming
Stars: ✭ 38 (-9.52%)
Mutual labels:  monad
elixir-control
An exploratory look into functors, applicatives, and monads for Elixir
Stars: ✭ 21 (-50%)
Mutual labels:  monad
kotlin-monads
Monads for Kotlin
Stars: ✭ 114 (+171.43%)
Mutual labels:  monad
Design-Patterns
Project for learning and discuss about design patterns
Stars: ✭ 16 (-61.9%)
Mutual labels:  monad
fnts
λ Minimal Functional Programming Utilities for TypeScript & JavaScript
Stars: ✭ 75 (+78.57%)
Mutual labels:  monad
J-Curry
A Java library that enables applying Functional Programming concepts like currying and partial application for functions, also it supports types like Either, Try, etc... using RxJava 2 interfaces, compatible with Java 7 and above
Stars: ✭ 17 (-59.52%)
Mutual labels:  monad
Each
A macro library that converts native imperative syntax to scalaz's monadic expressions
Stars: ✭ 245 (+483.33%)
Mutual labels:  monad
freAST
Fast, simple Free Monads using ScalaMeta macro annotations. Port of Freasy-Monad.
Stars: ✭ 14 (-66.67%)
Mutual labels:  monad
LLVM-JVM
[W.I.P] A Just-In-Time Java Virtual Machine written in Haskell
Stars: ✭ 22 (-47.62%)
Mutual labels:  monad
function-composition-cheatsheet
Composition of Functions
Stars: ✭ 24 (-42.86%)
Mutual labels:  monad
functional-structures-refactoring-kata
Starting code and proposed solution for Functional Structures Refactoring Kata
Stars: ✭ 31 (-26.19%)
Mutual labels:  monad
hymn
Hy Monad Notation - a monad library for Hy
Stars: ✭ 47 (+11.9%)
Mutual labels:  monad
free-monad-java
Free Monad in Java
Stars: ✭ 27 (-35.71%)
Mutual labels:  monad
freedsl
Practical effect composition library based on abstract wrapping type and the free monad
Stars: ✭ 37 (-11.9%)
Mutual labels:  monad
sealed-monad
Scala library for nice business logic oriented, for-comprehension-style error handling
Stars: ✭ 16 (-61.9%)
Mutual labels:  monad
Mtl
The Monad Transformer Library
Stars: ✭ 252 (+500%)
Mutual labels:  monad
UnderstandingLanguageExt
This is a tutorial that aims to demonstrate the practical fundamentals behind using LanguageExt in a fashion though step-by-step tutorials which introduce and then build up on concepts.
Stars: ✭ 73 (+73.81%)
Mutual labels:  monad
30minLearningJavaScriptMonad
30分でわかるJavaScriptプログラマのためのモナド入門
Stars: ✭ 15 (-64.29%)
Mutual labels:  monad
bullet-scala
A monadic library to resolve object relations with the aim of avoiding the N+1 query problem.
Stars: ✭ 53 (+26.19%)
Mutual labels:  monad
operational
Implement monads by specifying instructions and their desired operational semantics.
Stars: ✭ 77 (+83.33%)
Mutual labels:  monad

maybe-baby

2.x will be maintained, however, if possible for your repository, you should opt to use TypeScript's optional chaining, which was introduced in 3.7

Minimize defensive coding. A JavaScript implementation of the Maybe monad.

npm version build status coverage status dependency status devDependency status

Install

  • npm install --save maybe-baby
  • yarn add maybe-baby

Getting Started

What if we need the zipCode of the user below, which lives on the address object?

const user = { 
  email: '[email protected]',
  address: null,
  name: {
     first: 'John',
     last: null,
     middle: null
  }
};

Accessing it via dot notation will result in an error:

const zipCode = user.address.zipCode;  // Uncaught TypeError: Cannot read property 'zipCode' of undefined

Possible Solutions?

  1. Write some ugly null checks that don't scale well:
const getZipCode = (user) => {
  if (user !== null && user !== undefined) {
    if (user.address !== null && user.address !== undefined) {
      return user.address.zipCode
    }
  }
}
  1. Use _.get() or something similar, but these libraries have large footprints, and most likely won't be implementing the monadic structure.

  2. Wait for optional chaining to be approved in ECMA, or use babel-plugin-transform-optional-chaining.

  3. Use TypeScript's optional chaining

A Better Solution?

  1. Use maybe-baby to minimize defensive coding:
import Maybe from 'maybe-baby';

// Use a function getter
const getZipCode = (user) => Maybe.of(() => user.address.zipCode).join();

Now we can safely get the zipCode without worrying about the shape of the object, or encountering TypeErrors:

const zipCode = getZipCode(user);
console.log(zipCode);  // undefined

Docs

Documentation generated via JSDoc.


Migrating from 1.x to 2.x

Breaking changes were introduced in 2.0.0; the following redundant function were removed.

Maybe.of() can replicate the behavior of prop, props, and path.

prop(val: string | number)

const obj = Maybe.of({ 
  foo: { 
    bar: [123, 456] 
  } 
});

// Incorrect
const bar = obj.prop("foo").join(); // { bar: [123, 456] }

// Correct
Maybe.of(() => obj.join().foo).join(); // { bar: [123, 456] }

// Incorrect
obj
  .prop("foo")
  .prop("bar")
  .prop(1)
  .join(); // 456

// Correct
Maybe.of(() => obj.join().foo.bar[1]).join() // 456

props(...args)

const obj = Maybe.of({
  foo: 'bar',
  baz: [1,2,3]
});

// Incorrect
obj.props('baz', 0).join(); // 1

// Correct
Maybe.of(() => obj.join().baz[0]).join(); // 1

props(val: string)

const obj = Maybe.of({
  foo: 'bar',
  baz: [1,2,3]
});

// Incorrect
obj.path('baz.0').join() // 1

// Correct
Maybe.of(() => obj.join().baz[0]).join(); // 1

API

Check out the API below, or the complete documentation.

of(val: unknown | OfTypeFunc<T>)

Accepts a value of any type, and returns a monad:

const str = Maybe.of('foo');
const num = Maybe.of(123);
const bool = Maybe.of(true);
const obj = Maybe.of({});
const arr = Maybe.of([]);
const empty = Maybe.of(null);
const undef = Maybe.of(undefined);

Accepts a function, and sets the function's return value as the monad's value, returns a monad.

If the function results in an error, the monad's value is set to undefined.

type OfTypeFunc<T> = () => T;

const user = {};
const mZipCode = Maybe.of(() => user.address.zipCode);

console.log(mZipCode.join()); // undefined

isJust(): boolean

Returns true if the value is not null or undefined:

Maybe.of(123).isJust();   // true
Maybe.of(null).isJust();  // false

isNothing(): boolean

Returns true if the value is null or undefined:

Maybe.of(123).isNothing();   // false
Maybe.of(null).isNothing();  // true

join(): T

Returns the value:

Maybe.of(123).join();   // 123
Maybe.of(null).join();  // null

orElse(defaultValue: unknown): Maybe

Chain to the end of a monad to return as the default value if isNothing() is true:

Maybe.of(undefined)
  .orElse('No Value')
  .join();  // 'No Value'

map(transform: (val: T) => T | Maybe<T>): Maybe

Apply a transformation to the monad, and return a new monad:

const val = 1;
const newVal = Maybe.of(val).map(val => val + 1);

newVal.join(); // 2;

chain(chain: (val: T) => Maybe<T>): Maybe

Chain together functions that return Maybe monads:

function addOne (val) {
  return Maybe.of(val + 1);
}

const three = Maybe.of(1)
 .chain(addOne)
 .chain(addOne);

 three.join(); // 3

Credit

Credit to James Sinclair for writing The Marvellously Mysterious JavaScript Maybe Monad.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].