Preludeのつづきのつづきのつづき

昨日はfoldrまでやったので,今日はgcdから.

gcd

最大公約数を求める.ユークリッドの互除法を使うと簡単,ってのを以前結城さんの記事で読んだ記憶が.

gcd' :: Integral a => a -> a -> a
gcd' m 0 = m
gcd' m n = gcd' n (mod m n)

init

リストの末尾を除いたものを返す.ちょっとごり押しな感じもするけど,こんな感じかしら.

init' :: [a] -> [a]
init' [x] = []
init' (x:xs) = x : init' xs

なんというか,

Main> init' "hello"
"hell"

冗談みたいだ.

iterate

第一引数に一引数関数fをとりそれを,第二引数に適用,さらに適用されて出来たものにfを適用し,ってのを繰り返して無限リストを作る.

iterate' :: (a -> a) -> a -> [a]
iterate' f a = a : iterate' f (f a)

簡単に書くと,こうか.ちゃんと動作している以上,これで問題無いみたいだな.

lcm

最小公倍数を求める.求め方は簡単.wikipediaの最小公倍数のページがオススメ.

lcm' :: Integral a => a -> a -> a
lcm' a b = (a * b) `div` (gcd a b)

length

リストの長さを返す.

length' :: [a] -> Int
length' [] = 0
length' (x:xs) = 1 + length' xs

これまたごり押し.

lex

lexical analyzerのlexかしら,文字列を読み込んで,はじめのスペースで区切る.なぜかタプルに入れて.型が良くわかんないので,どう書けば良いのやら.

Hugs.Base> lex "Stadium Arcadium Jupiter"
[("Stadium"," Arcadium Jupiter")]

lines

Stringを引数に取って,改行文字で分けてリストにする.String型をどう処理すれば良いのか分かんないのでカンニング

lines :: String -> [String]
lines "" = []
lines s = let (l, s') = break (== '\n') s
                 in l : case s' of
      	             []        -> []
      	             (_:s'') -> lines s''

えぇ,こんなんワカンネェよ,だけど全て知ってる手続き.でも,このletの使い方は初めてだ.


どうなってるんだろう.

  1. breakを実行.breakは,条件が一致した所でリストをちょん切るんだよね.
  2. sを\nでちょん切って,それを(l, s')ってタプルにletで入れてるのか.なるほど,ちょん切った前半をlに入れて,後半をs'に入れてるのか.
  3. そしてinに移り,ちょん切った後半のs'が空のリストなら,空のリストを返す.空じゃなかったら,_(ワイルドカード)すなわち\nより後ろをlines関数に渡してるんだな!

良く出来てるなぁ.

lookup

第一引数と,第二引数の要素2個のタプルのリストのfstを比較.一致したらそのsndを返す.うへぇ,何書いてるのか分かんないから実際に書いてみるか.

lookup' :: Eq a => a -> [(a,b)] -> Maybe b
lookup' _ [] = Nothing
lookup' a (x:xs) | a == (fst x) = Just (snd x)
                       | otherwise = lookup a xs

うん,コードの方が,駄文より幾らか分かり易いな.このMaybeってのオモロい.

Main> :t Nothing
Nothing :: Maybe a
Main> Nothing
Nothing
Main> :t Just
Just :: a -> Maybe a
Main> Just 1
Just 1

何がしたいねん!!

map

おなじみmap.

map' :: (a -> b) -> [a] -> [b]
map' _ [] = []
map' f (x:xs) = f x : map' f xs

あんなに便利なのに簡単だ.よし,今日はコレぐらいで.