私は最初のハスケルプログラマーです(そして5年前に学んだ小さなHaskellですが) )(私はわかりやすくするために、種類を追加しました)の周りに渡される:
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])
これは動作します:
*Main> paragraphs ["Line 1", "Line 2", "", "Line 3", "Line 4"]
[["Line 1","Line 2"],["Line 3","Line 4"]]
だから、ソリューションです。しかし、その後、Haskellの経験は、このようなものを行うためのライブラリ関数は、ほとんど常に存在していることを示唆している:)一つの関連機能をgroupByと呼ばれ、それはほとんど動作します:
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"]]
おっと。私たちが本当に必要なのは「splitBy」であり、it's not in the librariesが、我々は自分自身を悪いものを除外することができます。
paragraphs4 :: [Line] -> [Para]
paragraphs4 ls = map (filter (/= "")) (groupBy (\x y -> y /= "") ls)
か、あなたはクールになりたい場合は、あなたが引数を取り除くと、それを行う得ることができます無意味な方法:
paragraphs5 = map (filter (/= "")) . groupBy (\x y -> y /= "")
さらに短い方法があると確信しています。:-)
編集:ephemientは(not . null)
が(/= "")
よりもクリーンであることを指摘しています。だから我々は
paragraphs = map (filter $ not . null) . groupBy (const $ not . null)
を書くことができます繰り返し(not . null)
は、私たちが本当に機能にアウトこの抽象べき強力な指標であり、以下の回答で指摘したように、これは、Data.List.Split moduleが何をするかです。
あなたはそれについての参考文献を持っていますか? Haskell 98のライブラリレポート(http://www.cs.auckland.ac.nz/references/haskell/haskell-library-1.4-html/list.html)*は、これは等価述語ですが、明示的に実装していますgroupBy関数groupByの型シグネチャには "Eq"という制約はなく、任意の(推移的な)述語関数で動作するはずであることを示唆しています...このように使用するのが一般的です:http://www.haskell .org/haskellwiki/List_function_suggestions#Generalize_groupBy_and_friends – ShreevatsaR
私は 'notを使うのが好きです。 '(= =" ")'を使用することになります。これにより、さらにポイントフリーの 'paragraphs = map(filter $ not。null)につながります。 groupBy(const $ not。null) ' – ephemient