The following code calculates a list of tuples of integers:
import Data.List (sort)
import Data.Char (digitToInt)
import Text.Printf
-- Check if the given list of numbers is ascending by exactly one
isAscending :: (Eq a, Num a) => [a] -> Bool
isAscending [] = True
isAscending [x] = True
isAscending (x:y:xs) = (x+1 == y) && isAscending (y:xs)
-- Check if the digits that are in the given number are in an intervall
-- So for 12345, 54321, 45321 the function returns True
-- but for 02345 it returns False
check :: Show a => a -> Bool
check x = isAscending $ map digitToInt $ sort $ show x
-- Find all numbers with property 'check' that have 5 digits
solve :: [Integer]
solve = filter check [10^4..10^5]
-- Print results
main :: IO()
main = mapM_ (uncurry $ printf "%d: %d") (zip [1..] solve)
But when I compile it I get:
$ ghc base.hs
[1 of 1] Compiling Main ( base.hs, base.o )
base.hs:23:25:
No instance for (PrintfArg a0) arising from a use of `printf'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance [safe] PrintfArg Char -- Defined in `Text.Printf'
instance [safe] PrintfArg Double -- Defined in `Text.Printf'
instance [safe] PrintfArg Float -- Defined in `Text.Printf'
...plus 12 others
In the second argument of `($)', namely `printf "%d %d"'
In the first argument of `mapM_', namely
`(uncurry $ printf "%d %d")'
In the expression:
mapM_ (uncurry $ printf "%d %d") (zip [1 .. ] solve)
base.hs:23:46:
No instance for (Enum a0)
arising from the arithmetic sequence `1 .. '
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Enum Data.Char.GeneralCategory -- Defined in `Data.Char'
instance Enum Double -- Defined in `GHC.Float'
instance Enum Float -- Defined in `GHC.Float'
...plus 16 others
In the first argument of `zip', namely `[1 .. ]'
In the second argument of `mapM_', namely `(zip [1 .. ] solve)'
In the expression:
mapM_ (uncurry $ printf "%d %d") (zip [1 .. ] solve)
base.hs:23:47:
No instance for (Num a0) arising from the literal `1'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
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 11 others
In the expression: 1
In the first argument of `zip', namely `[1 .. ]'
In the second argument of `mapM_', namely `(zip [1 .. ] solve)'
It works fine when I replace the last line with
main = mapM_ (print) (zip [1..] solve)
but that does not give the desired formatting. What did I do wrong? How can I printf a list of integer tuples?
I tried to make this shorter, but it seemed to give other errors:
import Data.List (sort)
import Data.Char (digitToInt)
import Text.Printf
-- Print results
main :: IO()
main = mapM_ (print "%d %d") ([(1,123), (2, 123), (3, 452), (4, 2)])
printf
uses magic. Basically, the problem you encounter is the same as
main :: IO ()
main = let k = read "1234"
in print k
SO.hs:2:16:
No instance for (Read a0) arising from a use of `read'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Read () -- Defined in `GHC.Read'
instance (Read a, Read b) => Read (a, b) -- Defined in `GHC.Read'
instance (Read a, Read b, Read c) => Read (a, b, c)
-- Defined in `GHC.Read'
...plus 25 others
In the expression: read "1234"
In an equation for `k': k = read "1234"
In the expression: let k = read "1234" in print k
SO.hs:3:11:
No instance for (Show a0) arising from a use of `print'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Show Double -- Defined in `GHC.Float'
instance Show Float -- Defined in `GHC.Float'
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
...plus 26 others
In the expression: print k
In the expression: let k = read "1234" in print k
In an equation for `main': main = let k = read "1234" in print k
Since read
is polymorphic in its return type, it's not clear what k
's type is. We need to specify that k
shall be, for example, an Int
:
main :: IO ()
main = let k = read "1234" :: Int
in print k
printf
's return type is also polymorphic, it must be an instance of PrintfType
. Since solve
's type is fixed as [Integer]
, there's only one culprit left: the list [1..]
. Indeed, this is also shown by the ambiguous Enum
instance:
base.hs:23:46: No instance for (Enum a0) arising from the arithmetic sequence `1 .. ' The type variable `a0' is ambiguous
The type checker cannot get the correct type for [1..]
. If you specify a type and make the list's type therefore non-ambiguous, everything works fine:
main = mapM_ (uncurry $ printf "%d: %d") (zip ([1..] :: [Integer]) solve)
TL;DR: When GHC yells at you for ambiguous types, annotate them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With