如何printf元组列表?

Mar*_*oma 4 haskell compiler-errors

以下代码计算整数元组的列表:

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)
Run Code Online (Sandbox Code Playgroud)

但是当我编译它时,我得到:

$ 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)'
Run Code Online (Sandbox Code Playgroud)

当我用最后一行替换它时,它工作正常

main = mapM_ (print) (zip [1..] solve)
Run Code Online (Sandbox Code Playgroud)

但这并没有给出所需的格式.我做错了什么?如何printf整数元组列表?

PS

我试图缩短它,但它似乎给出了其他错误:

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)])
Run Code Online (Sandbox Code Playgroud)

Zet*_*eta 7

printf使用魔法.基本上,你遇到的问题是一样的

main :: IO ()
main = let k = read "1234"
       in print k
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)

由于read它的返回类型是多态的,所以不清楚它的k类型是什么.我们需要指定k例如Int:

main :: IO ()
main = let k = read "1234" :: Int
       in print k
Run Code Online (Sandbox Code Playgroud)

printf返回类型也是多态的,它必须是一个实例PrintfType.因为solve's类型是固定的[Integer],所以只剩下一个罪魁祸首:列表[1..].实际上,模糊Enum实例也表明了这一点:

base.hs:23:46:
    No instance for (Enum a0)
      arising from the arithmetic sequence `1 .. '
    The type variable `a0' is ambiguous
Run Code Online (Sandbox Code Playgroud)

类型检查器无法获取正确的类型[1..].如果你指定一个类型并使列表的类型因此不含糊,那么一切正常:

main = mapM_ (uncurry $ printf "%d: %d") (zip ([1..] :: [Integer]) solve)
Run Code Online (Sandbox Code Playgroud)

TL; DR:当GHC对你的模糊类型大吼大叫时,请注释它们.

  • 喜欢TL; DR部分. (2认同)