ちょっと前に id:uskz 先生に「PStade.OvenはtakenWhileからtakenを定義してるから、Haskellでもできるんじゃないですか」とネタ振りしてたので、書いてみました。
インデックスのリストと一緒にループして、インデックスと比較する述語をxxxWhileに渡します。
インデックスリストは結果としていらないので、最後にインデックスを除いたリストを抽出。
take。
take2 :: Int -> [a] -> [a] take2 n xs = map snd (takeWhile (preds n) (zxs xs)) where zxs xs = zip (enumFrom 0) xs preds n zx = (fst zx) < n main = print $ take2 5 [3..10]
[3,4,5,6,7]
drop。
drop2 :: Int -> [b] -> [b] drop2 n xs = map snd (dropWhile (preds n) (zxs xs)) where zxs xs = zip (enumFrom 0) xs preds n zx = (fst zx) < n main = print $ drop2 5 [3..10]
ちなみに、これを作る過程で、関数の型を以下のように書いたらコンパイルエラーになりました:
take2 :: a -> [b] -> [b]
prog.hs:2:33: Could not deduce (Ord a) from the context () arising from a use of `preds' at prog.hs:2:33-39 Possible fix: add (Ord a) to the context of the type signature for `take2' In the first argument of `takeWhile', namely `(preds n)' In the second argument of `map', namely `(takeWhile (preds n) (zxs xs))' In the expression: map snd (takeWhile (preds n) (zxs xs)) prog.hs:2:43: Could not deduce (Enum a, Num a) from the context () arising from a use of `zxs' at prog.hs:2:43-48 Possible fix: add (Enum a, Num a) to the context of the type signature for `take2' In the second argument of `takeWhile', namely `(zxs xs)' In the second argument of `map', namely `(takeWhile (preds n) (zxs xs))' In the expression: map snd (takeWhile (preds n) (zxs xs))
元々のtakeの定義に合わせて第1引数の型を多相型ではなくIntにしたらコンパイルが通りました。