Haskell: Why does he say my function type is disabled?

I wrote a small Haskell program to find the region of a triangle, primarily for practicing custom types, but it continues to throw the following compilation error:

areafinder.hs:7:4: Couldn't match expected type `Triangle' against inferred type `mb' 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 don't get it here. Why is he throwing this error and what can I 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.:)

+4
source share
2 answers

The getTriangle function uses IO, so you must put it in the function signature.

 getTriangle :: IO Triangle 

In addition, the last line must have return , since it returns a pure value inside the I / O function.

 return (Triangle base height) 

Here are some additional tips: Haskell can understand that base and height are Double , because you pass them to Triangle , so you don't need to explicitly declare them that way. You can use liftM from the Control.Monad module to read input and convert to Double in one step.

 import Control.Monad getTriangle :: IO Triangle getTriangle = do putStr "Base: " base <- liftM read getLine putStr "Height: " height <- liftM read getLine return (Triangle base height) 

The main function also displays pure values ​​with IO. Since getTriangle is an IO, you cannot pass it directly to calcTriangle. The following is the main change:

 main = do tri <- getTriangle putStrLn ("Area = " ++ show (calcTriangle tri)) 

As a footnote, the area of ​​the triangle is base * height / 2 , not base * height .

Finally, the more advanced Haskell programmer will probably write getTriangle in terms of liftM2 , but this is just a matter of style. Here is how I wrote it:

 prompt str = putStr (str ++ ": ") >> liftM read getLine getTriangle = liftM2 Triangle (prompt "Base") (prompt "Height") 
+11
source

Note that you can drop getTriangle :: Triangle and by running :t getTriangle , the hugs / ghci hint will tell you what it thinks the types should be.

+3
source

Source: https://habr.com/ru/post/1306184/


All Articles