List 如何更改列表中的元素?
我有一个列表(第一个数字是id矩形,第二个数字是宽度矩形,第三个数字是高度矩形): 如何更改id为2的矩形的宽度和高度?我不知道如何实现函数modifyRectangle 我的代码:List 如何更改列表中的元素?,list,haskell,List,Haskell,我有一个列表(第一个数字是id矩形,第二个数字是宽度矩形,第三个数字是高度矩形): 如何更改id为2的矩形的宽度和高度?我不知道如何实现函数modifyRectangle 我的代码: modifyRectangle :: [RectangleType] -> Int -> Int -> Int -> IO [RectangleType] modifyRectangle [] _ _ _ = return [] modifyRectangle x idRectangle n
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
为什么要使用单子等来完成这类任务?在我看来,正确的方法是通过一个函数映射矩形列表,如果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]
你不能修改它,你可以用不同的值复制一个副本 有许多方法可以实现这一点,您可以过滤掉原始矩形并添加一个新的矩形(不会保持顺序),或者在原始列表上映射一个函数,除非id匹配,否则该函数将返回传入的矩形,在这种情况下,将返回新的矩形。My take:
modifyRect num f = map f'
where f' rec @ (Rectangle num' _ _)
| num' == num = f rec
| otherwise = id rec
modifyRect
接受一个函数并将其包装到另一个函数中,该函数仅在矩形的数目匹配时应用f
。否则它只使用标识
我发现它比其他解决方案更通用、更容易阅读。编写
rectangle@(rectangle id'width)
允许我使用rectangle
而不是重写整个模式(rectangle id'width)
。在模式匹配中非常方便,您希望为变量分配字段,但仍然为整个模式定义名称。顺便说一句,使用id
作为变量是一个相当糟糕的主意。通常,id
是标识函数id x=x
。
modifyRect num f = map f'
where f' rec @ (Rectangle num' _ _)
| num' == num = f rec
| otherwise = id rec