For example, with types, you can implement AdHoc polymorphism using Typeable
to define a different behavior depending on what the input type is:
foo :: forall a. Typeable a => a -> a
foo | Just HRefl <- typeRep @a `eqTypeRep` typeRep @Bool = not
| otherwise = id
-- >>> foo 3
3
-- >>> foo True
False
I would like to do something similar to that but instead check if a type has a curtain instance of a Constraint
, and implement a different behavior on that.
So far I have looked at two packages, Data.Constraint
and Data.Exists
. I think the solution lies with one of them but I have not been able to understand how I would go about doing this.
For context, this came about when I was thinking about what a polymorphic safe integer division function would look like
polymorphicSafeDiv :: Integral a => a -> a -> Maybe a
polymorphicSafeDiv x y = undefined
If I want this function to work for both bounded and unbounded Integral
s I need to consider both, division by zero, and the overflow scenario for minBound @Int / (-1)
. I would imagine something like
polymorphicSafeDiv :: Integral a => a -> a -> Maybe a
polymorphicSafeDiv x y
| y == 0 = Nothing
| y == (-1) = case (???) of
Just Relf -> Nothing
_ -> Just $ x `div` y
| otherwise = Just $ x `div` y