カテゴリー : プログラミング

F# メモ Option

Option型

C#でいうNullable型のようなもので、値を持たないことも表せるようになる。

引数 x が自然数なら x を、負の数なら None (値を持たない) を返す。

> let natural x =
    if x >= 0 then Some x
    else None;;

val natural : int -> int option

Option.get
‘a option -> ‘a

Option型 は Some (値を持っている) か None (値を持たない) のいずれかを表し、
Some の場合は値を取得できる。
None に対し Option.get を行うと例外が発生する。

> let a = natural 100
let b = natural -100
let c = Option.get a;;

val a : int option = Some 100
val b : int option = None
val c : int = 100

Option.isSome
‘a option -> bool

引数が Some なら true を、None なら false を返す。


Option.isNone
‘a option -> bool

引数が Some なら true を、None なら false を返す。

F# メモ List (2)

リスト関数

関数
関数の型
簡単な説明
List.length
‘a list -> int
要素の数を取得する
List.head
‘a list -> ‘a
先頭の要素を取得する
List.tail
‘a list -> ‘a list
先頭の要素を除いたリストを取得する
List.exists
(‘a -> bool) -> ‘a list -> bool
条件に合う要素が存在するか調べる
List.rev
‘a list -> ‘a list
順番を逆にしたリストを取得する
List.tryFind
(‘a -> bool) -> ‘a list -> ‘a option
条件に合う要素を取得する
存在しない場合はNoneを返す
List.zip
‘a list -> ‘b list -> (‘a * ‘b) list
2つのリストの要素を組み合わせ、
タプルのリストを作成する
List.filter
(‘a -> bool) ‘a list -> ‘a list
条件に合う要素のみを含むリストを作成する
List.partition
(‘a -> bool) -> ‘a list -> (‘a list * ‘a list)
条件に合う要素のみを含むリストと
それ以外のリストのタプルを作成する

他にも多数あります。msdn


集約関数 (Aggregate Operators)

リストなどのコレクションには個々の要素に対して何らかの操作を行う関数が多数用意されている。

List.map
(‘a -> ‘b) -> ‘a list -> ‘b list

‘a -> ‘b 変換関数をすべての要素に適用し、’b list を作成する。

例:整数のリストを基に、文字列のリストを作成する。

> let tostr x = sprintf "%d" x
let a = [1..10]
let b = List.map tostr a;;

val tostr : int -> string
val a : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
val b : string list = ["1"; "2"; "3"; "4"; "5"; "6"; "7"; "8"; "9"; "10"]

List.reduce
(‘a -> ‘a -> ‘a) ->’a list -> ‘a

リストの要素を辿りながら ‘a 型のアキュムレータを構築していく関数。
(‘a -> ‘a -> ‘a) の部分は現在のアキュムレータとリストの要素を引数とし、新たなアキュムレータを作成する関数。

例:1から5までの整数の積を求める。(ついでに、アキュムレータの確認を行う)

> let multiple a b =
    printfn "// %3d = %2d * %d" (a*b) a b
    a * b
let b = List.reduce multiple [1..5];;
//   2 =  1 * 2
//   6 =  2 * 3
//  24 =  6 * 4
// 120 = 24 * 5

val multiple : int -> int -> int
val b : int = 120

上の例のように、リストの先頭要素がアキュムレータの初期値となる。


List.fold
(‘acc -> ‘b -> ‘acc) -> ‘acc -> ‘b list -> ‘acc

リストの要素を辿りながら任意の型のアキュムレータを構築していく関数。
List.reduceを汎用的にしたもの。
アキュムレータの初期値を与える必要がある。

例:リスト中の文字数の合計を取得する

> let Count acc (str:string) = acc + str.Length
let dow = [
    "Sunday";
    "Monday";
    "Tuesday";
    "Wednesday"
]
let total = List.fold Count 0 dow;;

val Count : int -> string -> int
val dow : string list = ["Sunday"; "Monday"; "Tuesday"; "Wednesday"]
val total : int = 28

List.iter
(‘a -> unit) -> ‘a list -> unit

指定された関数を、リストの各要素に対して順次実行する関数。

F# メモ List (1)

基本


リストの作成。
[] で囲み、要素は ; で区切る。

> let odds = [1;3;5;7;9]
let evens = [2;4;6;8;10];;

val odds : int list = [1; 3; 5; 7; 9]
val evens : int list = [2; 4; 6; 8; 10]

リストの追加。
@ はリストの結合を行う。

> let appended = odds @ evens;;

val appended : int list = [1; 3; 5; 7; 9; 2; 4; 6; 8; 10]

要素の追加。
:: はリストの先頭に要素を追加する。

> 0 :: appended;;
val it : int list = [0; 1; 3; 5; 7; 9; 2; 4; 6; 8; 10]

範囲を指定する。
1から10までの整数のリストを作成する。

> let x = [1..10];;

val x : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]

範囲と間隔を指定する。
1から10までの奇数のリストを作成する。

> let x = [1..2..10];;

val x : int list = [1; 3; 5; 7; 9]

要素を持たないリスト。

> let emptylist = [];;

val emptylist : 'a list

yield

リストの要素を何らかの手続きで決定させることができる。

> let near x =
    [
        yield x - 1
        yield x
        yield x + 1
    ]
let nearTen = near 10;;

val near : int -> int list
val nearTen : int list = [9; 10; 11]

引数の値とその前後の値を要素とするリストを返す関数 near を作成し、10を与えている。
上から順に評価されるので、10-1=9、10、10+1=11が要素となる。

[] の中には条件式やループ等も使用できる。
30以下の素数のリストを作成する例。

> let primes =
    [
        let factors n =
            [
                for i in 2..n-1 do
                    if n % i = 0 then
                        yield i
            ]
               
        for i in 2..30 do
            if List.length (factors i) = 0 then
                yield i
    ];;

val primes : int list = [2; 3; 5; 7; 11; 13; 17; 19; 23; 29]

F# メモ コメント

行コメント

C++と同じで // から行末までがコメントとして扱われる。


ブロックコメント

(* と *) で囲まれた部分がコメントとなる。

このブロックコメントはネストすることができるので、

1
2
3
4
5
6
(*
    outer comment
    (*
        inner comment
    *)

*)

は正しい。しかし、

1
2
3
4
5
6
(*
    outer comment
    (*
        inner comment
   
*)

はコンパイルエラーとなる。

F# メモ タプル

タプルは複数の値を一つの組として扱う機能。
int と string のタプルの型は int * string と表される。
コンマで区切ることでタプルの作成や要素の取得ができる。

> let t = (1234, "1234");;

val t : int * string = (1234, "1234")

> let d, s = t;;

val s : string = "1234"
val d : int = 1234

タプルを関数の引数にするには以下のように括弧で括る必要がある。

> let sum (a, b, c) = a + b + c

let x = sum (12, 23, 34);;

val sum : int * int * int -> int
val x : int = 69

F# メモ unit

unit は値を持たないことを表す型で、CやC#でいう void のようなもの。
() は unit である。

> let x = ();;

val x : unit = ()

ignore は非 unit な式を unit に変換する関数。
つまり値を使わないことを明示する関数。

> ignore(2*2);;
val it : unit = ()

> 2*2 |> ignore;;
val it : unit = ()

のように使用できる。

TOP