unfoldr → scanl
unfoldr の練習の続き。unfoldr で書かれているコードを、他の関数で書き換えてみる。
もとのコードはこれ。Tabulation法で両替問題を解くコードの一部です。
mkqs :: [Count] -> Coin -> [Count] mkqs ps c = unfoldr phi (ps, []) where phi (p:ps, qs) = let q = p + prev (c-1) qs in Just (q, (ps, q:qs)) prev i xs = case genericDrop i xs of [] -> 0 x:_ -> x
今回は種にリストが含まれているから、iterate より scanl がよさそう。
書き直したのがこれ。できあがるリストとほしいリストの型が違うから、map で変換するという操作が必要になるんだ。
なんだか unfoldr も使えそうな気がしてきた。
mkqs :: [Count] -> Coin -> [Count] mkqs ps c = map head $ tail $ scanl phi [] ps where phi qs p = let q = p + prev (c-1) qs in q:qs prev i xs = case genericDrop i xs of [] -> 0 x:_ -> x