Haskell その7
Listあれこれ。
リストとインデックス
いつものごとく写経しながら動かしながら考える。
http://www.sampou.org/haskell/report-revised-j/list.html
elemIndex val list は、もしあれば、 list 中で最初にあらわれた val のインデックスを Just index として返す。 not (val `elem` list) であれば、 Nothing を返す。
写経。
t1 = elemIndex 3 [0..9] t2 = elemIndex 100 [0..9]
動かす。
*Sample2> t1 Just 3 *Sample2> t2 Nothing
Justとはなんぞや?
elemIndexの型っていったい?…
*Sample2> :type t1 t1 :: Maybe Int
出た、Maybeモナド。
噂には聞いてたけど<オイオイ
次の宿題は決まったな。ということで先へ。
http://www.sampou.org/haskell/report-revised-j/list.html
elemIndices val list は list 中にあらわれる val の出現に対応する インデックスをその順にならべたリストを返す。
写経。
t3 = elemIndices 3 [0,3,0,3,0,3,0] t4 = elemIndices 9 [0,3,0,3,0,3,0]
動かす。
*Sample2> t3 [1,3,5] *Sample2> t4 []
こちらは見つからなかったら空のリストを返すのか。
ふーむ…。
elemIndexは要素が見つからなかったらいったい何を返すのか?
見つからなかったら-1を返す、なーんてそういう姑息なマネはしないわな。
要するにMaybeは例外のためなのかな?…。
つーか、-1のインデックスを指定して要素を取り出すとどーなる?
…がーん、val = list[index] のようなイディオムがわかんない。
http://www.sampou.org/haskell/report-revised-j/list.html
and what the Prelude exports
標準プレリュードにある?
http://www.sampou.org/haskell/report-revised-j/standard-prelude.html
これっぽいですね。
(!!) :: [a] -> Int -> a xs !! n | n < 0 = error "Prelude.!!: negative index" [] !! _ = error "Prelude.!!: index too large" (x:_) !! 0 = x (_:xs) !! n = xs !! (n-1)
やって見る。
*Sample2> [0..9]!!(-1) *** Exception: Prelude.(!!): negative index
む、こちらはあからさまな例外処理。
Haskellの例外処理も宿題だな。
次いこ。
http://www.sampou.org/haskell/report-revised-j/list.html
find は述語を満す最初の要素を返す。もし、見つからない場合 には Nothing を返す。findIndex は対応 するインデックスを返す。findIndices はそのようなすべての インデックスのリストを返す。
写経。
f1 x | x > 0 = True | otherwise = False t5 = find f1 [-1,-2,-3,0,1,2,3] t6 = findIndex f1 [-1,-2,-3,0,1,2,3] t7 = findIndices f1 [-1,-2,-3,0,1,2,3]
動かす。
*Sample2> t5 Just 1 *Sample2> t6 Just 4 *Sample2> t7 [4,5,6]
もう驚かない。
だいたい期待どおりだ。
集合演算
http://www.sampou.org/haskell/report-revised-j/list.html
nub はリストのから要素の重複をとりのぞく。
delete x はそのリスト引数から最初に出現した x を取り除く。
写経。
t8 = nub [0,0,0,1,3,2,3,2,2,2,3,3,0,1,1,1] fparity x y = (x `rem` 2) == (y `rem` 2) t9 = nubBy fparity [0,0,0,1,3,2,3,2,2,2,3,3,0,1,1,1] t10 = delete 3 [0,0,0,1,3,2,3,2,2,2,3,3,0,1,1,1] t11 = deleteBy fparity 3 [0,0,0,1,3,2,3,2,2,2,3,3,0,1,1,1]
これらもなんとなく素直そう。動かす。
*Sample2> t8 [0,1,3,2] *Sample2> t9 [0,1] *Sample2> t10 [0,0,0,1,2,3,2,2,2,3,3,0,1,1,1] *Sample2> t11 [0,0,0,3,2,3,2,2,2,3,3,0,1,1,1]
あ、ウソ。
Byが付く関数が分からない。
http://www.sampou.org/haskell/report-revised-j/list.html
慣例でいうと、多重定義関数には、"By" 接尾辞のついた、 非多重定義関数版がある。例えば、関数 nub は以下のように 定義されている。
nub :: (Eq a) => [a] -> [a]
nub =
nub (x:xs) = x : nub (filter (\y -> not (x == y)) xs)しかし、同等性メソッドはすべての状況で適切であるとは限らない。 次の関数
nubBy :: (a -> a -> Bool) -> [a] -> [a]
nubBy eq =
nubBy eq (x:xs) = x : nubBy eq (filter (\y -> not (eq x y)) xs)ではプログラマが同等性テストを独自に与えることができる。 "By" 関数が、Eq 文脈を二項述語で置き換えた場合、 この述語は同等性を定義するものと仮定される。"By" 関数が Ord 文脈を二項述語で置き換えた場合、この述語は全順序を 定義しているものと見なす。
うー、寝る前にこういうの考えるのは厳し〜。
また明日じっくり理解しよう。
なんだか今日は宿題が多いな。