4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Swiftエンジニアが学ぶ高階関数「カリー化関数」

Last updated at Posted at 2017-02-18

はじめに

純粋関数型プログラミング言語であるHaskellを参考に、以下の3つの構成で高階関数についてまとめていく予定です。

本投稿はカリー化関数の概念についてまとめていきます。(別記事は随時更新予定)

高階関数

Haskellの関数は、引数として関数を取ったり返り値として関数を返したりすることが可能で、このような関数は高階関数と呼ばれます。

カリー化関数

Haskellのすべての関数は、複数の引数を取る関数が定義されているように見えますが、公式には引数は一つだけ取るようになっています。
これは関数がカリー化されることによって、複数の引数を取るような関数が定義できているということです。

まずは例を見るのがわかりやすいと思うので、max関数を用いて説明したいと思います。

Prelude> max 4 5
5
Prelude> (max 4) 5
5
Prelude>: Haskellの対話モード

maxは二つの関数を引数にとって、大きい方の数を返す関数に見えます。上記の例では、45を引数に取り、大きい数字である5を返しています。
これは正確には二つの引数を取って結果を返しているのではなく、以下の挙動になっています

  1. maxが最初に4を適用し、別の関数を返り値として返す
  2. 次に返り値である関数が5を適用し、最終的な数値である5を返す

これが上記の例のmax 4 5(max 4) 5が等価である理由です。

このように、カリー化関数とは、常に一つの引数を受け取り、次の引数を受け取るための関数を返す関数のことになります。
次は、自作関数を用いて説明します。

multTree :: Int -> Int -> Int -> Int
multTree x y z = x * y * z

これは、3つの引数を受け取り、3つの数を掛けた数を返します。
正確に言うと、3つの引数を受け取り、3つの数を掛けた数を返すように見える関数です。
この関数を実行してみます

Prelude> multTree 3 5 9
135

挙動は以下のようになります。

  1. 最初にmultTree3を適応し、Int -> Int -> Int型の関数を返す
  2. 次にInt -> Int -> Int型の関数が5を適応し、3と5を掛けた数を返す関数Int -> Intを返す
  3. 最後に9を受け取り、359を掛けた139を返す
Prelude> let multTwo = multTree 9
Prelude> :t multTwo
multiTwo :: Int -> Int -> Int
Prelude> let muitOne = multTwo 3
Prelude> :t muitOne
muitOne :: Int -> Int
:t: 型を調べるコマンド

Swiftから見るカリー化関数

Swiftは様々なプログラミングパラダイムを備えており、関数型プログラミングのアプローチが可能となっています。
Swiftからカリー化関数を見ていきます。

まずは、二つの引数の積を返す関数を定義したいと思います。
通常なら以下の定義をすることが多いと思います。

func multiple(_ x: Int, _ y: Int) -> Int {
    return x * y
}
multiple(3, 5)//15

この関数をカリー化した関数が以下になります。

func multiple(_ x: Int) -> (Int) -> Int {
    return { y in x * y }
}

multiple(3)(5)//15

一つの引数を取る関数の連続になっています。
カリー化してない場合と比較すると、一度に1つの引数に関数を適用するか、2つに適用するかを選択できますね。引数を一つにした場合は以下のように使い回すことができます。

let multClosure = multiple(3)

multClosure(5)//15
multClosure(4)//12

同様にHaskellにおいても、異なる関数を簡単に扱うことができます。

Prelude> multTwo 3 2
162
Prelude> muitOne 5
135

このようにカリー化された関数は抽象度が高く、異なる機能を持つ関数を簡単に作り出せます。
これがカリー化することのメリットと言えますね。

カリー化関数をこのように部分適応することで、関数を簡単に合成することができるので複雑なコードを、関数を使って再構築可能な小さなパーツに分解することができます。
今回は簡単な数式で紹介したので、実践的なイメージがしにくいと思いますが、次回はより実践的な例を用いて高階関数の理解を深めていきたいと思います。

参考文献

4
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?