Je ne suis qu'un début programmeur Haskell (et le petit Haskell que j'ai appris il y a 5 ans), mais pour commencer, j'écrirais la traduction naturelle de votre fonction, avec l'accumulateur ("le paragraphe courant") étant passé autour (je l'ai ajouté types, juste pour plus de clarté):
type Line = String
type Para = [Line]
-- Takes a list of lines, and returns a list of paragraphs
paragraphs :: [Line] -> [Para]
paragraphs ls = paragraphs2 ls []
-- Helper function: takes a list of lines, and the "current paragraph"
paragraphs2 :: [Line] -> Para -> [Para]
paragraphs2 [] para = [para]
paragraphs2 ("":ls) para = para : (paragraphs2 ls [])
paragraphs2 (l:ls) para = paragraphs2 ls (para++[l])
Cela fonctionne:
*Main> paragraphs ["Line 1", "Line 2", "", "Line 3", "Line 4"]
[["Line 1","Line 2"],["Line 3","Line 4"]]
Voilà une solution. Mais, l'expérience Haskell suggère qu'il ya presque toujours des fonctions de bibliothèque pour faire des choses comme ça :) Une fonction liée est appelée groupBy, et il fonctionne presque:
paragraphs3 :: [Line] -> [Para]
paragraphs3 ls = groupBy (\x y -> y /= "") ls
*Main> paragraphs3 ["Line 1", "Line 2", "", "Line 3", "Line 4"]
[["Line 1","Line 2"],["","Line 3","Line 4"]]
Oops. Ce dont nous avons besoin est un « splitBy », et it's not in the libraries, mais nous pouvons filtrer les mauvais nous-mêmes ceux:
paragraphs4 :: [Line] -> [Para]
paragraphs4 ls = map (filter (/= "")) (groupBy (\x y -> y /= "") ls)
ou, si vous voulez être cool, vous pouvez vous débarrasser de l'argument et faire la manière inutile:
paragraphs5 = map (filter (/= "")) . groupBy (\x y -> y /= "")
Je suis sûr qu'il y a un moyen encore plus court.:-)
Modifier: ephemient souligne que (not . null)
(/= "")
est plus propre que. On peut donc écrire
paragraphs = map (filter $ not . null) . groupBy (const $ not . null)
La répétition (not . null)
est une forte indication que nous devrions vraiment abstraite ceci en fonction, ce qui est ce que le Data.List.Split module le fait, comme indiqué dans la réponse ci-dessous.
Avez-vous une référence pour ça? Le rapport de la bibliothèque Haskell 98 (http://www.cs.auckland.ac.nz/references/haskell/haskell-library-1.4-html/list.html) * dit * que c'est un prédicat d'égalité, mais donne une implémentation explicite de la fonction groupBy. Notez que la signature de type de groupBy n'a pas de contrainte "Eq", suggérant qu'il est supposé fonctionner avec une fonction de prédicat arbitraire (transitive?) ... Il semble commun de l'utiliser de cette façon: http: //www.haskell .org/haskellwiki/List_function_suggestions # Generalize_groupBy_and_friends – ShreevatsaR
Je préférerais utiliser 'non. null' à l'aide de '(/ =" ")', ce qui conduirait à l'ajout d'un autre point 'map = (filter $ not. null). groupBy (const $ not. null) ' – ephemient