sanctuary-js / sanctuary

:see_no_evil: Refuge from unsafe JavaScript
https://sanctuary.js.org
MIT License
3.03k stars 94 forks source link

S.of(S.Maybe)(void 0) gives Just(undefined) instead of Nothing. #651

Closed t1ger-0527 closed 4 years ago

t1ger-0527 commented 4 years ago

Hi masters!

I'm learning FP with this book mostly-adequate-guide and I'm using sanctuary as a real-world reference. I find having this well documented and nicely implemented library helps a lot! Thanks for developing such great project!

Regarding my question. Maybe I'm using it wrong, but is the value Just(undefined) by design?

What is the proper way to convert an unsafe data (maybe from a remote endpoint) to Nothing/Just that we can pipe into functions safely?

davidchambers commented 4 years ago

Hello, @t1ger-0527. :wave:

Maybe I'm using it wrong, but is the value Just(undefined) by design?

This is very much by design. The type of S.of is Applicative f => TypeRep f -> a -> f a. There are no constraints on a, which means we can replace it with any type we choose, even Undefined.

S.head returns a value from which we can infer whether the input was empty:

> S.head ([])
Nothing

> S.head ([undefined, undefined, undefined])
Just (undefined)

Were null and undefined to be treated specially we would lose this property. In general, special cases should be avoided. :)

What is the proper way to convert an unsafe data (maybe from a remote endpoint) to Nothing/Just that we can pipe into functions safely?

Excellent question. Consider a value xs that we assume to be either null/undefined or an array of integers. We could convert this to a value of type Maybe (Array Integer) in a straightforward manner:

xs == null ? S.Nothing : S.Just (xs)

Depending on our level of confidence in our assumption, the expression above may or may not be satisfactory. If we want to be certain that the result is of type Maybe (Array Integer), we should specify a suitably demanding predicate:

S.filter (S.is ($.Array ($.Integer))) (S.Just (xs))

In the expression above, $ refers to the sanctuary-def module.

S.get, S.gets, and S.parseJson can also be of use when dealing with untrusted inputs.

t1ger-0527 commented 4 years ago

@davidchambers Thanks for such quick and thoughtful reply! It solves my question perfectly! ❤️

davidchambers commented 4 years ago

You are welcome, @t1ger-0527. :)