Haskell数据类型列表

时间:2016-06-01 14:11:18

标签: haskell

我是Haskell的新手,我想制作一个包含列表的程序。我想从键盘下一个元素读取,并将所有内容追加到我现有的列表中。由于我使用了数据类型,因此我不知道如何在名为cars的列表中添加包含所有这些详细信息的新车。   我知道序列let ls = name:model:color:year:price:coin:[cars]是错误的,我不知道如何让它工作。谁能给我一个关于我能在这做什么的想法呢?

type Name = String
type Model = String
type Color= String
type Year = String
type Price = String
type Coin = String
data Car = Car String String String String String String deriving (Show)
cars :: [Car]
cars = [Car "Range Rover" "Sport Supercharged" "Blue" "2015" "85790" "$" ,  Car "BMW" "4-Series" "Black" "2014" "65489" "$"]

main = do
    putStrLn "Car details "
    putStr "Name: "
    name <- getLine
    putStr "Model: "
    model <- getLine
    putStr "Color: "
    color <- getLine
    putStr "Year: "
    year <- getLine
    putStr "Price: "
    price <- getLine
    putStr "Coin: "
    coin <- getLine
    let ls = name:model:color:year:price:coin:[cars]
    putStrLn (show ls)

2 个答案:

答案 0 :(得分:7)

首先我建议你实际使用这些类型的同义词,如果你完全定义它们的话:

data Car = Car Name Model Color Year Price Coin
  deriving (Show)

请注意,这完全等同于声明所有字段String(因为ModelString只是完全相同类型的不同名称),所以更清楚地阅读。如果你使用record fields作为这样的类型,可能更清楚,但这在这里没有什么区别。

现在要从某些字符串属性“创建”新车,您希望将这些属性连接到列表。相反,只需使用Car构造函数并将单个车添加到列表中。

main = do
    putStrLn "Car details "
    putStr "Name: "
    name <- getLine
    ...
    let cars' = Car name model color year price coin : cars
    print cars'

如果您想知道:Car foo bar baz : cars(Car foo bar baz) : (cars)相同。事实上,Car就像其他任何函数一样被使用;你也可以定义一个辅助函数

redCar :: Name -> Model -> Year -> Price -> Coin -> Car
redCar n m y p c = Car n m "red" y p c

然后写

   print $ redCar name model year price coin : cars

OTOH,[cars] 可以预装另一辆车的汽车列表;相反,它是一个带有单个元素的列表 (该元素是汽车列表)。

另一个主题是你在Haskell中如何更新的东西。 ErikR解释了如何通过递归完成此操作;我注意到你可以在Haskell IO代码中也有适当的可变变量。我们通常尽量避免在IO中工作,但如果你真的编写了一个交互式应用程序,那么这是合理的:

import Data.IORef

main = do
    knownCars <- newIORef cars
    putStrLn "Car details "
    ...
    modifyIORef knownCars $ Car name model color year price coin
    print =<< readIORef cars

然后你可以用

来完成
    putStrLn "Details of another car:"
    ...
    modifyIORef knownCars $ Car name2 model2 color2 year2 price2 coin2

实际上已经添加了两辆车。当然,只有整个程序实际上在循环中运行时才有意义。 (事实上​​,“循环”仍然意味着递归。)

答案 1 :(得分:3)

你可能已被告知,Haskell&#34;变量&#34;是不可变的。这意味着你必须明确地将状态作为循环中的参数传递。

例如,这是一个循环,会反复询问用户颜色:

loop1 = do putStrLn "Enter a color: "
           color <- getLine
           loop1

然而,用户的输入没有被保存&#34;任何地方。下一步是跟踪所有先前的输入作为循环函数的参数:

loop2 colors = do putStrLn $ "Previous colors: " ++ show colors
                  putStrLn "Enter a color: "
                  color <- getLine
                  loop2 (color:colors)

希望这有帮助。