O Mundo Real Haskell, capítulo 4, página 98 da impressão pergunta se words
pode ser implementado usando dobras, e esta é minha pergunta também:
É possível? Se não, por que? Se for, como?
Eu vim com o seguinte, que é baseado na ideia de que cada não-espaço deve ser anexado à última palavra na lista de saída (isso acontece no otherwise
guarda) e que um espaço deve acionar o acréscimo de uma palavra vazia ao a lista de saída, se ainda não houver uma (isso é tratado no 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
Claramente, esta solução está errada, uma vez que os espaços iniciais na cadeia de entrada resultam em uma cadeia vazia principal na lista de cadeias de saída.
No link acima, examinei várias das soluções propostas para outros leitores, e muitas delas funcionam de forma semelhante à minha solução, mas geralmente "pós-processam" a saída da dobra, por exemplo tail
, se houver é uma string inicial vazia.
Outras abordagens usam tuplas (na verdade, apenas pares), para que a dobra lide com o par e possa lidar com os espaços iniciais / finais.
Em todas essas abordagens, foldr
(ou outra dobra, fwiw) não é a função que fornece a saída final pronta para uso; sempre há algo mais para ajustar a saída de alguma forma.
Portanto, volto à pergunta inicial e pergunto se é realmente possível implementar words
(de uma maneira que ele lide corretamente com espaços à direita / à esquerda / repetidos) usando dobras. Por usando pregas que significa que a função de dobragem tem de ser o mais exterior função:
myWords :: String -> [String]
myWords input = foldr step seed input