I'm trying to write a function with an arbitrary number of arguments. These arguments can be Int or String. And I have a problem with ints. For some reason (which I don't understand), the value 1 becomes a source of ambiguity. How to deal with this error and what is the source of it?
{-# LANGUAGE FlexibleInstances #-}
import Data.Typeable
data PackArgTypes = PackInt Int | PackString String
deriving Show
class PackArg t where
toPackArg :: t -> PackArgTypes
instance PackArg Int where
toPackArg = PackInt . fromIntegral
instance PackArg Integer where
toPackArg = PackInt . fromIntegral
instance PackArg String where
toPackArg = PackString
class PackType t where
pack' :: String -> [PackArgTypes] -> t
instance PackType (IO a) where
pack' fmt acc = do
print fmt
mapM_ print acc
return undefined
instance (PackArg a, PackType r) => PackType (a -> r) where
pack' fmt acc = \x -> pack' fmt $ acc ++ [toPackArg x]
pack :: (PackType t) => String -> t
pack fmt = pack' fmt []
main :: IO ()
main = do
pack "asd" "qwe" "asd"(1 :: Int) -- Ok
pack "asd" "qwe" "asd" 1 -- Sad
In said case I've got the error
test1.hs:33:3-6: No instance for (PackArg a0) arising from a use of ‘pack’ …
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance PackArg String
-- Defined at /home/knesterov/test1.hs:13:10
instance PackArg Int -- Defined at /home/knesterov/test1.hs:10:10
In a stmt of a 'do' block: pack "asd" "qwe" "asd" 1
In the expression: do { pack "asd" "qwe" "asd" 1 }
In an equation for ‘main’: main = do { pack "asd" "qwe" "asd" 1 }
test1.hs:33:26: No instance for (Num a0) arising from the literal ‘1’ …
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Num Double -- Defined in ‘GHC.Float’
instance Num Float -- Defined in ‘GHC.Float’
instance Integral a => Num (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
...plus 7 others
In the fourth argument of ‘pack’, namely ‘1’
In a stmt of a 'do' block: pack "asd" "qwe" "asd" 1
In the expression: do { pack "asd" "qwe" "asd" 1 }
Compilation failed.
EDIT
Thanks to user5402 who pointed to the difference between ghci and ghc. Ghci enables extension ExtendedDefaultRules by default
So with three additional lines my sample works with no errors.
{-# LANGUAGE ExtendedDefaultRules #-}
instance PackArg Integer where
toPackArg = PackInt . fromIntegral
The problem is here:
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Num Double -- Defined in ‘GHC.Float’
instance Num Float -- Defined in ‘GHC.Float’
...
Recall that the literal 1
can be interpreted as a value any Num
type, so GHC doesn't know which one to select - e.g. Int
, Double
, Rational
, etc.
The standard Text.Printf
module has the same problem:
import Text.Printf
main = putStrLn $ printf "%d" 3
gives he same error.
Note that if you won't get an error if you enter this code into ghci because there are defaulting rules which make the expression 1
monomorphic instead of polymorphic.