[PL] Ocaml : 리스트, 타입 정의

parkheeddong·2023년 5월 30일
0
post-thumbnail

1. List


1) element의 유한한 sequence

🌱 모든 element는 동일한 type을 가지고 있어야 한다.

[1;2;3] 은 정수 리스트이다.
[1;true] 는 옳지 않다.

🌱 element는 ordered되어있다.

[1;2] != [2;1]

🌱 첫 element는 head이며 마지막 element는 tail이다.

[] 는 empty list이다.
[5] 는 single element를 가진 리스트이다.




2) 리스트 연산자

🌱 :: 은 새로운 값을 리스트에 삽입하는 연산자이다.

0 :: [1;2;3] => [0;1;2;3]

🌱 @는 두 리스트를 concatenate 하는 연산자이다.

[1;2;3] @ [4;5;6] => [1;2;3;4;5;6]

module F = Format

let _ =
  let print_list name lst =
    let _ = F.printf "%s: [" name in
    let _ = List.iter (fun x -> F.printf "%d " x) lst in
    F.printf "]\n"
  in 
  let lst = [] in (*empty list*)
  let lst' = 1 :: lst in  (*[1]*)
  let lst'' = 2 :: lst' in (*[2;1]*)
  let another_lst = [3;4;5] in (*[3;4;5]*)
  let lst''' = lst'' @ another_lst in (*2;1;3;4;5*)
  let _ = print_list "lst" lst in (* []*)
  let _ = print_list "lst'" lst' in (*[1]*)
  let _ = print_list "lst''" lst'' in (*[2 1]*)
  let _ = print_list "another_list" another_list in (*[3 4 5]*)
  print_list "lst'''" lst''' (*[2 1 3 4 5]*)



3) List.iter 함수

🌱 ('a -> unit) -> 'a list -> unit

iterator로서, 함수를 인자로 받고 list를 받고 함수를 list의 요소에 적용한 뒤 unit을 반환한다.
(즉 아무것도 반환하지 않는다)

List.iter(fun x -> F.printf "%d" x) [1;2;3]
=> 
(fun x -> F.printf "%d" x) 1;
(fun x -> F.printf "%d" x) 2;
(fun x -> F.printf "%d" x) 3;



4) List.map 함수

한 함수를 인자로 받고, 리스트를 받고, 리스트를 반환한다.

함수를 리스트에 적용하여 리스트를 반환한다

List.map(fun x -> x+1)[1;2;3]
=> 
[(fun x -> x+1) 1; (fun x->x+1) 2; (fun x-> x+1) 3]

5) List.fold_left 함수

한 함수를 인자로 받고, 임의의 값을 받고, 리스트를 받은 이후 새로운 값을 반환한다.

List.fold_left (fun i x -> i + x) 0 [1;2;3] 
=> 
(fun i x -> i + x) ((fun i x -> i + x) ((fun i x -> i + x) 0 1) 2 ) 3

🌱 'a는 arbitary type 을 의미한다. (임의의 타입)

타입을 가리키지 않으며 정수, 문자열, 어떤 것이든 될 수 있다.




6) 리스트에 대한 패턴 매칭 케이스

🌱 [] => empty list

🌱 h :: t => h 는 first element를, t는 remaining element를 의미한다.

let _ = 
  let rec len lst =
    match lst with
    | [] -> 0
    | _ :: t ->
      1 + (len t)
  in 
  let _ = F.printf "Len: %d\n" (len []) in 
  let _ = F.printf "Len: %d\n" (len [1]) in
  let _ = F.printf "Len: %d\n" (len [1;2]) in
  F.printf "Len: %d\n" (len [1;2;3;4]) 

🔔 Example

[1;2;3;4;5];;
// int list = [1; 2; 3; 4; 5]

["OCaml"; "Java"; “C"];;
// string list = ["OCaml"; "Java"; "C"]

[(1,"one"); (2,"two"); (3,”three")];;
// (int * string) list = [(1, "one"); (2, "two"); (3, "three")

[[1;2;3];[2;3;4];[4;5;6]];;
// int list list = [[1; 2; 3]; [2; 3; 4]; [4; 5; 6]]

[1;"OCaml";3] ;;
//Error: This expression has type string but an expression was expected of type int



2. 타입 정의(Type Definition)




1) 타입 정의

Ocaml에서는 새로운 타입을 정의할 수 있다.

type [type_name] = [type]

type str_lst = string list (* str_list type definition*)

let _ =
  let is_empty (x: str_list) =
    match x with
    | [] -> true
    | _ :: _ -> false
  in
  let _ = F.printf "Res %b\n" (is_empty []) in (*true*)
  let _ = F.printf "Res %b\n" (is_empty ["welcome";"to";"this";"class"]) (*false*)



2) 변수의 타입 정의

변수의 타입도 정의할 수 있다.

type [type_name] = [name] (of [type])? (\ [name] (of [type])?)*


type number =
  Zero              (* Zero Constructor : 값 받지 않고 number type 값 생성*)
  | Integer of int  (* Integer Constructor : 정수값 하나를 받고 number type 값 생성*)
  | Real of float   (* Real Constructor : 실수값 하나 받고 number type 값 생성*)
// number은 Zero일수도, Integer일수도, Real일 수도 있다.


let _ =
  (* number type의 constructor을 이용하여 number type 생성*)
  let x : number =  Zero in 
  let y : number = Integer 3 in 
  let z : number = Float 3.0 in 
  let n_list : number list = [x;y;z] in 
  ()



3) 다양한 타입에 대한 패턴 매칭

type number =
  Zero              (* Zero Constructor : 값 받지 않고 number type 값 생성*)
  | Integer of int  (* Integer Constructor : 정수값 하나를 받고 number type 값 생성*)
  | Real of float   (* Real Constructor : 실수값 하나 받고 number type 값 생성*)

let print (n: number) =
  match n with 
  | Zero -> F.print "Val: zero\n" 
  | Integer i -> F.print "Val: Int %d\n" i
  | Float f -> F.print "Val: Float %f\n" f 

let _ =
  let _ = print Zero in 
  let _ = print (Integer 1) in 
  print (Float 9.9)

🔔 Example

type number =
  Zero              (* Zero Constructor : 값 받지 않고 number type 값 생성*)
  | Integer of int  (* Integer Constructor : 정수값 하나를 받고 number type 값 생성*)
  | Real of float   (* Real Constructor : 실수값 하나 받고 number type 값 생성*)

let print (n: number) =
  match n with 
  | Zero -> F.print "Val: zero\n" 
  | Integer i -> F.print "Val: Int %d\n" i
  | Float f -> F.print "Val: Float %f\n" f 

let add (n1: number) (n2: number) : number
match n1, n2 with
      | Zero, Zero -> Zero
      | Zero, Integer i (*this match case performs the same expression to the next case*)
      | Integer i, Zero -> Integer i
      | Zero, Floatf -> Float f
      | Floatf, Zero -> Float f
      | Integer i1, Integer i2 -> Integer (i1 + i2)
      | Float f1, Float f2 -> Float(f1 +. f2)
      | Float f, Integer i
      | Integer i, Float f -> Float((float_of_int i) +. f)

let _ =
    let _ = print (add Zero Zero) in (*Val: zero*)
    let _ = print (add (Integer 1) (Integer 3)) in (*Val: Int 4*)
    print (add (Float 1.7) (Integer 5)) (*Val: Float 6.7*)

0개의 댓글