在 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
做的是获取列表的第一个元素 ns
说 t'
运行crossCopyPaste t' (xs, ys)
,拿结果说result1
获取列表中的下一个数字 ns
说 t''
和运行 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)
现在,累加器的初始值只需要是xs
和ys
的初始值。所以我们可以像这样把它们放在一起
crossover ns xs ys = foldl (\acc t -> crossCopyPaste t acc) (xs, ys) ns
我是 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
做的是获取列表的第一个元素 ns
说 t'
运行crossCopyPaste t' (xs, ys)
,拿结果说result1
获取列表中的下一个数字 ns
说 t''
和运行 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)
现在,累加器的初始值只需要是xs
和ys
的初始值。所以我们可以像这样把它们放在一起
crossover ns xs ys = foldl (\acc t -> crossCopyPaste t acc) (xs, ys) ns