我对这些感到困惑:
当我这样写的时候
main = do
putStrLn . printf "%f" $ 2.3
会导致
使用
时,(PrintfArg a0)
printf
没有任何实例类型变量
a0
不明确
代码在GHCi中运行良好,当我在终端中使用runhaskell
时发生此错误。
所以我写了
putStrLn . printf "%f" $ (2.3 :: Double)
没关系,但我不知道原因。
不要"%f"
推断2.3
属于Double
类型?
据我所知,putStrLn
的类型为String -> IO()
,printf
的结果可以在{{1}时转换为String
没有2.3
装饰?
答案 0 :(得分:5)
因为Haskell不是依赖类型的语言,printf
的第一个参数的值(即您的案例中为"%f"
)无法处方printf
第二个参数的类型(在您的情况下为2.3
)。
2.3
的类型Fractional a => a
本身就是printf "%s" "foo"
,因为它是overloaded literal。 printf
's type可能看起来有点神奇,因为它是非常多态的,所以printf "%f" 2.3
和printf "%f" 2.3
都可以进行类型检查。这是通过PrintfType
和PrintfArg
类型类实现的。
总而言之,在2.3
中,类型检查器只知道a
是某种类型Fractional
同时包含PrintfArg
和a
实例;但它并不知道Fractional
实际需要什么。它需要一种类型,以便可以解析PrintfArg
和Num
个实例。
这种情况与show . read
问题有些类似,由于Double
defaulting到console.next();
,您的示例在GHCi中有效。