Haskell: Почему он говорит, что мой тип функции отключен? - PullRequest
4 голосов
/ 07 апреля 2010

Я написал небольшую программу на языке Haskell, чтобы найти область треугольника, в основном для отработки пользовательских типов, но она продолжает выдавать следующую ошибку при компиляции:

areafinder.hs:7:4:
    Couldn't match expected type `Triangle' against inferred type `m b'
    In a stmt of a 'do' expression: putStr "Base: "
    In the expression:
        do { putStr "Base: ";
             baseStr <- getLine;
             putStr "Height: ";
             heightStr <- getLine;
             .... }
    In the definition of `getTriangle':
        getTriangle = do { putStr "Base: ";
                           baseStr <- getLine;
                           putStr "Height: ";
                           .... }

Я не уверен, откуда взялась буква "m b", поэтому я в растерянности. Почему выдает эту ошибку, и что я могу сделать, чтобы исправить это? Вот мой код:

module Main where

data Triangle = Triangle Double Double -- base, height
getTriangle :: Triangle
getTriangle = do
    putStr "Base: "
    baseStr <- getLine
    putStr "Height: "
    heightStr <- getLine
    let base = read baseStr :: Double
    let height = read heightStr :: Double
    Triangle base height

calcTriangle :: Triangle -> Double
calcTriangle (Triangle base height) = base * height

main = putStrLn ("Area = " ++ show (calcTriangle getTriangle))

Спасибо. :)

Ответы [ 2 ]

11 голосов
/ 07 апреля 2010

Функция 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")
3 голосов
/ 07 апреля 2010

Обратите внимание, что вы можете отбросить getTriangle :: Triangle и, запустив :t getTriangle, запрос hugs / ghci сообщит вам, что, по его мнению, должны быть типы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...