如何更改列表中的元素?

时间:2011-04-23 08:10:42

标签: list haskell

我有一个列表(第一个数字是id矩形,第二个数字是宽度矩形,第三个数字是高度矩形):

[Rectangle 1 33 33, Rectangle 2 23 45, Rectangle 3 34 56]

如何更改id = 2的宽度和高度矩形?我不知道如何实现函数modifyRectangle。

我的代码:

modifyRectangle :: [RectangleType] -> Int -> Int -> Int -> IO [RectangleType]
modifyRectangle [] _ _ _ = return []
modifyRectangle x idRectangle new_width new_height = do
    let (Rectangle id width height) = fromJust (findRectangle idRectangle x)
    -- what next ???????
    return x

findRectangle :: Int -> [RectangleType] -> Maybe RectangleType
findRectangle _ [] = Nothing
findRectangle n ((Rectangle id width height) : xs) =
    if n == id then Just (Rectangle id width height)
    else findRectangle n xs

data RectangleType = Rectangle Int Int Int deriving(Show, Read)

addRectangle :: RectangleType -> [RectangleType] -> [RectangleType]
addRectangle x [] = [x]
addRectangle x xs = x:xs

3 个答案:

答案 0 :(得分:4)

您无法修改它,您可以使用不同的值制作副本。

对此有很多方法,您可以过滤掉原始矩形并添加一个新的矩形(不会保持顺序)或将函数映射到返回传入矩形的原始列表,除非id匹配,在这种情况下,返回新的矩形。

答案 1 :(得分:3)

我的看法:

modifyRect num f = map f'
    where f' rec @ (Rectangle num' _ _)
              | num' == num = f rec
              | otherwise = id rec

modifyRect接受一个函数并将其包装到另一个函数中,该函数仅在矩形的数字匹配时才应用f。否则它只使用身份。

我发现它比其他解决方案更通用,更容易阅读。

答案 2 :(得分:1)

为什么要使用monad等进行此类任务?在我看来,正确的方法是通过一个函数映射矩形列表,如果id匹配则返回新的矩形,如果不匹配则返回原始矩形。请注意,如果您要求的ID不存在,这将使列表保持原样,如果有多个ID具有相同的ID,则会更改所有匹配的矩形。

data RectangleType = Rectangle Int Int Int deriving(Show, Read)

modifyRectangle :: [RectangleType] -> Int -> Int -> Int -> [RectangleType]

modifyRectangle rectangles id new_width new_height = map
  (\ rectangle @ (Rectangle id' width height) -> if id == id'
    then Rectangle id' new_width new_height
    else rectangle) rectangles

示例:

*Main> modifyRectangle [Rectangle 1 42 24, Rectangle 1337 12 34] 1 10 1
[Rectangle 1 10 1,Rectangle 1337 12 34]
*Main> modifyRectangle [Rectangle 1 42 24, Rectangle 1337 12 34] 888 10 1
[Rectangle 1 42 24,Rectangle 1337 12 34]