I’m playing with PureScript this morning, to understand more about Monads.
Given this implementation:
mul :: forall m n. Bind m => Applicative m => Semiring n => m n -> m n -> m n
mul ma mb = do
a <- ma
b <- mb
pure (a * b)
I can make these tests pass:
Just 12 ==
mul (Just 3) (Just 4)
mul Nothing (Just 4)
mul (Just 3) Nothing
However, introducing Either requires me to implement
Right 12 ==
mul (Right 3) (Right 4)
I did find a reference for this requirement in the
(Eq a) => Eq1 (Either a)
(Ord a, Ord b) => Ord (Either a b)
The Ord instance allows Either values to be compared with compare, >, >=, < and <= whenever there is an Ord instance for both types the Either can contain.
Any Left value is considered to be less than a Right value.
But I can’t quite understand how I should implement this. My hunch is that I need to tweak the type signature but I’m not sure.
Could you show me how what I’m missing?
Hi - the issue is with the tests - those need the instance to be
Eq and indeed I think the problemis not the code you wrote (this should be
Right 3) but that the
Left type of your
Either will not be known (and thus infered as some type-variable
a) and thus the typechecker will complain - you should be able to help out like this:
assert $ (Right 12 :: Either String Int) == mul (Right 3) (Right 4) (basically: give the typechecker a hint)
disclaimer: I did not try this out so chances are that I typed some syntax/type error - sorry
Many thanks, that was it! Makes sens…
I have one last question : in this context, do I have to “commit”
Left’s type? Intuitively, I’d want to do this:
(Right 12 :: Either a Int) ==
mul (Right 3) (Right 4)
But that’s obviously wrong. I’m just wondering if I could be missing a cool trick here
you don’t have to “commit” to the type but you have to make sure that it is
Eq - and I think
Show but I could be wrong here)
So there needs to be a
forall a. Eq a => Show a => Either a Int and to be honest: I’m not sure if you can plug this in there (I’m not sure if this is allowed syntax) - I think you could do this with a
assert $ expected ...
expected :: forall a. Eq a => Show a => Either a Int
expected = Right 12
It looked like a cool idea but it didn’t work unfortunately.
I’ll go with being explicit for now, thanks again
ok - I guess Purescript does not fall back to defaults then (the actual code you gonna run needs actual types as the type-class instances are passed via a dictionary - I somehow thought Purescript would use default types - when I think about it it’s probably a rather stupid assumption - sorry)
Yeah, Haskell has a defaulting mechanism that we decided not to implement way back in the mists of time. Although it would have been nice in this case, it can also be confusing as it’s very ad-hoc. It’s even worse when you’re in GHCi, as it adds a bunch of extra defaults than then don’t work in real code.
yes that was what I was thinking about - in the end it’s not really a loss IMHO - defaults + monomorphism-restriction while nice can be a huge “WTF” generator in Haskell