isJust & fromJust
JonathanILevi opened this issue · 5 comments
I do not see in the docs a isJust
or fromJust
(potential to throw but unless isJust
was checked) nor isNothing
. Even the pure Haskell has theme functions.
The primary importance (for me) is that values passed around are explicit but how I implement a function is not where errors arise. The fact that a value is a Maybe is obvious (or will raise obvious errors). My function should be able to deal with that logically without needing to get into callback functions (JavaScript does not even have do
notation to make things at least look better). I give up compile time type safety/checking by using isJust
and fromJust
, but wait, JS is not statically typed anyway.
It is true I likely may never use isJust
or fromJust
and have the simple alternative with the other functions. But I am unwilling to start using a library without complete definitions (if I want to get a value from a Just
(regardless of whether I theoretically should (even Haskell has performUnsafeIO
!)) how can I do it?).
Thanks,
Jonathan
Hey @JonathanILevi, Thanks for the suggestion. I've seen things like isJust
implemented by creating a func using either
const isJust =
either(constant(false), constant(true))
for the fromJust
i'd be hesitant in suggesting it's addition or usage. Maybe
has two great options that you can use to define fallback values, option
and alt
. option
allows you to fold out the value while specify the value you want to use if the Maybe
is a Nothing
. alt
is for when you want to keep within the Maybe
container and have an alternative Maybe
value, if the original Maybe
is a Nothing
then the alt
method will return the given Maybe
otherwise it'll just return the current value inside a new instance of Maybe
Most of the time, if not all of the time, you don't want to think about it as needing to check if it is a Just
or a Nothing
you have your container that you can map
or chain
etc over and then fold
it out when ready
@JonathanILevi
Personally, I see those "theme" functions as bloat and while we use Haskell for some reference and provide some functions with the same name (fanout
, fst
, etc), we try not to let their choices influence what we provide in the library.
As far as your need for these functions, could you provide an example of where you would find them useful?
While it is a bummer that you feel this library is not complete without those two functions or theme functions, there are other libs out there like Sanctuary that do provide those functions and may feel more complete to you.
I totally agree with "most of the time, if not all of the time", but is it all the time or only most of the time? Unless you can mathematically prove that it is in-fact "all of the time" then the library is not turing-complete. I am actually sure that you can prove that you never need the fromJust
but even if you can, do I need a masters degree in order to solve it, or could it cause a speed bottle neck (even the turing machine is turing complete)?
There are 3 places that I see fromJust
potential being used:
- When I was first getting into the pure/functional style (with Haskell) I did use
fromJust
a couple times. Did I need to? no; I could go back now and obviously see how I should to it correctly. If I were forced to learn that then I might have given up. HavingfromJust
shallows the learning curve. - Deep nesting. I had a piece of in Haskell where I had a chain of functions which alternated creating
Maybe
s andIO
s. I could not simply monad them together with>>=
or even in ado
block. I had to have nested blocks withsequence
s (Maybe IO a -> IO Maybe a), or invent some new funny monad thing, to get the desired end result. But, we are in JavaScript and we do not have gooddo
notation or even function call notation without excessive parentheses. - I never expect code that uses
fromJust
to expose the fact that it is doing so. In come functions, imperative style is just easier to read (or easier for some to think in). If a function has a complex nesting of maybes one might want to implement the function differently for one reason or another.
This Library is not a learning library? It is a library designed to be used. Do not force me how to think--do convince me though! (not literally me, I already am) Convince and teach in blog posts and books--specifications are a very bad teacher.
The primary reasoning is that, even if fromJust
is never needed; noobish me used it because I did not know how to think the right way. Shallow the learning curve.
I would be happy with unsafeFromJust
to not be misleading.
I think we should shy away from these two functions.
The use of is[instanceType]
for Sum (Union) Types (Maybe
, Either
, Result
, etc) nudges the user to a more imperative style. IMO the value I get out of ADTs, is the ability to remove a majority of the boiler plate that comes with imperative code and just use the types to dictate flow and logic. Providing those is[instanceType]
functions in the lib is not really a "general" thing and really should be provided by the end user if they need them. As @dalefrancis88 has shown with his suggestion, we provide all the parts/bits/pieces you can use to craft the the functions you need.
As far as the fromJust
, there is no way to generally go from Maybe a
to any other type and we want to shy away from throwing anything but TypeErrors in this lib. (Those are the only errors we throw). So that is not feasible as there is no general case. We do provide an assortment of Natural Transformations for the Sum Types from one Sum Type to another Sum Type. But for moving from a SumType to another non-Sum type, that would be a one-off thing. To account for that generally, we would have to write a function for EVERY type the lib provides and force a user into whatever we decide to do when there is "structure" mismatch. So it makes more sense to NOT implement this and let the user write their own helpers specific to their context.
It really all comes down to this being a REALLY large library as is. so we want to keep to functions/patterns that provide the general case to the user and let the user write the helpers that they need for their specific context.
I guess that is reasonable. They are not that hard to implement oneself.
For anyone who sees this looking for an implementation here is one:
const isJust =
either(constant(false), constant(true))
const fromJust =
either(Identity, ()=>{throw Error();})