2

Let's consider the following example:

data A = A{x::Int} deriving(Show)

instance Func_f (A -> String) where
    f _ = "ala"

class Func_f a where
    f :: a

main :: IO ()
main = do 
    let 
        a = A 5
        x = f a 
    print 5

compiled with ghc -XFlexibleInstances main.hs

(I've tried -XExtendedDefaultRules, but without any progress)

Why while compiling we get an error?:

main.hs:25:21:
    No instance for (Func_f (A -> t0)) arising from a use of `f'
    The type variable `t0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there is a potential instance available:
      instance Func_f (A -> String) -- Defined at main.hs:7:10
    Possible fix: add an instance declaration for (Func_f (A -> t0))
    In the expression: f a
    In an equation for `x': x = f a
    In the expression:
      do { let a = A 5
               x = f a;
           print 5 }

There is only one instance for Func_f, so Haskell should be able to know the result of x = f a. You can fix the error by providing the type manually, like this: x = f a :: String, but this is not suitable for my case, because I'm generating Haskell code and I would love the Haskell's type inferencer to do this job for me.

AndrewC
  • 32,300
  • 7
  • 79
  • 115
Wojciech Danilo
  • 11,573
  • 17
  • 66
  • 132
  • 1
    Hmmm... Only one instance? Are you sure you need the type class at all? [Here](http://lukepalmer.wordpress.com/2010/01/24/haskell-antipattern-existential-typeclass/) you can read how to replace a type class with a data structure. (You're not doing the existential typeclass antipattern, but the resolution there may work here.) – AndrewC Jul 15 '13 at 18:11
  • I would have got many instances, but all resulting the same type. – Wojciech Danilo Jul 15 '13 at 21:25

2 Answers2

13

You're running into the open world assumption. The basic idea is that GHC always assumes that you could add more class instances to your code. Moreover, you cannot control how instances get exported and imported between modules. So relying on only having one instance of a particular class is not going to work and would lead to weird bugs.

Essentially, nothing stops you--or anybody else, for that matter--from writing another instance like:

 instance Func_f (A -> Int) where
   f _ = 10

and it would then be impossible to figure out which one you wanted in your code. This could cause your code to break just from linking against another module!

However, if you actually used the value, chances are it would get its type constrained by some other parameter and the ambiguity would go away. For example, the following works:

main :: IO ()
main = do 
  let a = A 5
      x = f a
  putStr x

Basically, this is one of those cases (similar to read . show) where a type signature is simply unavoidable because of how GHC treats typeclass instances.

Community
  • 1
  • 1
Tikhon Jelvis
  • 67,485
  • 18
  • 177
  • 214
4

There is only one instance for Func_f, so Haskell should be able to know the result of x = f a

This violates the open world assumption.

Don Stewart
  • 137,316
  • 36
  • 365
  • 468