I would like to make easy program in which I could add rectangles to list (id, width, height) and show rectangle with specyfic id (id, width, height) - I think I have more than one error in below code - do You know what can be wrong ? I will run this by command 'menuRectangles' (now this doesn't work):
import IO
import Char
menuRectangles = do
putStrLn "Please choose option:"
putStrLn "1 - Add rectangle"
putStrLn "2 - Show rectangle"
putStrLn "3 - Quit"
putStr "Number: ";
n <- getLine
case n of
"1" -> do addRectangle; menuRectangles;
"2" -> do showRectangle; menuRectangles;
"3" -> menuRectangles;
otherwise -> putStrLn "The End";
addRectangle = do
putStrLn "Id: "
id <- getLine
putStrLn "Width: "
width <- getLine
putStrLn "Height: "
height <- getLine
addingRectangle (Re开发者_StackOverflow中文版ctangle id width height);
showRectangle = do
putStrLn "Choose id rectangle: "
id <- getLine
showingRectangle r[id];
data RectangleType = Rectangle Int Int Int deriving(Show)
addingRectangle r [] = [r]
addingRectangle r rx = r:rx
showingRectangle (Rectangle id width height) = "id: " ++ show id ++ "width: " ++ show width ++ "height: " ++ height ++ "\n";
The solution is to use an accumulating list in menuRectangles
.
When you call addRectangles
you have to bind the result to a new variable - that is what this expression is doing:
rs_new <- addRectangle rs
Note - this is special syntax in Haskell for binding within an IO or monadic expression.
In Haskell the other binding form is let
:
let xs = [2,3,4]
ys = 1 : xs
in length ys
Here's a working version of your program - note you now have to run with main
so it can seed menuRectangles
with the empty list. When menuRectangles
is called recursively for a menu option you have to pass on the accumulating list.
import IO
import Char
main :: IO ()
main = do
xs <- menuRectangles []
mapM print xs
return ()
-- A new helper - this will throw an error
-- if you don't type a number. There are
-- plenty of ways to make it more robust.
--
getInt :: IO Int
getInt = do
xs <- getLine
return (read xs)
menuRectangles :: [RectangleType] -> IO [RectangleType]
menuRectangles rs = do
putStrLn "Please choose option:"
putStrLn "1 - Add rectangle"
putStrLn "2 - Show rectangle"
putStrLn "3 - Quit"
putStr "Number: "
n <- getLine
case n of
"1" -> do { rs_new <- addRectangle rs; menuRectangles rs_new };
"2" -> do { showRectangle rs; menuRectangles rs }
"3" -> do { putStrLn "Quitting"; return rs }
otherwise -> do { putStrLn "The End"; return rs }
addRectangle :: [RectangleType] -> IO [RectangleType]
addRectangle rs = do
putStrLn "Id: "
id <- getInt
putStrLn "Width: "
width <- getInt
putStrLn "Height: "
height <- getInt
let new_rs = addingRectangle (Rectangle id width height) rs
return new_rs
showRectangle :: [RectangleType] -> IO ()
showRectangle rs = do
putStrLn "Choose id rectangle: "
id <- getInt
-- Need a lookup
case findRectangle id rs of
Nothing -> putStrLn ("Not found " ++ show id)
Just rect1 -> putStrLn (showingRectangle rect1)
data RectangleType = Rectangle Int Int Int deriving(Show)
addingRectangle :: RectangleType -> [RectangleType] -> [RectangleType]
addingRectangle r [] = [r]
addingRectangle r rx = r:rx
showingRectangle :: RectangleType -> String
showingRectangle (Rectangle id width height) =
"id: " ++ show id ++ "width: " ++ show width ++
"height: " ++ show height ++ "\n";
-- We have to use Maybe - Just rectangle OR Nothing
-- to account for the case where the id does not match
--
findRectangle :: Int -> [RectangleType] -> Maybe RectangleType
findRectangle _ [] = Nothing
findRectangle n ((Rectangle i w h):xs) =
if n == i then Just (Rectangle i w h) else findRectangle n xs
精彩评论