printf和模糊类型变量的问题

时间:2012-09-15 10:07:38

标签: haskell ambiguous type-variables

我有一个模糊的类型变量问题。我喜欢哈斯克尔,但这真的是我仍然无法处理。 问题非常简单,涉及来自Text.Printf的printf。由于问题很普遍,我只是在一些示例代码中:

program = do
    d <- addd 4 8
    printf "%d" d

addd x y = return (x+y)

当然是printf是导入的。编译器然后在Num和PrintfArg之间给出了一个明显的,模糊的类型变量错误。我只是不知道在哪里适合正确的类型签名。

2 个答案:

答案 0 :(得分:2)

有几个地方可以放置类型签名。首先,addd具有最常见的类型(并且最常见的类型是(几乎总是)GHC在您不签名时推断的内容):

addd :: (Monad m, Num a) => a -> a -> m a

你可以通过给addd一个显式类型签名来限制它只对特定类型起作用,这样它在参数中根本不是多态的,例如:

addd :: Monad m => Int -> Int -> m Int
-- or,
addd :: Monad m => Integer -> Integer -> m Integer

或者,您可以在致电addd时告知GHC输入类型,例如:

d <- addd 4 (8 :: Integer)

然后类型推断会推断4d都是Integer s。

最后,您可以为d提供一种类型。当你使用它时(如果多次使用d,你只需要一个注释),如下所示:

printf "%d" (d :: Integer)

或者当你设置它时(需要GHC扩展名ScopedTypeVariables):

{-# LANGUAGE ScopedTypeVariables #-}

[...]
add = do
    (d :: Integer) <- addd 4 8

答案 1 :(得分:1)

我会尝试解释你的程序有什么问题。

  • 尝试提供明确的类型签名,它有助于编译器推断类型,并帮助您更好地理解您的程序。
  • addd是一个纯函数,所以不要使用return。
  • 不是你期望来自命令背景的回报。
  • 为什么您需要printf,如果要输出到控制台,请使用printputStrLn。如果要将类型(其show实例已定义)转换为字符串,请使用show

无论如何,这是您的更正程序

import Text.Printf

program :: String
program = do
    let d = addd 4 8
    printf "%d" d

addd :: Int -> Int -> Int
addd x y = x+y

您可以使用print作为

来编写它
program :: IO ()
program = do
    print $ addd 4 8

addd :: Int -> Int -> Int
addd x y = x+y

尝试阅读Haskell

上的一些介绍性材料