折叠后是否可以在没有后处理步骤的情况下实现单词功能?

Enr*_*lis 22 haskell functional-programming fold

Real World Haskell,第 4 章,第 98 页询问是否words可以使用折叠来实现,这也是我的问题:

是否可以?如果不是,为什么?如果是,如何?

我想出了以下内容,这是基于这样的想法,即每个非空格都应该添加到输出列表中的最后一个单词之前(这发生在otherwise守卫中),并且空格应该触发将一个空单词附加到如果还没有输出列表(这在if- then- 中处理else)。

myWords :: String -> [String]
myWords = foldr step [[]]
  where
    step x yss@(y:ys)
      | x == ' ' = if y == "" then yss else "":yss
      | otherwise = (x:y):ys
Run Code Online (Sandbox Code Playgroud)

显然,这个解决方案是错误的,因为输入字符串中的前导空格会导致输出字符串列表中的一个前导空字符串。

在上面的链接中,我为其他读者研究了几个建议的解决方案,其中许多解决方案的工作方式与我的解决方案类似,但它们通常对折叠的输出进行“后处理”,例如,tail如果有是一个空的前导字符串。

其他方法使用元组(实际上只是对),因此折叠处理对并且可以很好地处理前导/尾随空格。

在所有这些方法中,foldr(或另一个折叠,fwiw)不是提供开箱即用的最终输出的函数;总是有其他东西必须以某种方式调整输出。

因此,我回到最初的问题并询问是否真的可以words使用折叠来实现(以正确处理尾随/前导/重复空格的方式)。通过使用折叠,我的意思是折叠功能必须是最外层的功能:

myWords :: String -> [String]
myWords input = foldr step seed input
Run Code Online (Sandbox Code Playgroud)

chi*_*chi 17

如果我理解正确,您的要求包括

(1) words "a b c" == words " a b c" == ["a", "b", "c"]
(2) words "xa b c" == ["xa", "b", "c"] /= ["x", "a", "b", "c"] == words "x a b c"
Run Code Online (Sandbox Code Playgroud)

这意味着我们不能有

words = foldr step base
Run Code Online (Sandbox Code Playgroud)

对于任何stepbase

确实,如果我们有那个,那么

words "xa b c"
= def words and foldr
step 'x' (words "a b c")
= (1)
step 'x' (words " a b c")
= def words and foldr
words "x a b c"
Run Code Online (Sandbox Code Playgroud)

这与(2)相矛盾。

您肯定需要在foldr.


luq*_*qui 6

@chi 有一个很好的论点,您无法words使用“a”折叠来实现,但您确实说过使用 fold s

words = filterNull . words1
    where
    filterNull = foldr (\xs -> if null xs then id else (xs:)) []
    words1 = foldr (\c -> if c == ' ' then ([]:) else consHead c) []
    consHead c []       = [[c]]
    consHead c (xs:xss) = (c:xs):xss
Run Code Online (Sandbox Code Playgroud)

最外层和最内层的功能都是折叠。;-)