Search code examples
haskellambiguoustype-variables

Problems with printf and ambiguous type variables


I have a little ambiguous type variable problem. I love haskell but this is really what I still fail to handle. The problem is very easy and involves printf from Text.Printf. Since the problem is very general I'll just but in some sample code:

program = do
    d <- addd 4 8
    printf "%d" d

addd x y = return (x+y)

Of course printf is imported. The compiler then gives me an, obvious, ambiguous type variable error between Num and PrintfArg. I just don't know where to fit in the right type signature.


Solution

  • There are a few places you could put a type signature. Firstly, addd has most general type of (and the most general type is (almost always) what GHC infers when you leave off the signature):

    addd :: (Monad m, Num a) => a -> a -> m a
    

    You could restrict this to only work on a certain type by giving addd an explicit type signature, so that it isn't at all polymorphic in the arguments, e.g.:

    addd :: Monad m => Int -> Int -> m Int
    -- or,
    addd :: Monad m => Integer -> Integer -> m Integer
    

    Or, you could inform GHC of the input type when you call addd, e.g.:

    d <- addd 4 (8 :: Integer)
    

    and then the type inference will infer that 4 and d are both Integers.

    Lastly, you can give d a type. Either when you use it (if you use d multiple times, you only need a single annotation), like so:

    printf "%d" (d :: Integer)
    

    Or when you set it (requires the GHC extension ScopedTypeVariables):

    {-# LANGUAGE ScopedTypeVariables #-}
    
    [...]
    add = do
        (d :: Integer) <- addd 4 8