我有一个列表(第一个数字是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
答案 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]