《プログラミングの基礎》をReScriptで読む 第13章

[《プログラミングの基礎》](https://www.amazon.co.jp/dp/4781911609/ "Amazonへのリンク")はとても良い本です。
サンプルプログラムをReScriptで書いて、プログラミングの基礎とReScriptを学びます。
# 環境
* macOS Sonoma(バージョン 14.4.1)
* ReScript 11.1.0-rc.8
* @rescript/core 1.2.0
# 第13章
```ReScript:Ex13_1.res
open Ex08_3
open Ex08_4

// person_t list 型のデータの例
let lst = list{person1, person2, person3}
 
// 目的：人のリスト lst のうち血液型が ketsueki0 の人の数を返す
// count_ketsueki : person_t list -> string -> int *) 
let rec count_ketsueki = (lst, ketsueki0) =>
  switch lst { 
  | list{} => 0 
  | list{{name: _, shincho: _, taiju: _, tsuki: _, hi: _, ketsueki: k}, ...rest} =>
      if k == ketsueki0 {1 + count_ketsueki(rest, ketsueki0)}
			else {count_ketsueki(rest, ketsueki0)}
  }

// テスト
Console.log(count_ketsueki(list{}, "A") == 0) 
Console.log(count_ketsueki(lst, "A") == 1) 
Console.log(count_ketsueki(lst, "O") == 1) 
Console.log(count_ketsueki(lst, "B") == 1) 
Console.log(count_ketsueki(lst, "AB") == 0) 
```
```ReScript:Ex13_2.res
open Ex08_3
open Ex08_4

// person_t 型のリストの例
let lst = list{person1, person2, person3} 

// 目的：person_t 型のデータから名前を返す
// take_name : person_t -> string
let take_name = (person) => switch person {
| {name: n, shincho: _, taiju: _, tsuki: _, hi: _, ketsueki: _} => n
}

//テスト
Console.log(take_name(person1) == "浅井")
Console.log(take_name(person2) == "宮原")
Console.log(take_name(person3) == "中村")

// 目的：lst に含まれる人の名前のリストを返す
// person_name : person_t list -> string list
let person_name = (lst) => List.map(lst, take_name)
 
// テスト
Console.log(person_name(list{}) == list{})
Console.log(person_name(lst) == list{"浅井", "宮原", "中村"}) 
```
```ReScript:Ex13_3.res
// (1)
// f1 : 'a -> 'a
let f1 = (x) => x
 
// (2)
// f2 : 'a -> 'b -> 'a
let f2 = (x, _) => x
 
// (3)
// f3 : 'a -> 'b -> 'b
let f3 = (_, y) => y
 
// (4)
// f4 : 'a -> ('a -> 'b) -> 'b
let f4 = (x, f) => f(x)
 
// (5)
// f5 : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c
let f5 = (f, g, x) => g(f(x))
```
```ReScript:Ex13_4.res
// 目的：受け取ったふたつの関数を合成した関数を返す
// compose : ('b -> 'c) -> ('a -> 'b) -> 'a -> 'c
let compose = (f, g) => {
  let h = (x) => f(g(x))
  h
}

// 目的：3 を加える
// add3: int -> int
let add3 = (x) => x + 3

// 目的：2 を掛ける
// times2: int -> int
let times2 = (x) => x * 2
 
// テスト
Console.log(compose(times2, add3)(4) == 14)
```
```ReScript:Ex13_6.res
open Ex09_10
open Ex10_11
open Ex12_1

// 駅の例
let eki1 = {namae: "池袋", saitan_kyori: Float.Constants.positiveInfinity, temae_list: list{}}
let eki2 = {namae: "新大塚", saitan_kyori: 1.2, temae_list: list{"新大塚", "茗荷谷"}}
let eki3 = {namae: "茗荷谷", saitan_kyori: 0., temae_list: list{"茗荷谷"}}
let eki4 = {namae: "後楽園", saitan_kyori: Float.Constants.positiveInfinity, temae_list: list{}}
 
// 目的：未確定の駅 q を必要に応じて更新した駅を返す
// koushin1 : eki_t -> eki_t -> eki_t
let koushin1 = (p, q) => switch (p, q) { 
| ({namae: pn, saitan_kyori: ps, temae_list: pt}, 
   {namae: qn, saitan_kyori: qs, temae_list: _}) => {
    let kyori = get_ekikan_kyori(pn, qn, global_ekikan_list)
    if kyori == Float.Constants.positiveInfinity {q}
    else if ps +. kyori < qs {{namae: qn, saitan_kyori: ps +. kyori, temae_list: list{qn, ...pt}}}
    else {q}
   }
}

// テスト
Console.log(koushin1(eki3, eki1) == eki1)
Console.log(koushin1(eki3, eki2) == eki2)
Console.log(koushin1(eki3, eki3) == eki3)
Console.log(koushin1(eki3, eki4) == {namae: "後楽園", saitan_kyori: 1.8, temae_list: list{"後楽園", "茗荷谷"}})
Console.log(koushin1(eki2, eki1) == {namae: "池袋", saitan_kyori: 3.0, temae_list: list{"池袋", "新大塚", "茗荷谷"}})
Console.log(koushin1(eki2, eki2) == eki2)
Console.log(koushin1(eki2, eki3) == eki3)
Console.log(koushin1(eki2, eki4) == eki4)
```
```ReScript:Ex13_7.res
open Ex12_1
open Ex13_6

// 目的：未確定の駅のリスト v を必要に応じて更新したリストを返す
// koushin : eki_t -> eki_t list -> eki_t list
let koushin = (p, v) => { 
  let f = (q) => koushin1(p, q) 
  List.map(v, f)
}

// 駅リストの例
let lst = list{eki1, eki2, eki3, eki4}
 
// テスト
Console.log(koushin(eki2, list{}) == list{})
Console.log(koushin(eki2, lst) == 
 list{{namae: "池袋", saitan_kyori: 3.0, temae_list: list{"池袋", "新大塚", "茗荷谷"}}, 
  eki2, eki3, eki4})
```