Wrong answer from S.min when strings used

53 views Asked by At
S.min ('1') ('02') =>'02'

Why is this even possible? (yes type coercion... but this is Sanctuary) Can Sanctuary be configured so that Nothing is returned when Strings are used? Is there an elegant way to deal with this?

1

There are 1 answers

0
davidchambers On BEST ANSWER

Let's consider the type of S.min:

min :: Ord a => a -> a -> a

String satisfies the requirements of Ord, so String -> String -> String is one possible specialization:

> S.min ('foo') ('bar')
'bar'

If you are dealing with inputs that should be numbers but may not be, the best approach is to deal with the uncertainty up front:

//    untrustedInput1 :: Any
//    untrustedInput2 :: Any

//    input1 :: Maybe Number
const input1 = S.filter (S.is ($.Number)) (S.Just (untrustedInput1));

//    input2 :: Maybe Number
const input2 = S.filter (S.is ($.Number)) (S.Just (untrustedInput2));

Then, you could use S.lift2 to transform S.min into a function that can operate on Maybe Number values:

S.lift2 (S.min) :: (Apply f, Ord a) => f a -> f a -> f a

The signature above can be specialized like so:

S.lift2 (S.min) :: Maybe Number -> Maybe Number -> Maybe Number

The final step is to apply S.lift2 (S.min) to the trusted inputs:

S.lift2 (S.min) (input1) (input2)

Here is a full working example:

> S.lift2 (S.min)
.         (S.filter (S.is ($.Number)) (S.Just ('1')))
.         (S.filter (S.is ($.Number)) (S.Just ('02')))
Nothing