Функция getTriangle
использует IO, поэтому вы должны указать это в сигнатуре функции.
getTriangle :: IO Triangle
Кроме того, последняя строка должна иметь return
, поскольку она возвращает чистое значение внутри функции ввода-вывода.
return (Triangle base height)
Вот пара дополнительных советов: Haskell может выяснить, что base
и height
являются Double
, потому что вы передаете их Triangle
, поэтому вам не нужно явно объявлять их таким образом. Вы можете использовать liftM
из модуля Control.Monad
, чтобы прочитать ввод и преобразовать в Double
за один шаг.
import Control.Monad
getTriangle :: IO Triangle
getTriangle = do
putStr "Base: "
base <- liftM read getLine
putStr "Height: "
height <- liftM read getLine
return (Triangle base height)
Функция main
также позволяет смешивать чистые значения с IO. Поскольку getTriangle - это IO, вы не можете передать его напрямую в calcTriangle. Вот модифицированный main
:
main = do tri <- getTriangle
putStrLn ("Area = " ++ show (calcTriangle tri))
В качестве сноски площадь треугольника равна base * height / 2
, а не base * height
.
Наконец, более продвинутый программист на Haskell, вероятно, написал бы getTriangle
в терминах liftM2
, но это просто вопрос стиля. Вот как бы я это написал:
prompt str = putStr (str ++ ": ") >> liftM read getLine
getTriangle = liftM2 Triangle (prompt "Base") (prompt "Height")