在 foldl 的 lambda 函数中正确实现一个函数

Properly implementing a function inside foldl's lambda function

我是 haskell 的新手,正在尝试通过在线解决一些难题来学习。

我有这个功能

crossCopyPaste t (as, bs) = (take t as ++ drop t bs, take t bs ++ drop t as) 

只需要一个数字 t 和一对列表 (as, bs)

我还有一个功能

crossover ns xs ys

它接受一个整数列表 ns 和两个列表 xs ys

我想要 crossover 做的是获取列表的第一个元素 nst'

运行crossCopyPaste t' (xs, ys),拿结果说result1

获取列表中的下一个数字 nst''

和运行 crossCopyPaste t'' (fst result1, snd result1)(其结果将是result2

接下来的几个看起来像这样

crossCopyPaste t''' (fst result2, snd result2)

crossCopyPaste t'''' (fst result3, snd result3)

并不断这样做,直到列表中没有任何元素可以覆盖 ns

所以我想到了使用 foldl,因为它需要一个函数、起始元素和一个列表,并像这样应用所有内容

foldl (+) 0 (1:2:3:[])
      =  foldl (+) (0 + 1)             (2:3:[])
      =  foldl (+) ((0 + 1) + 2)       (3:[])
      =  foldl (+) (((0 + 1) + 2) + 3) []
      =            (((0 + 1) + 2) + 3)

但我不知道如何在我上面描述的上下文中实施它。


这是我认为可行的crossover

crossover ns xs ys = foldl (\acc t -> crossCopyPaste t (xs, ys)) 0 ns  

让我们先看看您的函数的签名 crossCopyPaste。 ghci 中的快速检查显示了这一点

> :t crossCopyPaste
crossCopyPaste :: Int -> ([a], [a]) -> ([a], [a])

以及foldl

的签名
> :t foldl
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b

因此我们可以看出传递给 foldl 的函数必须输出与其传递的相同类型。由于 crossCopyPaste 输出类型为 ([a], [a]) 的值,折叠函数需要接受该类型的值作为输入(累加器)。所以你的 lambda 需要看起来像这样:

(\(accx, accy) t -> crossCopyPaste t (accx, accy))

请注意,由于我们实际上不需要拆分元组的值,因此不需要对它们进行模式匹配,我们可以 re-write lambda as

(\acc t -> crossCopyPaste t acc)

现在,累加器的初始值只需要是xsys的初始值。所以我们可以像这样把它们放在一起

crossover ns xs ys = foldl (\acc t -> crossCopyPaste t acc) (xs, ys) ns