Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/wordpress/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 如何更改列表中的元素?_List_Haskell - Fatal编程技术网

List 如何更改列表中的元素?

List 如何更改列表中的元素?,list,haskell,List,Haskell,我有一个列表(第一个数字是id矩形,第二个数字是宽度矩形,第三个数字是高度矩形): 如何更改id为2的矩形的宽度和高度?我不知道如何实现函数modifyRectangle 我的代码: modifyRectangle :: [RectangleType] -> Int -> Int -> Int -> IO [RectangleType] modifyRectangle [] _ _ _ = return [] modifyRectangle x idRectangle n

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

如何更改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

为什么要使用单子等来完成这类任务?在我看来,正确的方法是通过一个函数映射矩形列表,如果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