无法将预期类型“IO b0”与实际类型“[a0]”匹配

时间:2012-11-03 18:28:50

标签: haskell greatest-common-divisor

我是哈斯克尔家伙的新手。我正在尝试编写一个gcd可执行文件。

ghc --make gcd

当我编译此代码时,我收到以下错误。

Couldn't match expected type `IO b0' with actual type `[a0]' 
In a stmt of a 'do' block:
  putStrLn "GCD is: " ++ gcd' num1 num2 ++ "TADA...."
In the expression:
  do { putStrLn "Hello,World. This is coming from Haskell";
       putStrLn "This is the GCD";
       putStrLn "Frist Number";
       input <- getLine;
       .... }
In an equation for `main':
    main
      = do { putStrLn "Hello,World. This is coming from Haskell";
             putStrLn "This is the GCD";
             putStrLn "Frist Number";
             .... }

我不明白我的问题在哪里......这是我的代码。

gcd' :: (Integral a) => a -> a -> a
gcd' x y = gcd' (abs x) (abs y)
      where gcd' a 0  =  a
        gcd' a b  =  gcd' b (a `rem` b)

main = do
    putStrLn "Hello,World. This is coming from Haskell"
    putStrLn "This is the GCD"
    putStrLn "Frist Number"
    input <- getLine
    let num1 = (read input)
    putStrLn "Second Number"
    input2 <- getLine
    let num2 = read input2
    putStrLn "GCD is: " ++ gcd' num1 num2 ++ "TADA...."

我所知道的是read帮助我将我的字符串转换为int。

1 个答案:

答案 0 :(得分:10)

首先,你需要括号,

putStrLn ("GCD is: " ++ gcd' num1 num2 ++ "TADA....")

或中缀函数应用程序($)

putStrLn $ "GCD is: " ++ gcd' num1 num2 ++ "TADA...."

没有它,该行被解析为

(putStrLn "GCD is: ") ++ gcd' num1 num2 ++ "TADA...."

并且IO动作putStrLn "GCD is: "String的串联导致 - 在有足够经验之前 - 有点神秘 - 类型错误。

从该行显示的上下文中 - 在IO - 阻止 - 中,对于某些IO b,它必须具有b类型。但是(++)的应用推断的类型对于某些类型[a]a。这些类型无法匹配,这就是编译器报告的内容。

请注意,修复后,您还需要将gcd'的结果转换为String

putStrLn $ "GCD is: " ++ show (gcd' num1 num2) ++ "TADA...."

或者你会看到另一个类型错误。


来自评论

  

让我的程序看起来更好。有没有一种方法可以将输入区域放在语句旁边而不是放下行?

总的来说,是的。不使用向输出字符串附加换行符的putStrLn,而是使用putStr而不是。{/ p>

putStr "Second Number: "
input2 <- getLine

在交互模式(ghci)中,效果很好。 stdout没有缓存在那里。对于已编译的程序,stdout通常是行缓冲的,这意味着在输出换行符或缓冲区已满之前它不会输出任何内容。

因此对于已编译的程序,您需要显式刷新输出缓冲区,

import System.IO -- for hFlush

putStr "Second Number: "
hFlush stdout
input2 <- getLine

或完全关闭缓冲

import System.IO

main = do
    hSetBuffering stdout NoBuffering
    ...

但至少后一种方法不适用于Windows(我不确定这是否已修复,我也不确定hFlush是否可以在Windows上运行。