おお、短い。
何がどうなっているのか細かく見ていこう。
euler22-1.hsでは使用していなかった
ある関数と何らかの入力値からリストを展開する関数のようだ。
常にJustを返す関数を与えると無限リストを生成する。
マッチしなくなれば
その他、
特にscoreSumのほうは、euler22-1.hsではインデックスをインクリメントしつつスコアの合計値も取り、
最後にインデックスを捨てるという少し煩雑な処理をしていたが、
インデックスを1から始まる無限リストとして扱うことで簡潔に書けるようになった。
何がどうなっているのか細かく見ていこう。
euler22-1.hsでは使用していなかった
fmap
とData.List.unfoldr
を上手く使っているようだ。Data.List.unfoldr
はあまり馴染みが無かったが、foldr
の相対となる関数である関数と何らかの入力値からリストを展開する関数のようだ。
> :t unfoldr unfoldr :: (b -> Maybe (a, b)) -> b -> [a]関数がJustを返すうちはリストの要素を作り続け、Nothingを返した時点で終了するので、
常にJustを返す関数を与えると無限リストを生成する。
> take 10 $ unfoldr (\x -> Just (x, x + 1)) 0 [0,1,2,3,4,5,6,7,8,9]fは正規表現を適用して部分一致したリストと一致した文字列以降の残りの文字列を返すので、
> let f ns = fmap (\(_, _, x, xs) -> (xs, x)) $ matchRegexAll (mkRegex "\"([A-Z]+)\"") ns > f "\"AAA\",\"BBB\",\"CCC\"" Just (["AAA"],",\"BBB\",\"CCC\"")これとnames.txtの内容をunfoldrに与えると、正規表現にマッチする文字列のリストを作ってくれる。
マッチしなくなれば
Text.Regex.matchRegexAll
がNothingを返すので、リストの生成は終了して有限リストが返る。> let listNames names = concat $ unfoldr f names > listNames "\"AAA\",\"BBB\",\"CCC\"" ["AAA","BBB","CCC"]なるほど!
その他、
foldl
で自前でスコアを足し合わせていた2箇所をsum
を使うようにした。特にscoreSumのほうは、euler22-1.hsではインデックスをインクリメントしつつスコアの合計値も取り、
最後にインデックスを捨てるという少し煩雑な処理をしていたが、
インデックスを1から始まる無限リストとして扱うことで簡潔に書けるようになった。