views:

186

answers:

2

Can anyone help with this exersise?

Write a program which asks the user for the base and height of a right angled triangle, calculates its area and prints it to the screen. The interaction should look something like:

The base?
3.3
The height?
5.4
The area of that triangle is 8.91

Solved with:

getTriArea :: IO Float
getTriArea = do
 putStr "The base? "
 base <- getLine
 putStr "The height? "
 height <- getLine
 let ar = ( (read base :: Float) * (read height :: Float) )/ 2
 return ar

main = do 
 result <- getTriArea
 putStr $ "The area of that triangle is " ++ show result
+1  A: 
getTriArea :: IO Float
getTriArea = do
 putStr "The base? "
 base <- getLine
 putStr "The height? "
 height <- getLine
 let ar = ( (read base :: Float) * (read height :: Float) )/ 2
 return ar

main = do 
 result <- getTriArea
 putStr $ "The area of that triangle is " ++ show result
Roman Shestakov
The type annotations and parens on those reads are redundant. You can just write `read base * read height / 2`. Function application is left-associative.
Chuck
+10  A: 

What you have works, but it is better Haskell style to separate pure from IO. Your getTriArea computation doesn't need to be locked up in the IO monad: lift it out!

import Control.Applicative

prompt :: (Read a) => String -> IO a
prompt s = putStr s >> read <$> getLine

triArea :: (Fractional a) => a -> a -> a
triArea base height = (base * height) / 2

main :: IO ()
main = do
    area <- triArea <$> prompt "The base? " <*> prompt "The height? "
    putStrLn $ "The area of that triangle is " ++ show (area :: Float)

Applicative isn't actually necessary, it just provides a few pretty infix operators. Monad works just fine.

import Control.Monad

prompt :: (Read a) => String -> IO a
prompt s = putStr s >> fmap read getLine

triArea :: (Fractional a) => a -> a -> a
triArea base height = (base * height) / 2

main :: IO ()
main = do  -- pick one of the following two lines
    area <- liftM2 triArea (prompt "The base? ") (prompt "The height? ")
    area <- return triArea `ap` prompt "The base? " `ap` prompt "The height? "
    putStrLn $ "The area of that triangle is " ++ show (area :: Float)

In a short program like this, it doesn't really matter all that much, but note that even those imports, the triArea definition can remain pure.

prompt :: (Read a) => String -> IO a
prompt s = putStr s >> getLine >>= return . read

triArea :: (Fractional a) => a -> a -> a
triArea base height = (base * height) / 2

main :: IO ()
main = do
    base <- prompt "The base? "
    height <- prompt "The height? "
    let area = triArea base height
    putStrLn $ "The area of that triangle is " ++ show (area :: Float)
ephemient