1

我有一个有点模棱两可的类型变量问题。我喜欢haskell,但这确实是我仍然无法处理的。问题很简单,涉及到 Text.Printf 中的 printf。由于问题非常普遍,我将仅在一些示例代码中:

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

addd x y = return (x+y)

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

4

2 回答 2

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

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

d <- addd 4 (8 :: Integer)

然后类型推断将推断出4并且d都是Integers。

最后,你可以给出d一个类型。要么当你使用它(如果你d多次使用,你只需要一个注解),像这样:

printf "%d" (d :: Integer)

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

{-# LANGUAGE ScopedTypeVariables #-}

[...]
add = do
    (d :: Integer) <- addd 4 8
于 2012-09-15T10:13:13.540 回答
1

我将尝试解释您的程序有什么问题。

  • 尝试给出明确的类型签名,它有助于编译器推断类型,也有助于你更好地理解你的程序。
  • addd 是一个纯函数,所以不要使用 return。
  • 返回不是您期望的来自命令式背景的内容。
  • printf毕竟你为什么需要使用print或者putStrLn如果你想输出到控制台。如果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

您可以使用printas编写它

program :: IO ()
program = do
    print $ addd 4 8

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

尝试阅读一些有关Haskell的介绍性材料

于 2012-09-15T10:12:57.213 回答