"替换"一个3元组

Nom*_*ics 8 haskell

我有以下列表(这是一个长度为2的列表,但在我的作业中我有一个长度+ n列表)

xxs = [(11,22,[(33,33,33),(44,44,44)]),(55,66,[(77,77,77),(88,88,88)])]
Run Code Online (Sandbox Code Playgroud)

我试图通过列表索引(n)和子列表索引(p)来"替换"一个3元组(p1或p2或p3或p4,从下面的图像).

列表细分的视觉效果

该函数最后应该是这样的:

fooo newtuple n p = (…)
Run Code Online (Sandbox Code Playgroud)

例如:(将p3替换为(98,98,98):

fooo (98,98,98) 2 1 
[(11, 22, [(33,33,33) , (44,44,44)]) , (55, 66, [(98,98,98),(88,88,88)])]  
Run Code Online (Sandbox Code Playgroud)

我按照以下步骤计划了代码:

  1. 访问我想要更改的pn.我设法通过以下方式实现:

    fob n p = ((aux2 xxs)!!n)!!p
       where aux2 [] = []
             aux2 ((_,_,c):xs) = c:aux2 xs
    
    Run Code Online (Sandbox Code Playgroud)
  2. "替换"3元组.我真的需要一些帮助.我被卡住了.我做过的最好的代码(在我脑海里有点意义):(记住:我的代码请不要太糟糕,我只研究Haskell 5周)

    foo n p newtuple = fooAux newtuple fob 
         where fooAux _ [] = [] 
               fooAux m ((_):ds) = m:ds
               fob n p = ((aux2 xxs)!!n)!!p
                  where aux2 [] = []
                        aux2 ((_,_,c):xs) = c:aux2 xs
    
    Run Code Online (Sandbox Code Playgroud)
  3. 最后,我将把所有的东西放在一起,使用splitAt.

我对这个问题的处理方法是否正确?我真的很感激第2步的一些帮助.

man*_*nge 7

我对Haskell也有点新意,但是让我们看看我们是否能够提出一个不错的方法来做到这一点.

所以,从根本上说,我们要做的是修改列表中的内容.使用函数式编程我想保持它有点一般,所以让我们做一个函数update.

update :: Int -> (a -> a) -> [a] -> [a]
update n f xs = pre ++ (f val) : post
  where (pre, val:post) = splitAt n xs
Run Code Online (Sandbox Code Playgroud)

现在,它将采用索引,函数和列表,并将列表中的nth元素替换为应用于它的函数的结果.

然而,在我们更大的问题中,我们需要在嵌套的上下文中进行更新.幸运的是,我们的update函数将函数作为参数,因此我们也可以update在该函数内调用!

type Triple a = (a,a,a)
type Item = (Int, Int, [Triple Int])

fooo :: Triple Int -> Int -> Int -> [Item] -> [Item]
fooo new n p = update (n-1) upFn
   where upFn (x,y,ps) = (x,y, update (p-1) objFn ps)
         objFn _ = new
Run Code Online (Sandbox Code Playgroud)

所有fooo必须做的是调用更新两次(一次在另一个调用中)并做一点"管家"工作(将结果正确地放入元组).在(n-1)和(p-1)人,因为你似乎索引开始1,而哈斯克尔开始于0.

让我们看看它是否适用于我们的测试用例:

*Main> fooo (98,98,98) 2 1 [(11,22,[(33,33,33),(44,44,44)]),(55,66,[(77,77,77),(88,88,88)])]
[(11,22,[(33,33,33),(44,44,44)]),(55,66,[(98,98,98),(88,88,88)])]
Run Code Online (Sandbox Code Playgroud)