Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 折叠后不需要后处理步骤就可以实现单词功能吗?_Haskell_Functional Programming_Fold - Fatal编程技术网

Haskell 折叠后不需要后处理步骤就可以实现单词功能吗?

Haskell 折叠后不需要后处理步骤就可以实现单词功能吗?,haskell,functional-programming,fold,Haskell,Functional Programming,Fold,询问是否可以使用折叠实现单词,这也是我的问题: 可能吗?若否,原因为何?如果是,如何进行? 我提出了以下想法,这是基于这样的想法:每个非空格都应该在输出列表中的最后一个单词前加上前缀(这种情况发生在否则保护中),如果没有空格,则空格应该触发将emtpy单词追加到输出列表中(这在中处理,如果-则-否则) 显然,这种解决方案是错误的,因为输入字符串中的前导空格会导致字符串输出列表中的一个前导空字符串 在上面的链接中,我为其他读者研究了几个建议的解决方案,其中许多方案的工作原理与我的解决方案类似,但它

询问是否可以使用折叠实现
单词
,这也是我的问题:

可能吗?若否,原因为何?如果是,如何进行?

我提出了以下想法,这是基于这样的想法:每个非空格都应该在输出列表中的最后一个单词前加上前缀(这种情况发生在
否则
保护中),如果没有空格,则空格应该触发将emtpy单词追加到输出列表中(这在
中处理,如果
-
-
否则

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

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

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

在所有这些方法中,
foldr
(或另一个fold,fwiw)并不是提供开箱即用的最终输出的函数;总有一些其他功能需要以某种方式调整输出

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

myWords :: String -> [String]
myWords input = foldr step seed input

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

(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"
这意味着我们不能有

words = foldr step base
对于任何
步骤
基础

myWords :: String -> [String]
myWords = foldr step [[]]
  where
    step x yss@(y:ys)
      | x == ' ' = if y == "" then yss else "":yss
      | otherwise = (x:y):ys
事实上,如果我们有,那么

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"
这与(2)相矛盾


foldr

@之后,您肯定需要一些后处理。chi有一个很好的论点,即您不能使用“a”折叠实现
单词,但您确实说过使用折叠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

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

是。尽管这有点棘手,但如果您深入到CPS()中,您仍然可以通过使用单个
foldr
来正确地完成这项工作。我以前展示过一种特殊的函数

在这类折叠中,我们的累加器,因此折叠的结果是一个函数,我们必须将它应用于同一类型的输入,这样我们才能得到最终的结果。因此,这可能算不算是最终处理阶段,因为我们在这里使用的是单个折叠,它的类型包括函数。公开辩论:)

sf
:要开始的初始函数值

go
:迭代器函数


实际上,我们并没有充分利用CPS的力量,因为我们在每一轮中都有前一个字符
pc
和当前字符
c
。在上面提到的
chunksOf
函数中,它非常有用,每次元素的升序被打破时,它都会将
[Int]
分块成
[Int]

我想你知道我的意思,但是+1因为挑剔:POr甚至
[“xa”]==单词“xa”==步骤“x”(单词“a”)==步骤“x”(单词“a”)==单词“a”=[“x”,“a”]
,它的优点是可以作为任意折叠方向的有效参数
ws :: String -> [String]
ws str = foldr go sf str $ ""
         where
         sf :: String -> [String]
         sf s = if s == " " then [""] else [s]
         go :: Char -> (String -> [String]) -> (String -> [String])
         go c f = \pc -> let (s:ss) = f [c]
                         in case pc of
                            ""        -> dropWhile (== "") (s:ss)
                            otherwise -> case (pc == " ", s == "") of
                                         (True, False)  -> "":s:ss
                                         (True, True)   -> s:ss
                                         otherwise      -> (pc++s):ss

λ> ws "   a  b    c   "
["a","b","c"]