垂れ流す思考

思考を垂れ流しアウトプットを行うブログ

すごいHaskell楽しく学ぼう!第5章 高階関数

すごいHaskell楽しく学ぼう!Memo

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

噂のすごいH本を読んで楽しくHaskellを学んでいこうというコンセプト ふつうのH本が終わったので次はこっち。

第5章 高階関数

サクッといけると思ったが結構重かった。重要な概念なんで仕方ないね。

  • カリー化関数
  • 部分適用

    この二つの動きは完全に覚えようとのこと。

ただこの二つは難しく考えないですんなりわかると思う。

カリー化関数

要は部分適用ができる関数。

部分適用

少ない引数で呼ばれた時に、残りの引数を取る関数になること。

sum'関数で考えると。

sum' :: Int -> Int -> Int
sum' x y = x + y

(sum' 1) -- このように呼ばれた場合
sum' y = 1 + y -- このような形の関数になること

(sum' 1) 2

Haskellは全ての関数がこのカリー化関数なので2つ以上の引数を取る関数は全て部分適用で処理されていると考える。

高階関数 Higher Order Function

関数を引数にしたり戻り値に関数を返したりする関数
wikiを見ればわかるがカリー化なんかは高階関数の一種...らしい。 -> https://ja.wikipedia.org/wiki/高階関数

私見

Haskellの場合カッコ()を省略する書き方が色々あるため、カッコ()を使う場合は上記の部分適用を使うためが多い気がする。

例えばmap関数で全てのリストに3を加える場合

map (+3) [1..10]

上記のように書くが(+3)は要は

+ (x, y)
+ (x, 3)

こんな感じで、二つの引数を取る関数を一つの引数を取る関数にするために使われている。

やっぱり引数を減らして見やすくするのは重要ですわな。
Ruby on Railsで関数定義する時どんどん引数が増えちゃうのはダメだね。
大きい関数ではなく小さい関数の組み合わせってことだな。
そうなるとやっぱ関数名も自明の方が可読性が上がると...
関数脳大事。

ラムダ式

JavaScript使ってたら定番の無名関数のこと。

// JSの場合
const succNum = x => x + 1

succNum(1) // -> 2
-- Haskellの場合
succNum = \ x -> x + 1

succNum 1 -- -> 2

書き方も見ればわかるかな。バックスラッシュが使われているのは \λ に似ているからだそうですよ。

畳み込み(fold)

foldの説明。
これはrubyでいうreduceみたいな動作を指すのかな?
リストの要素を処理して一つの値を返すこと。

Haskellの畳み込み関数は2引数関数(引数を二つ取る関数)と畳み込みに使う値(アキュムレータaccumulator)の初期値、最後にリストを使う。

underscore.jsとかの関数でaccってなんの略称なのか気になって調べた時、よくわかんなかったけど
ようやく納得いった。アキュムレータっていうですね、賢くなったわ。

foldrとfoldlの左右の違いとかよくわからなかったけどGHCiで書いていったらやっとわかったわ。
リストの左右から評価されるっていうのは言葉通り受け取っていいってことね。
あとはラムダ式を使う場合は引数の順番が違うことに注意かな。

map' :: (a -> b) -> [a] -> [b]
-- foldl leftの場合
map' f = foldl (\acc x -> acc ++ [f x]) []
-- foldr rightの場合
map' f = foldr (\x acc -> f x : acc) []

foldl は左からだから アキュムレータ、各要素... foldr は右からだから ...各要素、アキュムレータ てな感じの解釈で。

畳み込みを自分の中で落とし込むのに時間かかったわ〜

$ を使った関数適用

$はカッコを省略できるみたいな解釈だったけど定義見ると納得いった。

($) :: (a -> b) -> a -> b
 $ f x = f x

普通は関数適用の優先度が高いが$最も低い優先度の右結合なので
(map (+3) [1..5]) -> $ map (+3) [1..5]みたいに書ける。
カッコ消せるのはいいよね。

関数合成とポイントフリースタイル

.で関数を合体できるってやつ関数の返り値を別の関数に適用させる時にいいよねって感じ。 適当なサンプルコードを書こうと思ったけどなんかエラーが出てるからダメだ。
パッとHaskellのコードを書けるようになるには修行が足らぬ。

以上

余談

すごいH本p.73のラムダ式の挿絵に当たり前のようにHalf Lifeの主人公ゴードン・フリーマンが描かれててビビった。
胸に入マークが輝いてますね〜(λだけどね)

俺もHalf Lifeやるか〜

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!