HaskellでN-gram

N-gramって知ってますか?

任意の文字列に対して、N=2のとき

"hello" => "he", "el", "ll", "lo"

という文字列を生成するものです

これをHaskellで実装するにはどうしたらいいんだろうと考えていました

Stringをtakeでとって...?再帰っぽい??いちいち判定するの??とか考えていましたが、うまく値が取れず悩んでいました
Hoogleで適した関数を探していたのですが、最終手段Google先生に聞いてみました

その回答がこちら

http://codereview.stackexchange.com/questions/70023/function-to-get-ngrams-fast-in-haskell

ngrams :: Int -> [a] -> [[a]]
ngrams n l = take (length l - (n - 1)) . map (take n) . tails $ l

目から鱗でした。めっちゃHaskellっぽい!

Data.Listのtails関数はリストが空になるまでtailを適用する関数
先ほどの例と同じで入力が"hello"だとすると

["hello","ello","llo","lo","o",""]

という値を得られます

map (take n)ですべての要素に対してtakeでn文字取得します

["he","el","ll","lo","o",""]

そして、take (length l - (n - 1))でn文字部分の要素を返しています

["he","el","ll","lo"]

勉強になりました

UTF-8のマルチバイト文字を扱うにはどうしたらいいんだろう とりあえず基本のString型でいいのかな〜