본문 바로가기

Computer Science/Programming Language

[프로그래밍 언어/ ML] Records, Datatypes, Case Expressions and more - 컴도리돌이

728x90
728x90

2020/06/15 - [컴퓨터 전공 공부/프로그래밍언어론] - [프로그래밍언어/ML] pairs, lists, local bindings, benefit of no mutation - 컴도리돌이-(1)


Records

 

Records는 label이 부착된 이기종 요소(heterogeneous)의 구조화된 데이터 유형이다. label은 요소들을 어떤 순서로도 작성할 수 있도록 한다.

 

{f1 = e1,..., fn = en} (*Record 값에는 필드(모든 이름) 고정 값이 있음*)
 
{name = "Amelia", id = 41123 - 12}
{id : int, name : string}

<example>

- {abscissa=1.2, ordinate=3.2};
val it = {abscissa=1.2,ordinate=3.2} : {abscissa:real, ordinate:real} 

- {make="Toyota", model="Corolla", year=1986, color="silver"};
val it = {color="silver",make="Toyota",model="Corolla",year=1986}
  : {color:string, make:string, model:string, year:int} 

- {x_dim=2, y_dim=3} = {y_dim=3, x_dim=2}; (* order irrelevant *)
val it = true : bool 

- {a = (), b = 2, c = ("s",2), d = 1};
val it = {a=(),b=2,c=("s",2),d=1} : {a:unit, b:int, c:string * int, d:int} 

- {a = 2.3, b = {a="s",c=45}};
val it = {a=2.3,b={a="s",c=45}} : {a:real, b:{a:string, c:int}} 

- {one = (2.3, "string")};
val it = {one=(2.3,"string")} : {one:real * string} 

- {1=(), 2=true, 3=1};   (* n-tuples are records *)
val it = ((),true,1) : unit * bool * int 

- {1=(), 3=1, 2=true};
val it = ((),true,1) : unit * bool * int 

- {1=(), 3=1};
val it = {1=(),3=1} : {1:unit, 3:int} 

- {34564=1, b=2, b3=3, <*> =4};
val it = {34564=1,<*>=4,b=2,b3=3} : {34564:int, <*>:int, b:int, b3:int} 

- {1=1, 01=01, 001=001}            (* Error! *)
stdIn:23.5-23.10 Error: syntax error: deleting  COMMA INT0 EQUALOP 

- #a {a=3};                  (* field selection *)
val it = 3 : int 

- # a{z=1.2, a=3, b=true, 4=()};
val it = 3 : int 

- #a (#b {b={a=3}});
val it = 3 : int 

- let val r = {r=3} in # r r end;
val it = 3 : int 

- let val ### = 3 in # ## {## = ###} end;
val it = 3 : int

Datatype bindings

 

새로운 유형의 값을 만드는 함수(또는 새로운 유형의 값)이다.

 

데이터 유형 값에 액세스 하는 데는 두 가지 측면이 있다.
1. 어떤 variant인지(어떤 생성자가 만들었는지) 확인
2. 데이터 추출(vairant에 데이터가 있는 경우)

 

 

(*syntax*)
datatype t = C1 of t1 | C2 of t2 | … | Cn of tn


datatype exp = Constant of int 
                    | Negate of exp 
                    | Add of exp * exp 
                    | Multiply of exp * exp


(*An expression in ML of type exp:*)

Add (Constant (10+9), Negate (Constant 4))

 

-How to picture the resulting value in your head

<example>

- datatype color = Red | Blue | Green;
datatype color = Blue | Green | Red 

- Blue;  Red;  Green;
val it = Blue : color
val it = Red : color
val it = Green : color 

- datatype bool = true | false;
datatype bool = false | true 

- fun not (true) = false | not (false) = true;
val not = fn : bool -> bool 

- datatype numbs = i of int | r of real;
datatype numbs = i of int | r of real 

- [i 3, r 3.4, i 5, i 9, r 5.4];
val it = [i 3,r 3.4,i 5,i 9,r 5.4] : numbs list 

- fun isum nil = 0
=   | isum ((i n)::rest) = n+(isum rest) | isum (_::rest) = isum (rest);
val isum = fn : numbs list -> int 

