25. 複数の値をひとつの値に!
• タプル (e1, e2, …, en)
> (1, 2) ;;
val it : int * int = (1, 2)
> ("one", 2, 3.0) ;;
val it : string * int * float = ("one", 2, 3.0)
> let a = () ;;
val a : unit = ()
27. 純粋な関数
ラムダ計算においては、関数は常に一引数
関数定義: 関数適用:
fun x -> x + 1 ;; f x ;;
> let myFun = fun x -> x * x ;;
val myFun : int -> int
> myFun 10 ;;
val it : int = 100
28. 純粋な関数
ラムダ計算においては、関数は常に一引数
関数定義: 関数適用:
fun x -> x + 1 ;; f x ;;
複数の引数を扱うには
どうすればいいの?
> let myFun = fun x -> x * x ;;
val myFun : int -> int
> myFun 10 ;;
val it : int = 100
29. タプルを使おう!
> let myFun = fun (x, y) -> x + y ;;
val myFun : int * int -> int
> myFun (30, 70) ;;
val it : int = 100
let stream = // .NET Framework のメソッド
File.Open ("a.txt", FileMode.Open, FileAccess.Read)
30. 練習(fst, snd)
タプルの第1要素を返す関数を定義してみよう
> let fst' = fun (x, _) -> x ;;
val fst' : 'a * 'b -> 'a
> fst' ("first", 2) ;;
val it : string = "first"
Keyword : ワイルドカード、総称型、型推論
34. 関数の中に関数?
λx.λy. x y
> let f = (fun x -> (fun y -> x + y)) ;;
val f : int -> int -> int
> f 10 ;;
val it : (int -> int) = <fun:it@38-6>
35. 関数の中に関数?
> (f 4) 6 ;;
val it : int = 10
> f 1 2 ;; // 左結合
val it : int = 3
関数を入れ子にすることで、
複数の引数を扱う関数を表現できる!
36. 関数の中に関数?
let add = fun x -> fun y -> fun z -> x+y+z ;;
> add 20 30 50 ;;
⇒ (fun x -> (fun y -> (fun z -> x + y + z))) 20 30 50
⇒ (fun y -> (fun z -> 20 + y + z)) 30 50
⇒ (fun z -> 20 + 30 + z) 50
⇒ 20 + 30 + 50
⇒ 100 !!
37. 省略記法
let f = fun x -> fun y -> fun z -> x y z ;;
let f = fun x y z -> x y z ;;
let f x y z = x y z ;;
39. カリー化とは?
• f (x, y, z)
「x を受け取り、[残りの引数をとる関数]を返す」
形に変形する
let f (x, y, z) = x + y + z ;;
let f x = (fun (y, z) -> x + y + z) ;;
let f x = (fun y -> (fun z -> x + y + z)) ;;
40. カリー化とは?
> let f1 (x, y, z) = x + y + z ;;
val f1 : int * int * int -> int
> let f2 x y z = x + y + z ;;
val f2 : int -> int -> int -> int
> f1 10 ;; // Error
> f2 10 ;;
val it : (int -> int -> int) = <fun:it@66-7>
41. カリー化とは?
• ‘a * ‘b -> ‘c を
• ‘a -> ‘b -> ‘c に変換するのがカリー化
• let f x y z = ~ で定義されるのは
カリー化された関数
42. 部分適用とは?
> let f x y = x + y ;; // fun x -> fun y -> x + y
val f : int -> int -> int
> let add1 = f 1 ;; // fun y -> 1 + y ;;
val add1 : (int -> int)
> add1 9 ;;
val it : int = 10
> add1 99 ;;
val it : int = 100
43. 練習(curry, uncurry)
‘a * ‘b -> ‘c の型の関数をカリー化する関数を定義しよう
> let curry f x y = f (x, y) ;; // 高階関数
val curry : ('a * 'b -> 'c) -> 'a -> 'b -> 'c
> let f1 (x, y) = x + y ;;
val f1 : int * int -> int
> let f2 = curry f1 ;; //部分適用
val f2 : (int -> int -> int)
> f2 50 80 ;;
val it : int = 130
47. リスト
• 単方向連結リスト
• List の定義
– []
– x :: List
> [] ;; => val it : 'a list = []
> 1 :: [] ;; => val it : int list = [1]
> 1 :: 2 :: 3 :: [] ;;
val it : int list = [1; 2; 3]
48. リスト
List の定義
– []
– x :: List
> List.head [1; 2; 3] ;;
val it : int = 1
> List.tail [1; 2; 3] ;;
val it : int list = [2; 3]
> List.head (List.tail (List.tail [1; 2; 3])) ;;
???
49. リスト
List の定義
– []
– x :: List
> List.head [1; 2; 3] ;;
val it : int = 1
> List.tail [1; 2; 3] ;;
val it : int list = [2; 3]
> List.head (List.tail (List.tail [1; 2; 3])) ;;
val it : int = 3
50. Listモジュール
append fold iteri2 ofArray sortBy
average fold2 length ofSeq sortWith
averageBy foldBack map partition sum
choose foldBack2 map2 permute sumBy
collect forall map3 pick tail
concat forall2 mapi reduce toArray
empty head mapi2 reduceBack toSeq
exists init max replicate tryFind
exists2 isEmpty maxBy rev tryFindIndex
filter iter min scan tryPick
find iter2 minBy scanBack unzip unzip3
findIndex iteri nth sort zip zip3
51. List.map : ('a -> 'b) -> 'a list -> 'b list
すべての要素に関数を適用
> let add1 x = x + 1 ;;
val add1 : int -> int
> List.map add1 [9; 99; 999] ;;
val it : int list = [10; 100; 1000]
> List.map (fun x -> x + 1) [1; 2; 3] ;;
val it : int list = [2; 3; 4]
52. List.map : ('a -> 'b) -> 'a list -> 'b list
すべての要素に関数を適用
> ( + ) ;;
val it : (int -> int -> int) = <fun:it@25-4>
> ( + ) 1 1 ;;
val it : int = 2
> List.map (( + ) 1) [1; 2; 3] ;; // 部分適用
val it : int list = [2; 3; 4]
53. List.filter : ('a -> bool) -> 'a list -> 'a list
関数の適用結果が真の要素だけ抽出
> let even x = x % 2 = 0 ;;
val even : int -> bool
> List.filter even [1; 2; 3; 4; 5; 6; 7; 8] ;;
val it : int list = [2; 4; 6; 8]
> List.filter (( < ) 4) [1; 5; 6; 2; 3; 7] ;;
val it : int list = [5; 6; 7]
54. 定義してみると・・・
let rec MyMap f list' =
match list' with
| [] -> []
| x :: rest -> f x :: MyMap f rest
let rec MyFilter f = function
| [] -> []
| x :: rest when f x -> x :: MyFilter f rest
| _ :: rest -> MyFilter f rest
これは何だ・・・(?_?)
56. パターソマッチ
let MyMatch1 tuple =
match tuple with
| (0, 0) -> "zero"
| (x, y) when x > y -> ">"
| (x, y) when x < y -> "<"
| _ -> "="
> MyMatch1 (3, 5) ;;
val it : string = "<"
> MyMatch1 (2, 2) ;;
val it : string = "="
57. もしパターンマッチがなかったら...
let MyMatch1' tuple =
if fst tuple = 0
&& snd tuple = 0 then "zero"
elif fst tuple > snd tuple then ">"
elif fst tuple < snd tuple then "<"
else "="
58. パターンマッ千
let MyMatch2 list' =
match list' with
| [] -> 0
| [x] -> x
| [x; y] -> x - y
| _ -> failwith "エラー!"
> MyMatch2 [13; 3] ;;
val it : int = 10
> MyMatch2 [1; 2; 3] ;;
System.Exception: エラー!
59. 八゚ターンマッチ
let rec MyMatch3 list' =
match list' with
| [] -> 0
| x :: rest -> x + MyMatch3 rest
> [1 .. 5] ;;
val it : int list = [1; 2; 3; 4; 5]
> MyMatch3 [1 .. 3] ;;
???
60. 八゚ターンマッチ
let rec MyMatch3 list' =
match list' with
| [] -> 0
| x :: rest -> x + MyMatch3 rest
> [1 .. 5] ;;
val it : int list = [1; 2; 3; 4; 5]
> MyMatch3 [1 .. 3] ;;
val it : int = 6
61. パ夕ーンマッチ
type Color =
| Red
| Green
| Blue
| White
let MyMatch4 color =
match color with
| Red -> "あか"
| Green -> "みどり"
| _ -> "そのた"
62. pat :=
const -- constant pattern
long-ident pat-paramopt patopt -- named pattern
_ -- wildcard pattern
pat as ident -- "as" pattern
pat '|' pat -- "or" pattern
pat '&' pat -- "and" pattern
pat :: pat -- "cons" pattern
pat : type -- pattern with type constraint
pat,...,pat -- tuple pattern
(pat) -- parenthesized pattern
list-pat -- list pattern
array-pat -- array pattern
record-pat -- record pattern
:? atomic-type -- dynamic type test pattern
:? atomic-type as ident -- dynamic type test pattern
null -- null-test pattern
attributes pat -- pattern with attributes
65. [<AbstractClass>]
type BaseClass() =
abstract Method1 : int -> int
type IBase =
abstract Method2 : int -> int
type SubClass() =
inherit BaseClass()
override self.Method1 x = x + 10
interface IBase with
member self.Method2 x = x * 10
67. [<Measure>] type h
[<Measure>] type km
[<Measure>] type cm
[<Measure>] type cm2 = cm ^ 2
> 155<km/h> ;;
val it : int<km/h> = 155
> 5<cm> * 8<cm> ;;
val it : int<cm ^ 2> = 40
> let a : int<cm2> = 2<cm> * 10<cm> ;;
val a : int<cm2> = 20
> 1<h> + 2<cm> ;;
error: The unit of measure 'cm' does not match the unit of measure 'h'
69. let (|S|A|B|C|) score =
if score >= 80 then S
elif score >= 60 then A
elif score >= 40 then B
else C
let GiveGrade score =
match score with
| S -> "たいへんよい"
| A -> "よい"
| B -> "がんばろう"
| C -> "ゆとり"
71. 式を <@ ~ @> で囲うと、式木を得られる
Microsoft.FSharp.Quotations
> <@ let f x = x + 10 in f 90 @> ;;
val it : Expr<int> =
Let (f,
Lambda (x,
Call (None, Int32 op_Addition[Int32,Int32,Int32](Int32, Int32),
[x, Value (10)])), Application (f, Value (90)))
{CustomAttributes = [NewTuple (Value ("DebugRange"),
NewTuple (Value ("stdin"), Value (5), Value (7), Value (5), Value (10)))];
Raw = ...;
Type = System.Int32;}
72. Microsoft.FSharp.Quotations.Patterns
let MyFun = function
| Var v -> "変数だよー : " + v.Name
| Value (o, _) -> "定数値だよー : " + o.ToString ()
| NewTuple _ -> "タプルだよー"
| Call _ -> "関数呼び出しだよー"
| Lambda _ -> "λ式だよー"
| _ -> "その他"
> MyFun <@ 100 @> ;;
val it : string = "定数値だよー : 100"
> MyFun <@ 1 + 1 @> ;;
val it : string = "関数呼び出しだよー"
> MyFun <@ fun x -> x @> ;;
val it : string = "λ式だよー"