查看hackage中span的定义,我们发现这个有用的提示:
span p xs 等价于 (takeWhile p xs, dropWhile p xs)
所以,正如您将函数定义为
group' [] = []
group' (x:xs) = (x : takeWhile (== x) xs) : group' (dropWhile (== x) xs)
您可以很容易地看到在这种情况下您的p 是(== x)。所以,在上面的 span 定义中替换它
span p xs = (takeWhile p xs, dropWhile p xs)
span (== x) xs = (takeWhile (== x) xs, dropWhile (== x) xs)
span 返回一对列表,因此您可以使用fst 和snd 访问它们。
所以我们有这个
takeWhile (== x) xs = fst (span (== x) xs)
和
dropWhile (== x) xs = snd (span (== x) xs)
使用它,我们可以像这样在您的原始函数中替换它们:
group' [] = []
group' (x:xs) = (x : fst (span (== x) xs) ) : group' (snd (span (== x) xs) )
当然,用相同的参数调用同一个函数两次(span (== x) xs)并不好,所以让我们用let绑定调用它一次:
group' [] = []
group' (x:xs) = let s = span (== x) xs in (x : (fst s)) : group' (snd s)
我喜欢 Haskell 最终只是数学的方式,您可以仅使用一些代数方程将某些定义(例如您用于 takeWhile 和 dropWhile 的定义)替换为其他定义(跨度)!