简体   繁体   English

如何printf元组列表?

[英]How can I printf a list of tuples?

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? 如何printf整数元组列表?

PS PS

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 . printf使用魔法 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. 由于read的返回类型是多态的,因此不清楚k的类型是什么。 We need to specify that k shall be, for example, an Int : 我们需要指定k应该是,例如, 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 . printf的返回类型也是多态的,它必须是PrintfType一个实例。 Since solve 's type is fixed as [Integer] , there's only one culprit left: the list [1..] . 由于solve的类型固定为[Integer] ,因此只剩下一个罪魁祸首:列表[1..] Indeed, this is also shown by the ambiguous Enum instance: 实际上,模糊的Enum实例也表明了这一点:

 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..] . 类型检查器无法获得[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. TL; DR :当GHC对你的模糊类型大吼大叫时,请注释它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM