top page > computer > haskell > web_lecture > for_programmer > taketo_unfoldr.html
更新日:
文責: 重城良国

関数takeToの関数unfoldrによる定義

takeTo_unfoldr.hs

はじめに

抽象化のしかたはひとつではない。そこが面白い。関数takeToはの型は

takeTo :: (a -> Bool) -> [a] -> [a]

だ。「リストを引数にとる関数」なので関数foldrで定義した。「リストを返す関数」でもあるので関数unfoldrでも定義できる。

生の再帰

takeTo p [] = []
takeTo p (x : xs)
| p x = [x]
| otherwise = x : takeTo p xs

xが条件を満たすならそれ以降の要素は不要なのでxだけから成るリストを返す。満たさないならば再帰的にtakeTo pを残りのリストに適用した結果にxを追加する。

関数foldrによる定義

takeTo p = foldr (\x -> (x :) . if p x then const [] else id) []

xが条件を満たすときは続く値をとわず空リスト(const [])に、満たさないときは続く値に再帰的に関数を適用した結果そのもの(id)に、xを追加した値を返す。

関数unfoldrによる定義

モジュールData.Listが必要だ。

import Data.List

takeTo p = unfoldr $ \s -> case s of
[] -> Nothing
x : xs | p x -> Just (x, [])
| otherwise -> Just (x, xs)

リストの先頭を結果として返しながら要素を先頭から削っていくイメージだ。xが条件pを満たしたときは次にわたすリストは空リストとする。

まとめ

関数takeToを「リストをとる関数」として、あるいは「リストを返す関数」として、の2通りで抽象化できることを学んだ。覚えようとする必要はない。たくさんの例を見ていくことで体で覚えよう。

「関数unfoldrの定義」へもどる 「構文: @パターン」へ

正当なCSSです! HTML5 Powered with CSS3 / styling, and Semantics