我编写了一个小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: ";
.... }
我不确定'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))
感谢。 :)
答案 0 :(得分:11)
getTriangle
函数使用IO,因此您必须将其放在函数签名中。
getTriangle :: IO Triangle
此外,最后一行应该有return
,因为它在IO函数中返回一个纯值。
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")
答案 1 :(得分:3)
请注意,您可以删除getTriangle :: Triangle
并通过运行:t getTriangle
来表示拥抱/ ghci提示,它会告诉您它认为类型应该是什么。