How to unwrap Monads for return statements that expect a value?
See original GitHub issueIs your feature request related to a problem? Please describe. In my use case I would like to use functional programming techniques, using ramda for a functional library and Crocks for an algebraic data structure library to write code in a not fully functional codebase. No one else on my team has any familiarity with Functional Programming and I’m new to it myself. I want to be able to pull values out of monads so I can return normal values in a codebase that’s not functional in nature and slowly add more functional elements. I’m typically going to be using Either, IO, and Maybe monads to write my code, then extract the final result out of the resulting monad so I can return the value to a function that is not made to accept monads yet.
Describe the solution you’d like Folktale has a function called getOrElse which will return a value or an undefined/error string. This is super useful and allows me to write functionally in an environment that does not expect to handle monads. For example, I can make some Results/Either monads, chain them together and then carefully unwrap the value for possible return. I get some functioal benefits with a small amount of impurity at the end of my function. Does Crocks have something similar or is there another way I can unwrap Either, IO, or Maybe with an internal function?
Describe alternatives for how you do this now My current workaround is just to use Folktale, but the maintainer has mentioned that they don’t have the bandwidth to maintain the project anymore. Folktale also has a limited amount of monads for me to use.
Code
const simpleFunction = (a) => {
myMaybe = Maybe.of(a);
// some random transformations on myMaybe
// this will fall back to the second case if the maybe is empty
return myMaybe.getOrElse() || doSomethingElseOnError();
}
Additional context I also made a stackoverflow with this question, but could not tag it properly because I don’t have enough reputation to add a Crocks tag.
Thanks in advance for your advice or feedback!
Issue Analytics
- State:
- Created 3 years ago
- Comments:11 (5 by maintainers)
Top GitHub Comments
@JustinHoyt very nice. So a here are a couple of pointers to get you started.
Result
inside of theIO
, this will limit ALL interactions with the process arguments to theResult
lift
functions usually take instances of Applicatives as opposed to functions. You can use things likefanout/merge
orconverge
/compose2
for pushing the results of functions into thelift
.lift
alift
so that both effects are applied. Kinda like doingmap(map(fn))
like we do forFunctor
composition, but instead of covarient Functors, these are Applicative Functors.run
function is on the instance, as opposed to theTypeRep
, so it would have beenresult.run()
With those points in mind, i came up with something like this:
EDIT: Oh, also take note of the
Array.of
in that compose on theErr
side. This is becauseString
is aMonoid
andResult
accumulatesMonoid
s in theErr
forApplicative
interaction. If both params where invalid, it wouldconcat
the twoString
s. By throwing the value into anArray
, it will accumulate the errors in separate entries.@evilsoft Seeing how you make a simple reusable function with validateEither blows my mind haha. I also didn’t know about bimap so that’s a super useful function to just learn! Thanks for the example, it’s helping me identify opportunities to create generic reusable functions.
On a side note, I learned what I know about functional programming entirely from Professor Frisby’s Mostly Adequate Guide to Functional Programming. It’s a wonderful book, but I’m curious if you’d recommend any other readings or series to improve my functional programming in JS. I just found your ADT video series, so I’ll try to work through that this weekend and next.