为什么必须在脚本的 printf 中声明数字类型(当与 putStr 一起使用时)而不是 ghci?

Why must the number type be declared in printf (when used with putStr) for a script but not for ghci?

为什么当 运行 作为脚本时 3putStr (printf "abc%d\n" 3) 中不明确,而当 运行 在高铁?也就是说,为什么我必须在脚本中声明 3 的类型而不是 ghci?

这里是ghci内的操作:

$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> putStr "abc3\n"
abc3
Prelude> import Text.Printf
Prelude Text.Printf> printf "abc%d\n" 3
abc3
Prelude Text.Printf> let main = putStr (printf "abc%d\n" 3)
Prelude Text.Printf> main
abc3
Prelude Text.Printf> let main = printf "abc%d\n" 3 :: String
Prelude Text.Printf> main
"abc3\n"
Prelude Text.Printf> :quit
Leaving GHCi.

声明为 Intscript 的正确操作如下:

$ cat runmain-good
#!/usr/bin/env runghc
import Text.Printf
main = putStr (printf "abc%d\n" (3 :: Int))
$ ./runmain-good
abc3

这是 script 的错误操作,当 3 的类型不明确时 ... 典型的用户友好 Haskell 错误:

$ cat runmain-bad
#!/usr/bin/env runghc
import Text.Printf
main = putStr (printf "abc%d\n" 3)
$ ./runmain-bad

runmain-bad:3:16:
    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 first argument of `putStr', namely `(printf "abc%d" 3)'
    In the expression: putStr (printf "abc%d" 3)
    In an equation for `main': main = putStr (printf "abc%d" 3)

runmain-bad:3:33:
    No instance for (Num a0) arising from the literal `3'
    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 second argument of `printf', namely `3'
    In the first argument of `putStr', namely `(printf "abc%d" 3)'
    In the expression: putStr (printf "abc%d" 3)

GHCi 只是在默认情况下启用了宽松的默认规则(因此文字 5 默认为 Integer),只是为了让您的生活更轻松。

您可以通过启用 ExtendedDefaultRules 在 GHC 中实现类似的效果。

请参阅 GCHi docs 以获得更详尽的讨论。