🥃 Pratica
Functional Programming for Pragmatists
Why is this for pragmatists you say?
Pratica sacrifices some common FP guidelines in order to provide a simpler and more approachable API that can be used to accomplish your goals quickly - while maintaining data integrity and saftey, through algrebraic data types.
Install
With yarn
yarn add pratica
or if you prefer npm
npm i pratica
Documentation
Table of Contents
Monads
Maybe
Use this when dealing with nullable and unreliable data that needs actions performed upon.
Maybe is great for making sure you do not cause runtime errors by accessing data that is not there because of unexpected nulls or undefineds.
Every Maybe can either be of type Just
or Nothing
. When the data is available, it is wrapped with Just
, if the data is missing, it is Nothing
. The examples below should clarify futher.
Maybe.map
Map is used for running a function on the data inside the Maybe. Map will only run the function if the Maybe type is Just
. If it's Nothing, the map will short circuit and be skipped.
const person = name: 'Jason' age: 4 // Example with real data // Example with null data // Maybe type is Nothing, so this function is skipped // Maybe type is Nothing, so this function is skipped
Maybe.chain
Chain is used when you want to return another Maybe when already inside a Maybe.
const person = name: 'Jason' age: 4 // p.height does not exist so Maybe returns a Nothing type, any .map, .chain, or .ap after a Nothing will be short circuited // this func won't even run because height is Nothing, so `undefined * 2.2` will never execute, preventing problems.
Maybe.default
Default is a clean way of making sure you always return a Just with some default data inside.
// Example with default data // won't run // won't run // the data is null so 99 is the default
Maybe.ap
Sometime's working with Maybe can be reptitive to always call .map
whenever needing to a apply a function to the contents of the Maybe. Here is an example using .ap
to simplify this.
Goal of this example, to perform operations on data inside the Maybe, without unwrapping the data with .map
or .chain
// Need something like this// Maybe(6) + Maybe(7) = Maybe(13) // no function to apply
Maybe.inspect
Inspect is used for seeing a string respresentation of the Maybe. It is used mostly for Node logging which will automatically call inspect() on objects that have it, but you can use it too for debugging if you like.
const log = console // `Just(86)` // `Just('HELLO')` // `Nothing` // `Nothing`
Maybe.cata
Cata is used at the end of your chain of computations. It is used for getting the final data from the Maybe. You must pass an object to .cata
with 2 properties, Just
and Nothing
(capitalization matters), and both those properties must be a function. Those functions will run based on if the the computations above it return a Just or Nothing data type.
Cata stands for catamorphism and in simple terms means that it extracts a value from inside any container.
const isOver6Feet = personheight > 6 ? : Nothing
Maybe.isJust
isJust returns a boolean representing the type of the Maybe. If the Maybe is a Just type then true is returned, if it's a Nothing, returns false.
const isOver6Feet = height > 6 ? : Nothing const log = console // true // false
Maybe.isNothing
isNothing returns a boolean representing the type of the Maybe. If the Maybe is a Just type then false is returned, if it's a Nothing, returns true.
const isOver6Feet = height > 6 ? : Nothing const log = console // false // true
Result
Use this when dealing with conditional logic. Often a replacment for if statements - or for simplifying complex logic trees. A Result can either be an Ok
or an Err
type.
Result.map
const person = name: 'jason' age: 4
Result.chain
const person = name: 'Jason' age: 4 const isPerson = pname && page ? : const isOlderThan2 = page > 2 ? : const isJason = pname === 'jason' ? :
Result.mapErr
You can also modify errors that may return from any result before getting the final result, by using .mapErr
or .chainErr
.
// ignored because it's an error
Result.chainErr
// ignored because it's an error
Result.swap
Use .swap()
to convert an Err to an Ok, or an Ok to an Err.
Result.bimap
Use .bimap()
for easily modifying an Ok or an Err. Shorthand for providing both .map
and .mapErr
Result.ap
// Need something like this// Ok(6) + Ok(7) = Ok(13) // no function to apply
Result.inspect
const log = console // `Ok(86)` // `Ok('HELLO')` // `Err('Something happened')` // `Err(404)`
Result.cata
const isOver6Feet = personheight > 6 ? :
Result.isOk
const isOver6Feet = height > 6 ? : const log = console // true // false
Result.isErr
const isOver6Feet = height > 6 ? : const log = console // false // true
Utilities
parseDate
Safely parse date strings. parseDate returns a Maybe monad.
const goodDate = '2019-02-13T21:04:10.984Z'const badDate = '2019-02-13T21:04:1' // it's a maybe, so you can use chain/default/ap
encase
Safely run functions that may throw an error or crash. encase returns a Maybe type (so Just or Nothing).
const throwableFunc = JSON // this func doesn't throw, so Just is called // this function throws an error so Nothing is called
encaseRes
Safely run functions that may throw an error or crash. encaseRes returns a Result type (so Ok or Err). Similar to encase
but the Err returns the error message.
const throwableFunc = JSON // this func doesn't throw, so Ok is called // this function throws an error so Err is called
justs
Filter out any non-Just data type from an array
const data = 1 true Nothing // returns [Just('hello')]
oks
Filter out any non-Ok data type from an array
const data = 1 true Nothing // returns [Ok('hey')]
get
Safely retrieve a nested property in an object. Returns a Maybe.
const data = name: 'jason' children: name: 'bob' name: 'blanche' children: name: 'lera' data
head
Safely get the first item in an array. Returns a Maybe.
const data = 512 // example with data // example with empty data
last
Safely get the last item in an array. Returns a Maybe.
const data = 512 // example with data // example with empty data
tail
Safely get the tail of an array (Everything except the first element). Returns a Maybe.
const data = 512 // example with data // example with empty data
tryFind
Safely try to retrieve an item from an array. Returns a Maybe.
const users = name: 'jason' age: 6 id: '123abc' name: 'bob' age: 68 id: '456def' users