我正在学习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)
答案 0 :(得分:12)
printf :: PrintfType r => String -> r
的重载返回类型可能有点令人困惑,但它有助于查看可用的PrintfType
个实例:
首先,我们有这个例子:
instance (PrintfArg a, PrintfType r) => PrintfType (a -> r)
这个用于允许printf
获取可变数量的参数。由于currying,这是有道理的,但您可能不会将其视为函数的“真实”返回类型。有关其工作原理的详细信息,请参阅How does printf work in Haskell?。
然后我们有了这个实例,
instance PrintfType (IO a)
这意味着我们可以将其用作IO
操作。与print
类似,这会将结果打印到标准输出。操作的结果是undefined
,所以你应该忽略它。 1
> printf "Foo %d\n" 42 :: IO ()
Foo 42
> it
*** Exception: Prelude.undefined
最后,
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"
因此,根据您是要打印结果还是仅返回结果,您可以在示例中将???
替换为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