添加矩形列表并显示矩形

时间:2011-04-17 17:50:40

标签: haskell

我想制作一个简单的程序,我可以在其中添加矩形到列表(id,width,height)并显示带有specyfic id(id,width,height)的矩形 - 我想我在下面的代码中有多个错误 - 你知道什么是错的吗?我将通过命令'menuRectangles'来运行它(现在这不起作用):

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 (Rectangle 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";

1 个答案:

答案 0 :(得分:1)

解决方案是使用menuRectangles中的累积列表。

当你调用addRectangles时,你必须将结果绑定到一个新变量 - 这就是这个表达式正在做的事情:

rs_new <- addRectangle rs

注意 - 这是Haskell中用于在IO或monadic表达式中进行绑定的特殊语法。

在Haskell中,另一种绑定形式是let

let xs = [2,3,4]
    ys = 1 : xs
in length ys

这是您的程序的工作版本 - 请注意,您现在必须使用main运行,以便它可以使用空列表来menuRectangles种子。当递归调用menuRectangles菜单选项时,你必须传递累积列表。

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