在Haskell中理解splitAt的问题?
因此,我发现Haskell中的内置splitAt函数可以定义如下:在Haskell中理解splitAt的问题?,haskell,Haskell,因此,我发现Haskell中的内置splitAt函数可以定义如下: splitAt :: Int -> [a] -> ([a], [a]) -- Pre: n >= 0 splitAt n [] = ([], []) splitAt n (x : xs) = if n == 0 then ([], x : xs) else (x : xs', xs'') where (xs', xs'') = splitAt (n - 1)
splitAt :: Int -> [a] -> ([a], [a])
-- Pre: n >= 0
splitAt n []
= ([], [])
splitAt n (x : xs)
= if n == 0
then ([], x : xs)
else (x : xs', xs'')
where
(xs', xs'') = splitAt (n - 1) xs
我在这里不明白/不能理解的是where部分
例如,
splitat2“Haskell”
应该返回([“Ha”],[“skell”])
,但我真的不明白在这里如何将(x:xs',xs')
定义为另一个函数?这在视觉上会是什么样子
举个例子:
splitAt 2 "Haskell"
= (('H':xs',xs''))
^因此,这会在1“askell”处进行拆分,但对于上面元组中的xs',xs'
发生了什么,我感到非常困惑
谢谢
(xs', xs'') = splitAt (n - 1) xs
这将获取一对splitAt(n-1)xs
的结果,并将名称xs'
分配给该对的第一个元素(即xs
的第一个n-1
元素)和xs'
分配给第二个元素(即剩余元素)
这就产生了一对。该对的第一个元素是一个列表,它是将x
前置到xs'
的结果(即,前置到xs
的第一个n-1
元素)。第二个元素是xs'
(即xs
)的其余元素。你所说的“定义(x:xs',xs'')为另一个函数”是什么意思?@sepp2k我的意思是,(xs',xs')=splitAt(n-1)xs这不是另一个函数。这相当于case splitAt(n-1)xs of(xs',xs')->如果n==0,那么…
它只是运行splitAt(n-1)xs
并调用结果的第一部分xs'
和第二部分xs'
。我无法真正想象字符串(x:xs)发生了什么。x在(x:xs',xs'')中实际理解了什么?@AinJalutx
在xs'
@AinJalutxs'
前面加了一个前缀,因此永远不能将一个视为另一个。这里唯一的重复是函数是递归的(因此从这个意义上讲,每次递归调用代码都会重复)。让我们以splitAt 3“编程”为例。所以当我们到达splitAt n(x:xs)时,你是说它会做类似(p:r,o)的事情?下一步是什么?还有,为什么我们要把第三个元素放在逗号后面的空格里?当然,这是分裂错误的东西?@AinJalut如果我们进行splitAt 3“编程”
,这与splitAt n(x:xs)
与n=3
,x='P'
和xs=“编程”
的情况相匹配。因此,行(xs',xs'')=splitAt(n-1)xs
变为(xs',xs'')=splitAt 2“程序设计”
。所以xs'
变成了“ro”
,xs'
变成了“gramming”
。所以结果,(x:xs',xs')
,将是('P':“ro”,“gramming”)
,也就是(“Pro”,“gramming”)
。sepp2k,这里的递归在哪里?在splitAt 2“程序设计”之后,它不是达到了n=0吗?@AinJalut递归的事实是xs'
和xs'
取决于splitAt 2“程序设计”
的结果,这里我简单地说是(“ro”,“gramming”)
,因为我不想把splitAt 2“程序设计”的整个过程都讲一遍
请再说一遍。
(x:xs', xs'')