Post

OCaml 시험대비 정리

OCaml 시험대비 정리

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 과 같은 새로운 기능을 사용할 수 있습니다! *)
This post is licensed under CC BY 4.0 by the author.