I wrote a little Haskell program to find the area of a triangle, primarily to practice custom types, but it keeps throwing the following error on compile:
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: ";
.... }
I’m not sure where ‘m b’ comes from, so I’m at a loss here. Why is it throwing this error, and what can I do to fix it? Here is my code:
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))
Thanks. 🙂
The
getTrianglefunction uses IO, so you have to put that in the function signature.Also, the last line should have
return, since it’s returning a pure value inside an IO function.Here are a couple extra tips: Haskell can figure out that
baseandheightareDouble, because you pass them toTriangle, so you don’t need to explicitly declare them that way. You can useliftMfrom theControl.Monadmodule to read the input and convert toDoublein one step.The
mainfunction also appears to mix pure values with IO. Since getTriangle is IO, you can’t pass it directly to calcTriangle. Here is a modifiedmain:As a footnote, the area of a triangle is
base * height / 2, notbase * height.Finally, a more advanced Haskell programmer would probably write
getTrianglein terms ofliftM2, but this is just a matter of style. Here is how I would write it: