sanctuary-js / sanctuary

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

simplify S.encase and S.encaseEither #103

Closed davidchambers closed 8 years ago

davidchambers commented 8 years ago

Currently, encase and encaseEither have misleading type signatures:

encase :: (* -> a) -> (* -> Maybe a)

encaseEither :: (Error -> a) -> (* -> b) -> (* -> Either a b)

They are misleading because Hindley–Milner notation cannot represent a function which returns a curried function of unknown arity.

In addition to the documentation problem, there's a usability problem. Functions with unwanted optional arguments must be wrapped in lambdas. For example:

S.encaseEither(S.I, x => JSON.parse(x))

A solution to both problems is to have one function for each arity up to some arbitrary limit:

encase  :: (a -> b) -> a -> Maybe b
encase2 :: (a -> b -> c) -> a -> b -> Maybe c
encase3 :: (a -> b -> c -> d) -> a -> b -> c -> Maybe d

encaseEither  :: (Error -> l) -> (a -> r) -> a -> Either l r
encaseEither2 :: (Error -> l) -> (a -> b -> r) -> a -> b -> Either l r
encaseEither3 :: (Error -> l) -> (a -> b -> c -> r) -> a -> b -> c -> Either l r

An incidental benefit of this approach is that arguments to the wrapped function may be provided up front. For example:

> S.encaseEither(R.prop('message'), JSON.parse, '[1,2,3]')
Right([1, 2, 3])
> S.encaseEither(R.prop('message'), JSON.parse, 'XXX')
Left("Unexpected token X")
benperez commented 8 years ago

This approach seems sound to me. I like the idea of being explicit about the number of parameters you are expecting in the supplied function. More often these days I'm starting to see variadic functions and function context as distracting and occasionally problematic features of JavaScript.