OCaml
시험을 앞두고, 시험 중에 요긴하게 쓰일만한 내용들을 따로 정리해둔다. 안그럼 돌아서면 까먹고, 누우면 까먹고 그런 상태라..
List Modules
List.fold_left
- List.fold_left는 리스트의 요소들을 처음부터 끝까지 훑으면서 하나의 값으로 합쳐나갑니다.
 - 숫자 리스트의 총합이나 평균을 구할 때
 - 리스트에서 가장 크거나 작은 값을 찾을 때
 - 특정 조건을 만족하는 요소의 개수를 셀 때
 
1
2
3
  | let prices = [1500; 3000; 2500]
(* 0원(초기값)에서 시작해서, 가격을 차례대로 더해나간다 *)
let total_price = List.fold_left (+) 0 prices (* 결과: 7000 *)
  | 
List.map
- List.map은 리스트의 모든 요소에 똑같은 작업을 해서 새로운 리스트를 만듭니다. 리스트의 길이는 변하지 않습니다.
 - 숫자 리스트의 모든 값을 두 배로 만들 때
 - 문자열 리스트의 모든 단어를 대문자로 바꿀 때
 - 사용자 객체 리스트에서 사용자 이름만 뽑아 리스트를 만들 때
 
1
2
  | let scores = [80; 95; 72]
let bonus_scores = List.map (fun score -> score + 5) scores
  | 
List.flatten
- List.flatten은 여러 겹으로 포장된 리스트를 한 겹의 평평한 리스트로 만들어줍니다.
 - map을 사용한 결과가 리스트의 리스트일 때 이를 하나로 합치고 싶을 때 (예: 각 문장(리스트)에서 단어(리스트)를 뽑아 전체 단어 목록을 만들 때)
 - 여러 출처에서 가져온 데이터 목록들을 단일 목록으로 병합할 때
 
1
2
3
4
5
  | let class_A = ["철수"; "영희"]
let class_B = ["민준"]
let class_C = ["수빈"; "지아"; "현우"]
let all_students = List.flatten [class_A; class_B; class_C]
(* 결과: ["철수"; "영희"; "민준"; "수빈"; "지아"; "현우"] *)
  | 
List.find
리스트에서 특정 조건을 만족하는 첫 번째 원소를 찾아주는 함수
1
2
  | (* 리스트 [1; 3; 4; 5; 6] 에서 첫 번째 짝수를 찾아라 *)
List.find (fun x -> x mod 2 = 0) [1; 3; 4; 5; 6];;
  | 
List.for_all
리스트의 모든 원소가 특정 조건을 만족하는지 확인해서 true 또는 false를 반환하는 함수
1
2
  | (* 리스트 [10; 5; 22; 1] 의 모든 원소가 0보다 큰가? *)
List.for_all (fun x -> x > 0) [10; 5; 22; 1];;
  | 
1
2
  | (* 리스트 [10; -5; 22; 1] 의 모든 원소가 0보다 큰가? *)
List.for_all (fun x -> x > 0) [10; -5; 22; 1];;
  | 
for_all은 10을 확인하고, 그 다음 -5를 확인합니다. -5는 0보다 크지 않으므로 조건을 만족하지 못합니다. for_all은 즉시 false를 반환하고 검사를 멈춥니다.
Tree
Tail-Recursive
일단 helper 함수 선언하고, 베이스 케이스를 만들 것!
Example 1
1
2
3
4
5
6
  | type tree = Leaf of int | Node of int * tree * tree
let rec sum_tree t =
  match t with
  | Leaf n -> n
  | Node (n, left, right) -> n + sum_tree left + sum_tree right
  | 
1
2
3
4
5
6
7
8
9
10
  | let sum_tree_tr tree =
  let rec helper acc tr =
    match tr with
    | [] -> acc
    | t :: ts -> (
        match t with
        | Leaf n -> helper (n + acc) ts
        | Node (n, l, r) -> helper (n + acc) (l :: r :: ts))
  in
  helper 0 [ tree ]
 | 
Example 2
1
2
3
4
5
6
  | let rec map_acc f z = function
  | [] -> z, []
  | x :: xs ->
      let z, xs = map_acc f z xs in
      let z, x = f z x in
      z, x::xs
 | 
1
2
3
4
5
6
7
8
9
10
11
12
  | let map_acc_tr f z list =
  let rec reverse xs ys = match xs with
  | [] -> ys
  | x::xs -> reverse xs (x::ys) in
  let rec map_helper f z list acc = match list with
  | [] -> z, acc
  | x::xs -> 
    let z, x = f z x in
    map_helper f z xs (x::acc)
  in 
  let reversed = reverse list [] in
  map_helper f z reversed []
 | 
Module System
Signature
모듈이 어떤 모양이어야 하는지, 어떤 규칙을 지켜야 하는지 정의
1
2
3
4
5
6
7
8
9
  | module type MySignature = sig
  (* 여기에 이 모듈이 반드시 가져야 할 규칙들을 선언합니다. *)
  (* 실제 구현(로직)은 포함하지 않습니다. *)
  type t (* 외부에 공개할 타입의 이름 *)
  val my_value : t (* 반드시 포함해야 할 값 *)
  val my_function : t -> bool (* 반드시 포함해야 할 함수와 그 타입 *)
end
  | 
Modules
시그니처라는 설계도에 맞춰 실제 로직을 구현한 구체적인 부품
1
2
3
4
5
6
7
8
  | module MyModule : MySignature = struct
  (* 시그니처에서 약속한 규칙들을 실제로 구현합니다. *)
  type t = int (* 타입을 구체적인 타입(예: int)으로 정의 *)
  let my_value = 10 (* 값을 구체적으로 할당 *)
  let my_function x = (x > 0) (* 함수의 로직을 실제로 구현 *)
end
  | 
Functors
다른 모듈을 부품으로 입력받아서, 새로운 모듈을 제품으로 만들어냅니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  | (* MyFunctor는 InputSignature 규칙을 따르는 InputModule을 부품으로 받아서,
   OutputSignature 규칙을 따르는 새 모듈을 만듭니다. *)
module MyFunctor (InputModule : InputSignature) : OutputSignature = struct
  (* InputModule의 타입과 함수를 사용해서 새로운 규칙을 정의합니다. *)
  (* 예: 입력받은 모듈의 타입 t를 리스트로 감싸는 새 타입 정의 *)
  type t = InputModule.t list
  (* 예: 입력받은 모듈의 값을 사용하는 새 함수 정의 *)
  let new_function l =
    match l with
    | [] -> false
    | x :: _ -> InputModule.my_function x
end
 | 
Functor Application
펑터라는 공장에 실제 부품(모듈)을 넣어 최종 제품(새로운 모듈)을 생산합니다. 펑터를 테스트하거나 사용할 때 반드시 필요한 과정
1
2
3
4
5
6
7
  | (* 1. 펑터에 부품으로 넣어줄 실제 모듈이 필요합니다. (위에서 만든 MyModule 사용) *)
(* 이미 MyModule은 InputSignature 규칙을 따른다고 가정합니다. *)
(* 2. MyFunctor 공장에 MyModule이라는 부품을 넣어 NewModule을 생산합니다. *)
module NewModule = MyFunctor (MyModule)
(* 이제 NewModule.new_function 과 같은 새로운 기능을 사용할 수 있습니다! *)
  |