-
[프언] #13. Automatic Type Inference2023-2학기/프로그래밍언어 2023. 12. 10. 02:29
지난 글에서 Type Checker를 구현하는 과정에서, Proc Expression을 단순 Recursion으로 구현할 수 없는 문제가 있었습니다. 그 문제를 해결하기 위해 프로시져를 정의할 때, 프로시져에 들어가는 인수의 Type을 미리 지정하는 방식인 Type Annotation을 사용했었고요. 이번 글에서는 다른 방식인 Type Inference를 이용해 이 문제를 해결해보도록 하겠습니다.
Automatic?
Type Annotation은 프로그래머가 필요한 Type을 직접 지정하도록 하는 방식이었다면, Type Inference는 알려지지 않은 Type을 프로그램이 자동으로 추리해 내는 방식입니다.
Examples of Type Inference
if x then x-1 else 0
위와 같은 코드가 있다고 가정합시다. 코드라고 말했지만 이 코드는 사실 큰 ITE (If Then Else) Expression과 같습니다. 저희는 이 큰 ITE Expression의 Type을 알아내는게 목적이겠죠. 저희가 알아내고자 하는 Type을 t0라고 정의하겠습니다.
ITE Expression에서 저희는 조건문, 그러니까 If 다음에 들어가는 Exprssion은 Bool이라는 사실을 알고 있습니다. If 다음에 오는 Expression은 x이죠. 근데 아직 저희는 x의 Type을 모르기 때문에 이를 tx라고 하겠습니다. 그러면, tx=bool 라고 적을 수 있습니다.
그다음으로 Then과 Else 다음에 들어가는 Expression은 전체 Expression의 Type임도 알고 있죠. Then 다음에 오는 Expression은 x-1인데, 저희는 아직 이것의 Type을 모르기 때문에 이를 t1이라고 두겠습니다. 그러면 t1=t0 이죠. t0가 Expression 전체의 Type이니깐요.
Else 다음에 들어가는 Expression은 0 역시 t0일텐데, 저희는 0이 Int Type이라는 걸 알고 있죠. 따라서, int=t0 입니다.
그다음으로는 아직 분해되지 않은 Expression인 x-1을 보겠습니다. Subtraction Expression에서, - 기호 양쪽에 오는 Expression의 Type은 모두 Int여야 합니다. 따라서 tx=int, t1=int 임을 알 수 있습니다.
지금까지 나온 식들을 전부 나열하면 아래와 같습니다.
tx=bool
t1=t0
int=t0
tx=int
t1=int
이런 식들을 Type Equation이라고 합니다. 이제 주어진 프로그램에서 얻을 수 있는 Type Equation을 전부 적고 나면, 이제 이를 전부 만족하는 근이 있는지를 체크해 보면 됩니다.
다들 아시다시피, 첫 번째 식과 네 번째 식은 동시게 참이 될 수 없습니다. 따라서 이 Type Equations를 만족하는 근이 없으므로 Type Error가 발생하게 됩니다.
proc f (f 11)
위 코드도 같은 방법으로 풀어보겠습니다. 먼저 전체 Expression의 Type을 t0로 정의합니다. 이 Expression은 Proc Expression이며 Proc Expression의 Type은 f와 (f 11)에 의해 정해집니다. 저희는 아직 이 두 Expression의 Type을 모르기 때문에, f의 Type을 tf, (f 11)의 Type을 t1이라고 정의해 두겠습니다. 그러면 t0=tf→t1 입니다.
그리고 (f 11)은 프로시져 f에 11을 넣어 나오는 값을 의미합니다. 11은 Int이고 (f 11)의 Type은 t1이므로 저희는 프로시져 f의 Type이 int→t1 임을 알 수 있습니다. 따라서, tf=int→t1 입니다.
위 코드를 통해서는 아래와 같은 Type Equation들을 얻을 수 있었습니다.
t0=tf→t1
tf=int→t1
위 식들을 만족하는 근은 존재할까요? 존재합니다. t1에 대한 조건이 없으므로 아래와 같은 근을 도출할 수 있습니다.
(t0,t1,tf)=((int→t)→t,t,int→t)for∀t∈T
따라서 Type Error가 발생하지 않습니다.
이렇게 차근차근 저희가 정의해 왔던 문법을 짚어가며 Type Equation을 도출할 수도 있지만, 각 Expression을 정의할 때 사용했던 Inference Rule을 이용해서 Type Equation을 도출할 수도 있습니다.
한 예시로, 더하기 기호를 정의할 때 위와 같은 형태의 Inference Rule을 사용했었습니다. 위 Inference Rule을 통해 아래와 같은 Type Equation을 만들 수 있습니다.
같은 방식으로, 아래와 같은 관계식을 적을 수 있습니다.
Formalizing Type Inference
각각의 Type Equation들을 나타내는 기호로 TyEqn을 사용하겠습니다. 그리고 이 Type Equation들을 만드는 알고리즘을 아래와 같이 정의하겠습니다.
ν(Γ,e,t)는 Γ의 Environment 내부에서 e가 Type t를 가진다는 것을 의미합니다. 간단한 예시를 들자면, ν([x↦int],x+1,α)=alpha≐int 입니다.
이제 이런 식으로 정의된 ν를 통해 Type Equation을 만들어낼 수 있습니다.
이를 이용해 어떤 프로그램이든 Recursive 하게 Type Equation을 얻어낼 수 있습니다. 아래는 간단한 예시입니다.
Solving Type Equations
이제 코드를 보고 Type Equation들을 얻어내는 알고리즘은 만들었으므로, 만들어진 Type Equation을 보고 이를 해결하는 과정이 필요합니다.
proc f proc x ((f 3) - (f x))
위 식을 통해서 아래와 같은 Type Equation들을 얻었다고 생각해 봅시다.
위 Type Equation을 해결하기 위해 다음과 같은 방법을 사용할 겁니다. 먼저 Equation, Substitution 이렇게 2가지 구역을 만든 뒤 모든 Type Equation들을 Equation 영역에 넣습니다.
그리고 이제 Equation 영역에 있는 식들을 하나하나 Substitution으로 넘겨줄 건데요,
일단 첫 번째 식을 Substitution으로 넘기면 이런 모습이 됩니다. 다음으로는 두 번째 식을 옮길 건데요, 옮기는 식의 좌변이 t1이잖아요? 이때 Substitution 영역에 있는 식에 t1이 존재하면, 그걸 tx→t2로 바꿔치기해 줍니다.
이렇게요. 같은 방식으로 쭉 옮겨줍니다.
다음으로 옮길 식은 tf=int→t3인데요, 같은 과정으로 옮기되 t3의 Type은 이미 Int로 확정되었기 때문에 t3 대신 Int를 적어서 옮겨줍니다.
마지막 식을 보면 t4의 Type이 Int로, tf의 Type이 Int → Int로 결정되어 있습니다. 따라서, 정리하면 아래와 같습니다.
이 식은 2개의 식으로 분리가 가능합니다.
이 2개의 식 역시 Substitution으로 옮겨주는데, 첫 번째 식은 의미가 없는 식이므로 생략합니다.
이렇게 Type Equation의 해결이 끝났습니다.
감사합니다.
이 글은 컴퓨터공학과 학부생이 개인 공부 목적으로 작성한 글이므로, 부정확하거나 틀린 내용이 있을 수 있으니 참고용으로만 봐주시면 좋겠습니다. 레퍼런스 및 글에 대한 기본적인 정보는 이 글을 참고해 주세요.
'2023-2학기 > 프로그래밍언어' 카테고리의 다른 글
[프언] #15. Subtype Polymorphism (0) 2023.12.13 [프언] #14. Let-Polymorphic Type System (0) 2023.12.10 [프언] #12. Manual Type Annotation (0) 2023.12.05 [프언] #11. Type System (0) 2023.12.04 [프언] #10. Concrete/Abstract Syntax (1) 2023.11.20