Use specialized implementation if a class instance is available

Viewed 1162

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?

2 Answers
Related