- datatype shape = Rectangle of real*real | Circle of real | Line of (real*real)list
=    | Spline of (real*real)list;
datatype shape
  = Circle of real
  | Line of (real * real) list
  | Rectangle of real * real
  | Spline of (real * real) list 

- Circle (1.2);  Circle (3.4);
val it = Circle 1.2 : shape
val it = Circle 3.4 : shape 

- Rectangle (4.3, 1.9);  Rectangle (40.3, ~8.345);
val it = Rectangle (4.3,1.9) : shape
val it = Rectangle (40.3,~8.345) : shape 

- Line [(1.1, 2.2)];  Line [];
val it = Line [(1.1,2.2)] : shape
val it = Line [] : shape 

- datatype ilist = inil | cons of int * ilist;
datatype ilist = cons of int * ilist | inil 

- datatype itree = empty | node of int * itree * itree;
datatype itree = empty | node of int * itree * itree 

- datatype
=    stmt = Assign | Block of block
= and
=    block = Begin of stmt list;
datatype stmt = Assign | Block of block
datatype block = Begin of stmt list 

- Assign;
val it = Assign : stmt 

- Block (Begin [Assign]);  Block (Begin [Assign, Assign]);
val it = Block (Begin [Assign]) : stmt
val it = Block (Begin [Assign,Assign]) : stmt 

- datatype 'a option = NONE | SOME of 'a;  (* predefined in structure Option *)
datatype 'a option = NONE | SOME of 'a 

- datatype 'a glist = gnil | cons of 'a * 'a glist;
datatype 'a glist = cons of 'a * 'a glist | gnil 

- datatype 'a binary_tree = empty | node of 'a * 'a binary_tree * 'a binary_tree;
datatype 'a binary_tree = empty | node of 'a * 'a binary_tree * 'a binary_tree 

- datatype ('a,'b) union =InLeft of 'a | InRight of 'b;
datatype ('a,'b) union = InLeft of 'a | InRight of 'b 

- InLeft(3); InRight (true); InLeft("s");
val it = InLeft 3 : (int,'a) union
val it = InRight true : ('a,bool) union
val it = InLeft "s" : (string,'a) union 

- [InLeft(3), InRight (true)];
val it = [InLeft 3,InRight true] : (int,bool) union list 

- [InLeft(3), InRight (true), InLeft("s")];  (* type error *)
stdIn:40.1-40.41 Error: operator and operand don't agree [literal]
  operator domain: (int,'Z) union * (int,'Z) union list
  operand:         (int,'Z) union * (string,bool) union list
  in expression:
    InLeft 3 :: InRight true :: InLeft "s" :: nil

Case

 

(*general the syntax*)

case e0 of 
       p1 => e1 
       | p2 => e2 
       … 
       | pn => en

fun f x = 
       case x of
              Pizza => 3
              | TwoInts(i1, i2) => i1+ i2
              | Str s => String.size s

<example>

datatype mytype = TwoInts of int * int
                | Str of string
                | Pizza


- val y = Pizza : mytype;   
val y = Pizza : mytype
- f y;
val it = 3 : int
- val z = Str("hi") : mytype;
val z = Str "hi" : mytype
- f z;
val it = 2 : int
- val x = TwoInts(5,6);
val x = TwoInts (5,6) : mytype
- f x ;
val it = 11 : int

Recursive datatypes

 

datatype bindings은 재귀 구조를 설명할 수 있음

 

datatype my_int_list = Empty
	| Cons of int * my_int_list
    
val x = Cons(4,Cons(23,Cons(2008,Empty)))

fun append_my_list (xs,ys) =
	case xs of
		Empty => ys
		| Cons(x,xs’) => Cons(x, append_my_list(xs’,ys))

 

Options are datatypes

 

Options은 이미 정의된 datatype binding이다.

 

fun inc_or_zero intoption =
	case intoption of
		NONE => 0
		| SOME i => i+1

 

NONE과 SOME은 function이 아닌 constructor이며, pattern-matching 할 때 사용된다. (not isSome, valOf)

 

lists are datatypes

 

(*hd, tl or null을 사용하지 않고..*)

fun sum_list xs =
    case xs of
        [] => 0
        | x::xs' => x + sum_list xs'

fun append (xs,ys) =
    case xs of
        [] => ys
        | x::xs' => x :: append(xs',ys)
728x90
728x90