Last active
August 28, 2018 22:57
-
-
Save evilsoft/7a48449bb42084bd43aa4e62d907060e to your computer and use it in GitHub Desktop.
This file contains hidden or 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
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