Niki
Niki

Reputation: 11

Choose default instance under ambiguous types

Is there a Haskell language extension for the type class method to "use the only potential instance available"?

I want to compile the following

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances     #-}

class Foo a r where
 foo :: a -> r 


instance Foo a (Bool -> a) where
  foo x _ = x 

-- This compiles 
-- bar :: Int -> Bool

-- This does not  
bar :: a -> Bool  
bar _ = True 


use :: Bool 
use = bar $ foo _5 True
  where
    _5 :: Int 
    _5 = 5 

Now I get the following error:

     No instance for (Foo Int (Bool -> r0))
  (maybe you haven't applied enough arguments to a function?)
  arising from a use of ‘foo’
The type variable ‘r0’ is ambiguous
Note: there is a potential instance available:
  instance Foo a (Bool -> a) -- Defined at tests/pos/Fixme.hs:9:10

But since there is only one potential instance available, is there a way to force ghc to use that instance? Or is there a way to declare some instance as a default instance when types are ambiguous?

Upvotes: 1

Views: 507

Answers (1)

Daniel Wagner
Daniel Wagner

Reputation: 152682

The standard trick is to make your instance more polymorphic, thus:

instance (a ~ b, bool ~ Bool) => Foo a (bool -> b) where
    foo x _ = x

This precludes you from writing other function instances, but makes it clear what types to use when a function instance is wanted. You will need to turn on the TypeFamilies extension to do this. In your specific case you may be able to get away with just instance a ~ b => Foo a (Bool -> b), which would allow further function instances with other argument types, at the cost of more frequent ambiguity errors.

See a previous answer of mine for some more explanation of this trick.

Upvotes: 2

Related Questions