Skip to content

Instantly share code, notes, and snippets.

@evilsoft
Last active August 28, 2018 22:57
Show Gist options
  • Save evilsoft/7a48449bb42084bd43aa4e62d907060e to your computer and use it in GitHub Desktop.
Save evilsoft/7a48449bb42084bd43aa4e62d907060e to your computer and use it in GitHub Desktop.
const {
bimap, compose, composeK, fanout, isNumber,
liftA2, map, merge, prop, safe
} = require('crocks')
const {
add, multiply
} = require('ramda')
/////////////////////////////////////////////////////////////////
// `fanout ` takes a single value and splits it into a Pair with
// the result of the value run through each function in in both the
// left and right portions. The left postion is the result of the
// first function and the right is the second.
//
// We use (2) functions each one pulling a seperate key. With this
// code we are doing the same validation, just against a different key.
// We could process and validate each one in a different way, as long
// as they return the same Applicative.
//
// Once we have our values in the Pair, and they are seperated, we can
// manipulate each one independently. Notice the left value and its effect
// is not dependent on the right and vice-versa. To show this we use
// a contrived add10 to the left and double the right. But this can be anything
// including chaining in another Maybe check/effect or spliting it again and
// combining into another result.
//
// Then, when all is said and done we can use the `merge` function in crocks
// which will take a function and apply the Pair to its arguments, merging
// the branches. The function we use is liftA2 that will take the (2),
// loosly related Maybes and combine them under addition. But not only will
// it combine those values using the function, it will also combine any effects
// generated from their processing. So in the case of Maybe, it will return
// Nothing if something horrible happened.
//
// But this is generic for ALL Applicatives, for Async/Flutre it will combine
// Async values (non-dependent webcalls, like calls to many different services)
// and their success/failure. State will comnine State transactions, returns a
// result based only on the shared environment and nothing else, etc.
// Whatever the effect is, this pattern will combine them.
//
// Contrast this with Monads that combine sequential, dependent values; do this
// and then this and then that, one after the other. Both combine effects, but one
// is sequential and the other is parallel.
/////////////////////////////////////////////////////////////////
const data = {
a: 34,
b: 99
}
// propNumber :: String -> Object -> Maybe Object
const propNumber = key =>
composeK(safe(isNumber), prop(key))
// work :: a -> Maybe Number
const work = compose(
merge(liftA2(add)),
bimap(map(add(10)), map(multiply(2))),
fanout(propNumber('a'), propNumber('b'))
)
work(data)
//=> Just 242
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment