传递给printf时,在重载的文字上键入需要的注释

use*_*064 0 printf haskell type-inference

我对这些感到困惑:

我这样写的时候

main = do
    putStrLn . printf "%f" $ 2.3
Run Code Online (Sandbox Code Playgroud)

它会导致

没有实例(PrintfArg a0)从使用所产生的printf

类型变量a0不明确

代码在GHCi中运行良好,当我runhaskell在终端中使用时发生了这个错误.

所以我写

putStrLn . printf "%f" $ (2.3 :: Double)
Run Code Online (Sandbox Code Playgroud)

没关系,但我不知道原因.

"%f"推断2.3属于类型Double

据我所知,putStrLn有类型String -> IO(),不能将printf结果转换为何String2.3不装饰Double

Cac*_*tus 5

因为Haskell是不是一个依赖类型的语言中,价值printf的第一个参数(即"%f"你的情况)没有处方的方式类型printf的第二个参数(2.3在你的情况).

就其自身而言,2.3类型是Fractional a => a因为它是一个重载的文字.printf的类型可能看起来有点神奇,因为它是非常多态的,因此例如printf "%s" "foo"并且printf "%f" 2.3都可以进行类型检查.这是通过PrintfTypePrintfArg类型类实现的.

总而言之printf "%f" 2.3,类型检查器只知道2.3某种类型a同时具有a FractionalPrintfArg实例; 但它不知道a实际需要什么.它需要一种类型才能解析FractionalPrintfArg实例.

这种情况有点类似于show . read问题,并且您的示例在GHCi中起作用,因为Num 默认Double.