Не удалось сопоставить ожидаемый тип `IO b0'с фактическим типом`[a0]'

Я новичок в Haskell, ребята. Я пытаюсь написать исполняемый файл 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 ответ

Решение

Во-первых, вам нужны скобки,

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-do-block - должен иметь тип IO b для некоторых b, Но тип, выведенный из применения (++) является [a] для какого-то типа a, Эти типы не могут быть сопоставлены, и это то, что сообщает компилятор.

Обратите внимание, что после исправления вам также необходимо преобразовать результат gcd' к String,

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

или вы увидите другую ошибку типа.


Из комментария

Чтобы моя программа выглядела лучше. Есть ли способ, что область ввода находится рядом с оператором вместо строки вниз?

В общем да. Вместо того, чтобы использовать putStrLn который добавляет новую строку к выходной строке, используйте putStr который не

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).

Другие вопросы по тегам