Consider the following situation:
slow_func :: Eq a => [a] -> [a]
fast_func :: Ord a => [a] -> [a]
I have two functions, slow_func
and fast_func
. These functions are different implementations of the same abstract function (they do the same thing), but one is faster than the other. The faster implementation is only available if the type a
can be ordered. Is there a way to construct a function which acts as fast_func
when possible, and reverts to slow_func
otherwise?
as_fast_as_possible_func :: Eq a => [a] -> [a]
I have already tried the following:
{-# LANGUAGE OverlappingInstances #-}
class Func a where
as_fast_as_possible_func :: [a] -> [a]
instance Ord a => Func a where
as_fast_as_possible_func = fast_func
instance Eq a => Func a where
as_fast_as_possible_func = slow_func
Unfortunately, this doesn't compile, generating the following error:
Duplicate instance declarations:
instance Ord a => Func a
-- Defined at [...]
instance Eq a => Func a
-- Defined at [...]
The reason is that OverlappingInstances
wants one of the instances to be most specialized with respect to the instance specification, ignoring its context (rather than using the most restrictive context, which is what we need here).
Any way to do this?