我是Haskell的初学者,而且我不了解此代码段的工作方式。我不明白'let'声明中会发生什么,调用'split xys'之后(ls1,ls2)会得到什么?
split :: [(a, b)] -> ([a], [b])
split [] = ([], [])
split ((x, y):xys) = let (ls1, ls2) = split xys
in
(x:ls1, y:ls2)
让我们用一个简短的例子来说明第一次递归迭代:
如果是调用:split [(1,2),(3,4)]
split xys
在第一次迭代中返回什么?以及由于'let'而导致(ls1,ls2)发生了什么?
答案 0 :(得分:4)
split :: [(a, b)] -> ([a], [b])
split
是一个函数,它接收一对列表,然后返回一对列表。它是使用递归定义的:
split [] = ([], [])
拆分空白列表会导致两个空白列表。
split ((x, y):xys) =
此等式定义如何通过模式匹配来拆分列表中包含至少一个元素的列表。列表中第一对的两个部分将分别称为x
和y
,列表的其余部分(第一对之后的剩余部分)将被称为{{1 }}。
xys
此子句将根据递归调用进行定义。我们取出列表中没有第一对的列表,然后调用 let (ls1, ls2) = split xys
,记住,它将返回一对两个列表。我们再次使用模式匹配,因此split
和ls1
将是这两个列表。
ls2
我们将根据需要返回一对新列表。第一个列表将包含递归调用中的第一个列表,以及我们在递归之前切断的对的第一部分。第二个列表将类似地包含递归调用中的第二个列表,再加上我们在递归之前切断的对的第二部分。
示例:
in (x:ls1, y:ls2)
:这不会拆分空白列表,因此第二个等式匹配。 split [(1,2),(3,4)]
绑定到x
,1
绑定到y
,而2
绑定到xys
。我们在[(3, 4)]
上递归调用split。在此递归执行中,[(3, 4)]
是x
,3
是y
,而4
是xys
。我们再次递归调用[]
,这次匹配了基本情况并返回了split
。在第一个递归调用中,这意味着([], [])
绑定到ls1
,而[]
绑定到ls2
。因此[]
是x:ls1
,而[3]
是y:ls2
,因此此递归调用将返回[4]
。原始调用将获得此结果,因此([3],[4])
绑定到该对的第一个组件ls1
,而[3]
绑定到第二个组件ls2
。因此[4]
是x:ls1
,而[1, 3]
是y:ls2
。因此,顶级调用将返回[2, 4]
。