↓ 본문으로 건너뛰기

[Coq 입문] Ch01. Functional Programming in Coq (1)

·3 분
nyan101
작성자
nyan101
목차
Coq 입문 - 이 글은 시리즈의 일부입니다.
[Coq 입문] Ch01. Functional Programming in Coq (1)

Introduction

여기서는 Coq에서 사용되는 Galina라는 functional programming language의 기초적인 사용법과, Coq에서 증명에 실제 활용되는 기초적인 tactic에 대해 다룬다.

Data and Functions

Days of the Week

먼저 Coq에서 타입을 선언하는 법을 알아보자. 모든 Coq 구문은 .(마침표)로 끝남에 유의하자

Inductive day : Type :=
| monday
| tuesday
| wednesday
| thursday
| friday
| saturday
| sunday.

day 타입에는 monday, tuesday 등의 원소가 있다. 편의상 원소라는 용어를 사용하지만 엄밀히 말해 ‘원소’라는 표현보단는 ‘인자 0개를 가지는 생성자’로 이해하는 편이 좋다.

이제 day 타입을 다루는 함수를 하나 정의하자

Definition next_weekday (d:day) : day :=
match d with
| monday => tuesday
| tuesday => wednesday
| wednesday => thursday
| thursday => friday
| friday => monday
| saturday => monday
| sunday => monday
end.

next_weekday 함수는 day 타입의 인자 d를 받아 day 타입을 반환한다. Compute 를 통해 함수를 실행시켜볼 수 있다.

공간상의 문제로 앞으로는 간단히 아래처럼 표기하자. >> 가 있는 줄은 입력. 빈 줄 이후에 이어지는 내용은 그에 대한 출력을 의미한다.

>> Compute (next_weekday (next_weekday friday)).
  
  = tuesday
    : day

Example 키워드로 함수의 동작 예시에 이름을 붙여 기록할 수 있다.

Example test_next_weekday:
  (next_weekday (next_weekday saturday)) = tuesday.

Example도 증명이 필요하다. 아래쪽에 다음을 추가해 test_next_weekday에 대한 증명을 추가할 수 있다.

Proof. simpl. reflexivity. Qed.

Proof, Qed, simpl 등 키워드에 대해서는 다시 설명하겠지만 잠시 과거의 잔재를 통해 어떻게 동작하는지 감을 잡을 수 있다.

Booleans

앞서 day 타입을 정의한 것과 유사하게, 이번엔 bool 타입을 정의해보자. 상식을 거스르지 않고 이번에 만들 bool 타입도 2개의 원소를 가진다.

Inductive bool : Type :=
| true
| false.

day 때와 비슷하게 함수를 정의할 수 있다. 2변수 함수를 정의하는 부분에 유의해서 살펴보자. (orb는 andb와 거의 동일하므로 생략)

Definition negb (b:bool) : bool :=
match b with
| true => false
| false => true
end.

Definition andb (b1:bool) (b2:bool) : bool :=
match b1 with
| true => b2
| false => false
end.

Coq에서는 Notation 키워드를 통해 함수에 새로운 표기를 추가할 수 있다.

Notation "x && y" := (andb x y).
Notation "x || y" := (orb x y).

그러면 추가된 표기를 이용한 표현이 가능하다.

>> Compute (true || (false && true)).

  true : bool

Types

모든 expression은 타입을 가지고 있다. Check 키워드를 통해 기존에 만든 원소들의 타입을 확인해보자.

>> Check true.

  true : bool
>> Check andb.

  andb : bool -> bool -> bool

New Types from Old

기존에 정의된 타입을 이용해 새로운 타입을 정의할 수 있다. ‘생성자(constructor)‘라는 용어를 염두에 두고 아래 정의를 살펴보자.

Inductive rgb : Type :=
| red
| green
| blue.

Inductive color : Type :=
| black
| white
| primary (p : rgb).

red, green, blue는 rgb타입의 원소이고, black, white는 color타입의 원소가 된다. 또한 primary red는 color 타입의 원소가 된다. 마찬가지로 primary green, primary blue는 color 타입이 되지만, primary true는 color 타입이 아니다.

