Skip to content

Instantly share code, notes, and snippets.

@pocketberserker
Created May 27, 2017 07:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pocketberserker/bede63fdca986f0a41400d2449c31eaf to your computer and use it in GitHub Desktop.
Save pocketberserker/bede63fdca986f0a41400d2449c31eaf to your computer and use it in GitHub Desktop.

岐阜の阜はファンクショナルのF

CC BY-SA 4.0

自己紹介

icon

  • なかやん・ゆーき / ぺんぎん / もみあげ
  • @pocketberserker / id:pocketberserker
  • Microsoft MVP for F# (2013/04/01~ 2017/07)
    • Visual Studio and Development Technologies

関数プログラミングとは?

明確な線引きはない、はず。

アスキードワンゴから出版された『Haskellによる関数プログラミングの思考法』によると:

  • 関数プログラミングはプログラムを構成する方法である。この方法では関数と関数適用を主に使い、命令や命令の実行は使わない。
  • 関数プログラミングでは数学で使う単純な記法を用いる。この記法では問題を簡潔明快に記述できる。
  • 関数プログラミングは単純な数学を基礎とする。この基礎がプログラムの性質に関する等式論証を支えている。

数学云々の話は議論あるかもしれないので今回はスルー。

関数と関数適用

let plusOne x = x + 1

plusOne 1 // 2

関数を引数に適用するから関数適用

F#では関数は数値や文字列と同様に値として扱える。

// List.map: 'T list -> ('T -> 'U) -> 'U list

List.map plusOne [0 .. 9] // [1;2;3;4;5;6;7;8;9;10]

関数を渡せる。

// foo: bool -> ('T -> 'T) -> ('T -> 'T)
let foo cond f =
  if cond then f
  else id

関数を返せる。

適用順序

人間は上から順にコードを読みたい生き物である。

List.take 3 (List.map plusOne [0 .. 9])

[0 .. 9]
|> List.map plusOne
|> List.take 3

(|>)'T -> ('T -> 'U) -> 'Uで、順序を入れ替える。

関数合成

既存の関数を合成することができる。

let mulTwo x = x * 2

[0 .. 9]
|> List.map (plusOne >> mulTwo)

(>>)('T -> 'U) -> ('U -> 'V) -> ('T -> 'V)

再帰とfoldと高階関数と

再帰関数を定義するにはrecキーワードを用いる。

let rec listLength l =
  match l with
  | [] -> 0
  | x::xs -> 1 + listLength xs

[0..9]
|> listLength

多くのデータ構造ではfoldと呼ばれる関数が定義されている。

// List.fold: ('T -> 'U -> 'T) -> 'T -> 'U list -> 'T

[0..9]
|> List.fold (fun r _ -> r + 1) 0

再帰は何でも書けるが、foldは簡潔に賭けて便利なことが多い。 foldで書けない時(あるいはパフォーマンスが関係しているとき)に再帰関数を記述する、という方針を持っておくとよいかも。

束縛、シャドウィング

letを遣えば識別子と値を関連付けられる。

let a = 1

束縛した値を置き換えたいがmutableを使いたくない場合、どうすべきか?

シャドウィングという機能を使えばよい。

let a = 1
let a = 100000
a + 1 // 1000001

最初の束縛は隠蔽されるため、あたかも代入したかのように扱える。

let a = 1 in
let a = 100000 in
a + 1

スコープがあるよ、と考えればわかりやすいかもしれない。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment