Recently I have decided to switch from lodash to ramda to play with functional way of composing my logic. I love it! After some extensive digging into FP I have found that's it's not only about handy pure/point free utilities (ramda), but more about complex (at least for me) math abstractions (fantasy-land). I don't get all of it, but Either and Task pattern looks very handy. Problem is that I am not sure how to merge it with ramda utilities. I know about ramda-fantasy, but it's no longer maintained. Ramda-fantasy suggested libraries doesn't work the same way as ramda-fantasy. With all this new information about Monads/Monoids/Functors types I am completely lost.
For example, what the convention for this?
Right('boo')
.map(x => x + '!')
.map(x => x.toUpperCase())
vs
R.pipe(
R.map(x => x + '!')
R.map(x => x.toUpperCase())
)(Right('boo'))
Am I don't need ramda If I will decide to switch to Monads all the way?
One way to think about it is to think about types versus functions.
Ramda offers a large collection of utility functions. They operate on arrays, on objects, on functions, on strings, on numbers, etc. But they also operate on user-defined types. So in your example,
R.map
operates on anything which matches the Functor specification. If the implementation ofEither
you use matches that specification, then Ramda'smap
will operate on it.But Ramda does not supply types. It works with the built-in types such as Object, Array, Function, etc. But -- arguably outside
Lens
-- it does not supply any types of its own. Libraries such as Folktale provide large collections of types, such asMaybe
,Result
,Validation
,Task
andFuture
; more dedicated ones such as Fluture provide powerful versions of one specific type (Future
). All of these types implement the Functor specification. A very incomplete list of such implementations is supplied by FantasyLand.These two notions, functions on an abstract type and collections of types are complementary. A Ramda function which works on any functor will work on whatever version of Either you use (so long as it matches the specification.) More on this relationship is in this StackOverflow Q+A.
The question compared these two snippets:
and
But neither is how I would think of the problem from a Ramda perspective. Ramda is all about functions. It supplies functions and expects you to use them to build more sophisticated functions, and then to use those to build even higher level functions.
If we wrote this function:
or perhaps this version
Then this function is now available to use on many types. For example:
The first three -- Array, Object, and Function implementations -- are supplied by Ramda. But the others still work since Ramda interoperates with the FantasyLand Functor specification. And it will work if you supply your own
map
method on your type (or even better afantasy-land/map
method.)So no, you don't need Ramda to work with Monads or with other abstract types. You can work directly with their implementation. But Ramda offers some nice ways to interoperate with them in a generic manner.