这是Haskell permutations
模块中Data.List
函数的代码:
permutations :: [a] -> [[a]]
permutations xs0 = xs0 : perms xs0 []
where
perms [] _ = []
perms (t:ts) is = foldr interleave (perms ts (t:is)) (permutations is)
where interleave xs r = let (_,zs) = interleave' id xs r in zs
interleave' _ [] r = (ts, r)
interleave' f (y:ys) r = let (us,zs) = interleave' (f . (y:)) ys r
in (y:us, f (t:y:us) : zs)
有人可以花些时间向我解释这段代码的工作原理吗?
我的困惑源于这样一个事实:我非常习惯于编写没有外部依赖关系的函数(即使它们嵌套在另一个函数中),特别是如果它们是递归的。由于permutations
内perms
以及t
内ts
和interleave'
的存在,就功能流程而言,我迷失了。
谢谢!
答案 0 :(得分:3)
首先,我将以一种可能更容易重写的形式重写代码
理解,内部函数定义移到main函数之外。请注意,我必须向interleave
添加一些参数
interleave'
这样他们就可以“看到”他们拥有的所有相同变量
在其他功能中定义它们时的访问权限。
为了清晰起见,我还添加了类型签名。
permutations :: [a] -> [[a]]
permutations xs0 = xs0 : perms xs0 []
函数perms
有两个列表,并创建所有可能的列表
两个列表中元素的排列 - 但不包括原始顺序。例如:
λ> perms "ab" "XY"
["aXYb","XaYb","aYXb","YaXb","baXY","abXY","aXbY","bXaY","XbaY","XabY","bYXa","YbXa","YXba","bXYa","XbYa","XYba","bYaX","YbaX","YabX","baYX","abYX","aYbX"]
因此,当我们使用空的第二个列表调用它时,如permutations
所做的那样,它为我们提供了所有其他输入元素的可能排列。我们所要做的就是坚持原始序列,我们得到答案。 (如果你看一下上面的permutations
,你会发现它正是它所做的。)
λ> perms "abc" ""
["bac","cba","bca","cab","acb"]
这是定义或perms
。
perms :: [a] -> [a] -> [[a]]
perms [] _ = []
perms (t:ts) is = foldr (interleave (t:ts)) (perms ts (t:is)) (permutations is)
函数interleave
采用两个列表,并生成所有可能的列表
将它们混合在一起的方式(就像你一包卡片一样)。然后呢
将第三个列表附加到可能的随机播放列表中。例如:
λ> interleave "ab" "XY" ["@", "#"]
["aXYb","XaYb","@","#"]
这是它的定义:
interleave :: [t] -> [t] -> [[t]] -> [[t]]
interleave (t:ts) xs r = let (_,zs) = interleave' (t:ts) id xs r in zs
interleave' :: [t] -> ([t] -> a) -> [t] -> [a] -> ([t], [a])
interleave' (_:ts) _ [] r = (ts, r)
interleave' (t:ts) f (y:ys) r = let (us,zs) = interleave' (t:ts) (f . (y:)) ys r
in (y:us, f (t:y:us) : zs)
答案 1 :(得分:0)
尝试将任何递归调用视为对同一函数的调用,但使用不同的参数(希望,否则您可能会有无限循环),然后尝试遵循一个非常简单的示例的逻辑,如{{1 }},permutations []
或permutations [1]
。
查找内部表达式何时减少到基本情况,这是不再发生递归的地方。例如,permutations [1,2]
的基础案例interleave'
和interleave' _ []
的{{1}}已为。{/ p>
虽然我可能会因为尝试跟踪此函数的绕组而有点迷失,但我相信你会发现某些表达式会达到基本情况并从那里展开,你将能够评估递归调用那导致那里。