printf返回什么?

时间:2012-02-22 10:33:42

标签: haskell

我正在学习Haskell,这是我尝试理解语法的第一步。我很难过,不幸的是,语言参考没有帮助。

我尝试:type (line_length 1 2 3 4)并且我reference on printf红了但是,它使用含有模糊含义的符号而不是单词。所以,我被困住并寻求帮助。

简单说明:我用什么来代替???

line_length :: Integer -> Integer -> Integer -> Integer -> ???
line_length ax ay bx by =
            printf ("The length of the line between the points" ++
            "(%d,%d) and (%d,%d) is %.5f\n") ax ay bx by
            ((((fromIntegral (ax - bx)) ** 2.0) +
            ((fromIntegral (ay - by))) ** 2.0) ** 0.5)

2 个答案:

答案 0 :(得分:12)

printf :: PrintfType r => String -> r的重载返回类型可能有点令人困惑,但它有助于查看可用的PrintfType个实例:

  1. 首先,我们有这个例子:

    instance (PrintfArg a, PrintfType r) => PrintfType (a -> r)
    

    这个用于允许printf获取可变数量的参数。由于currying,这是有道理的,但您可能不会将其视为函数的“真实”返回类型。有关其工作原理的详细信息,请参阅How does printf work in Haskell?

  2. 然后我们有了这个实例,

    instance PrintfType (IO a)
    

    这意味着我们可以将其用作IO操作。与print类似,这会将结果打印到标准输出。操作的结果是undefined,所以你应该忽略它。 1

    > printf "Foo %d\n" 42 :: IO ()
    Foo 42
    > it
    *** Exception: Prelude.undefined
    
  3. 最后,

    instance IsChar c => PrintfType [c]
    

    这里的类型类主要是为了使它符合Haskell 98。由于IsChar的唯一实例是Char,因此您可以将其视为

    instance PrintfType String
    

    但这需要GHC特定的扩展FlexibleInstances

    此实例的含义是,您也可以在不打印的情况下返回String,类似于C中的sprintf

    > printf "Foo %d\n" 42 :: String
    "Foo 42\n"
    
  4. 因此,根据您是要打印结果还是仅返回结果,您可以在示例中将???替换为IO ()String

    但是,您的代码存在另一个问题,即编译器无法确定您想要最后一个参数的类型,因此您必须使用类型注释来帮助它:

    line_length :: Integer -> Integer -> Integer -> Integer -> String
    line_length ax ay bx by =
                printf ("The length of the line between the points" ++
                "(%d,%d) and (%d,%d) is %.5f\n") ax ay bx by
                ((((fromIntegral (ax - bx)) ** 2.0) +
                ((fromIntegral (ay - by))) ** 2.0) ** 0.5 :: Double)
    

    1 这样做是为了避免扩展。使用扩展程序,我们可以编写instance PrintfType (IO ()),结果将是()

答案 1 :(得分:1)

当我遇到类型签名时,我让Haskell为我做了艰苦的工作。就是这样,我

  • 编写没有类型签名的定义
  • 将其加载到ghci
  • 以交互方式检查Haskell提供的类型
  • 在源文件中复制该签名(确保它是我的意图)