이렇게 만들어진 타입에 대해서도 함수를 정의할 수 있으며, 하스켈과 유사하게 _를 더미(dummy)로 하는 패턴 매칭을 사용할 수 있다.

Definition isred (c:color) : bool :=
match c with
| black => false
| white => false
| primary red => true
| primary _ => false
end.

isred가 color -> bool인 함수이므로 (isred red)는 올바른 expression이 아님에 주의하자. (단, (isred (primary red))는 올바른 expression이다)

Tuples

한 constructor가 여러 인자를 가질 수도, 패턴 매칭에서 여러 인자를 한번에 매칭시킬 수도 있다.

Inductive bit : Type :=
| B0
| B1.

Inductive nybble : Type :=
| bits (b0 b1 b2 b3 : bit).

Definition all_zero (nb:nybble) : bool :=
match nb with
| (bits B0 B0 B0 B0) => true
| (bits _ _ _ _) => false
end.

Check, Compute를 통해 생각한 대로 동작하는지 확인해보자.

Modules

지금까지 작성한 모든 코드는 전역(global scope)에 속한다. 단순히 예제를 따라해보는 거라면 몰라도 코드가 복잡해질수록 모든 걸 전역으로 두는 대신 영역을 나눠야 할 필요성이 커진다. 자바의 패키지, C++의 네임스페이스처럼 Coq에서는 모듈을 제공한다.

Module XXX.
(* code *)
End XXX.

이렇게 모듈 내부에 정의된 요소들은 모듈 바깥에서 XXX.Y 로 불러올 수 있다.

Coq 입문 - 이 글은 시리즈의 일부입니다.
[Coq 입문] Ch01. Functional Programming in Coq (1)

관련 글

[Coq 입문] Ch00. Overview

·3 분
Coq를 공부해보겠다는 막연한 목표와 함께 이런저런 자료를 찾아보고 그만두기를 반복하던 중, DeepSpec Summer School 세미나에서 나온 영상을 발견했다. 유투브에서 찾은 다른 영상들이 4,5년 전 자료였던 반면 DeepSpec에서는 최근인 2017, 2018년까지 꾸준히 학습자료와 세미나 영상이 업로드되고 있다. 사실 예전 LaTeX을 익힐 때에도 이것저것 찾아보기만 하다가 결국 학교 과제를 LaTeX으로 작성해보고서야 익숙해졌는데, 이번에도 실 사용 없이 공부하는게 얼마나 갈지는 잘 모르겠다.. 자료 초반에 “All the core chapters are suitable for both upper-level undergraduate and graduate students.” 라는 말이 있던데, 물론 저런 말들이 다 그렇듯이 전부 거짓말이겠지만 이젠 undergraduate 신분이라는 핑계도 사라졌으니 좀더 확실히 짚고 넘어가야겠다는 생각도 든다.

Coq 02 - 자연수 덧셈의 결합법칙 증명

·5 분
대부분의 reference가 그렇듯이 읽다보면 쉽게 지루해진다. 지루함을 덜하고 Coq에 익숙해지기 위해 일단 예제를 조금씩 따라해보면서 익혀가기로 했다. 자바를 처음 배울 때 public static void main(int argv, char **argc)가 정확히 뭔지는 몰라도 “Hello World” 부터 찍어보는 그런 마음으로 진행해봤다. CoqIDE 실행 프로그램을 처음 실행하면 다음과 같은 화면을 볼 수 있다. 크게 3가지 창으로 나뉘어져 있으며, 왼쪽은 코드 작성을, 오른쪽 위/아래는 각각 Proof 보조/결과 출력을 담당하는 역할이었다.

Coq 01 - Introduction

·6 분
<Interactive Theorem Proving and Program Development>라는 책을 추천받아 조금씩 읽어보기로 했다. 첫 장에서는 Coq에 대한 간단한 안내를 진행한다. 책의 순서를 따라가면서 하나씩 알아보자 타입 먼저 Coq에서는 Gallina라는 언어를 사용해 요구사항(Specification)을 서술한다. 대부분의 다른 프로그래밍 언어들과 마찬가지로 타입은 declaration과 typing rule에 의해 정해진다.