Prelude
HaskellのPreludeのなかで比較的簡単そうなの(Monadoとか含まないとか、sin,cosみたいにプリミティブじゃないやつ)を自分で実装してみた。
結構勉強になるかも。
...いや、ふつける欲しいんだけどさ。金無くね...。
まぁ秋休みでやや食費浮くのでその分ふつけるに回してもいいのだけど...
とりあえず何も見ずに、型と実行結果、名前などから機能を類推して自分で実装
その後http://www.sampou.org/haskell/report-revised-j/standard-prelude.htmlで答え合わせ
と言った感じで。
で、動作も完璧、これでok!!とか自信満々に答え見に行くともっと簡単に実装されてるっていうね...
結構ショック。
でもかなり美しい。思わず納得。
...ソースコードみて美しいとかいい始めたら末期だな...。
以下自分の回答が大きく外してる例 / 美しいと思った実装を↓
and
_and [] = True _and (True:bs) = and bs _and _ = False
模範回答
_and = foldr (&&) True
fold系強すぎ...。
break
_break f x = let _break' f' (x':xs') acc' = if f' x' then (acc',(x':xs')) else _break' f' xs' (acc'++[x']) in _break' f x []
苦肉の策の局所宣言。
模範回答(実際にはspanに(not p)を与えてるのですが...
_break :: (a -> Bool) -> [a] -> ([a],[a]) _break p (x:xs) | p x = ([], x:xs) | otherwise = (x:xs', xs'') where (xs',xs'') = _break p xs
美しいなぁ...
concatMap
_concatMap p = foldr (\a b -> (p a) ++ b) [];
concatのコードを少し変えるだけで出来るはずだ!とか思ってやったら
模範回答
_concatMap f = concat . map f
そのまんまconcat利用してました...
lines
模範回答
_lines :: String -> [String] _lines s = let (l,s') = break (== '\n') s in l : case s' of [] -> [] (_:s'') -> _lines s''
さっぱり分からず最初から答えを見に。
美しいなぁ...
reverse
_reverse xs = let _reverse' [] zs = zs _reverse' (y:ys) zs = _reverse' ys (y:zs) in _reverse' xs []
たしかreverseはアキュームレータ使ったの作ってから作った方が楽なはず!!とか授業でやったな、とか思って実装するも...
模範回答
_reverse = foldl (flip (:)) []
またfoldか!!
にしてもうまいなぁ...
splitAt
_splitAt n xs | n <= 0 = ([], xs) _splitAt n (x:xs) = (x:ys, zs) where (ys, zs) = _splitAt (n-1) xs
これは美しくできた!!とか思って絶賛自画自賛。
模範回答
_splitAt n xs = (take n xs, drop n xs)
...そりゃないよ...(д
unlines
_unlines [] = [] _unlines (x:xs) = x ++ "\n" ++ _unlines xs
模範回答
_unlines = concatMap (++ "\n")
ぬ、ぬぅ。確かに考えてみれば...。Stringは[Char]なんだし...。
unzip
_unzip [] = ([], []) _unzip ((x, y):xys) = (x:xs, y:ys) where (xs, ys) = _unzip xys
これは美しく決まった!とか絶賛自画自賛。(splitAtとまったく同じw
模範回答
_unzip = foldr (\(a, b) ~(as, bs) -> (a:as, b:bs)) ([], [])
foldか...そだよね...。
ちなみにこの「~」が未だ謎。「~」の動作は一応は理解...というか「知った」が...。
必須なんだろうか...。そもそも型的にタプル以外来る訳ないし...。そもそも束縛失敗したら関数全体が?ん?よく分からん
やはり「~」が理解できてなさげ。
zip
_zip [] _ = [] _zip _ [] = [] _zip (x:xs) (y:ys) = (x, y) : _zip xs ys
これ以外に書き方無くないか?とか思ってたら
模範回答
_zip = zipWith (,)
zipWithはまだやってねーよ!!(ascii順で一個終わる毎に答え合わせしてた。
てな感じでpreludeをざっと。
haskellおもしろい!!