타입 시스템이란 무엇입니까?


50

배경

사이드 프로젝트로 언어를 디자인하고 있습니다. 작동하는 어셈블러, 정적 분석기 및 가상 머신이 있습니다. 내가 만든 인프라를 사용하여 사소한 프로그램을 이미 컴파일하고 실행할 수 있기 때문에 대학에서 프레젠테이션을하는 것에 대해 생각했습니다.

내 이야기에서 나는 VM이 ​​타입 시스템을 제공한다고 언급했다. " 당신의 타입 시스템은 무엇입니까? " 대답 한 후 나는 그 질문을하는 사람에게 비웃었다.

따라서이 질문을함으로써 명성을 잃게 되더라도 프로그래머에게 의지합니다.

내 이해

내가 이해하는 것처럼 유형 시스템은 프로그램의 엔터티에 대한 추가 정보 계층을 제공하는 데 사용되므로 런타임 또는 컴파일러 또는 기타 기계 장치가 작동하는 비트 문자열로 수행 할 작업을 알 수 있습니다. 또한 계약을 유지하는 데 도움이됩니다. 컴파일러 (또는 코드 분석기, 런타임 또는 기타 프로그램)는 특정 시점에서 프로그램이 작동 할 것으로 예상되는 값으로 프로그램이 작동하는지 확인할 수 있습니다.

타입은 또한 인간 프로그래머에게 정보를 제공하는데 사용될 수 있습니다. 예를 들어 다음과 같은 선언을 찾습니다.

function sqrt(double n) -> double;

이 것보다 더 유용

sqrt(n)

전자는 많은 정보를 제공합니다. sqrt식별자는 함수이고 단일 double을 입력으로 사용하고 다른 double것을 출력으로 생성 합니다. 후자는 아마도 단일 매개 변수를 취하는 함수 일 것입니다.

내 대답

따라서 "유형 시스템은 무엇입니까?"라는 질문을받은 후 나는 다음과 같이 대답했다 :

타입 시스템은 동적이며 (타입은 값을 보유한 변수가 아닌 값에 할당 됨) 놀라운 강제 규칙없이 강력합니다 (호환되지 않는 타입을 나타내므로 문자열을 정수에 추가 할 수는 없지만 부동 소수점 숫자에는 정수를 추가 할 수 있음) .

유형 시스템은 VM에서 명령어의 피연산자가 유효한지 확인하는 데 사용됩니다. 프로그래머는 함수에 전달 된 매개 변수가 올바른지 (즉 올바른 유형인지) 확인하기 위해 프로그래머가 사용할 수 있습니다.
타입 시스템은 서브 타이핑과 다중 상속 (프로그래머가 기능을 모두 사용할 수 있음)을 지원하며, 객체에서 메소드의 동적 디스패치가 사용될 때 유형이 고려됩니다. VM은 유형을 사용하여 주어진 유형에 대해 주어진 메시지가 어떤 기능을 구현하는지 확인합니다.

후속 질문은 "그리고 어떻게 유형이 값에 할당됩니까?"였습니다. 그래서 나는 모든 값들이 박스로 묶여 있고 타입의 이름, 응답하는 메시지, 그리고 상속되는 타입에 대한 정보를 제공하는 타입 정의 구조를 가리키는 포인터를 가지고 있다고 설명했다.

그 후, 나는 웃었고, "그건 진짜 형식 체계가 아닙니다"라는 주석으로 대답이 사라졌습니다.

따라서 내가 설명한 내용이 "실제 유형 시스템"으로 적합하지 않은 경우 어떻게해야합니까? 내가 제공 한 것을 유형 시스템으로 간주 할 수 없다는 것이 맞습니까?


19
사람들이 유형 시스템에 대해 이야기 할 때 보통 정적 유형에 대해 이야기합니다. 동적 타이핑은 거의 아무것도 보장하지 않기 때문에 타입 시스템에 관심이있는 사람들에게는 그다지 흥미롭지 않습니다. 예를 들어 변수 x는 어떤 종류의 가치를 가질 수 있습니까? 아무것도.
Doval

7
나는 그들의 반응을 방어 / 설명하기 위해 그들이해야 할 말을 듣고 궁금하다.
Newtopian

18
@Doval Dynamic 타이핑은 고양이에게 5를 더하는 것과 같은 일을함으로써 무의미한 상태에 빠지지 않도록 보장 할 수 있습니다. 물론, 그것은 당신이 시도하는 것을 방해 하지는 않지만 적어도 실제로 일어나지 않도록 막을 수 있으며 실제로 무엇이 잘못되었는지 파악하고 진정으로 유형이없는 언어로는 할 수없는 일을 교정 할 수있는 기회를 줄 수 있습니다.
8bittree

10
그 사람은 "그리고 어떻게 유형이 값에 할당됩니까?" 그들은 상자 및 포인터 다이어그램이 아니라 입력 규칙에 대해 듣고 싶었습니다. 그러나 웃음은 절대 무례했습니다.
gardenhead

10
웃기는 사람은 강력한 유형 체계를 가진 특정 언어 (가족)의 열성 일 가능성이 높으며 (Haskell은 인기가있는 것으로 보임), 그보다 덜 강하고 (따라서 장난감), 더 강하고 (실용적이지 않은) 것을 조롱 할 것입니다. 아니면 그냥 다릅니다. 열광 자와의 대화에 참여하는 것은 위험하고 무의미합니다. 그런 웃음은 너무 무례해서 이런 종류의 더 깊은 문제를 나타냅니다. 당신은 그들이 설교를 시작하지 않았기 때문에 운이 좋은 ...
hyde

답변:


30

그것은 모두 유형 시스템이 제공하는 것에 대한 훌륭한 설명처럼 보입니다. 그리고 귀하의 구현은 수행중인 일에 대해 합리적인 것으로 들립니다.

일부 언어의 경우 언어가 런타임 디스패치를 ​​수행하지 않기 때문에 런타임 정보가 필요하지 않습니다 (또는 vtable 또는 다른 메커니즘을 통해 단일 디스패치를 ​​수행하므로 유형 정보가 필요하지 않습니다). 일부 언어의 경우 이름이나 상속이 아닌 유형 평등에만 관심이 있기 때문에 기호 / 자리 표시 자만 있으면 충분합니다.

사용자 환경에 따라 해당 유형 시스템에서 더 많은 형식을 원했을 수도 있습니다. 프로그래머가 할 있는 것이 아니라 증명할 수있는 것을 알고 싶어 합니다. 불행히도 이것은 학계에서 매우 일반적입니다. 학계가 그런 일을한다고하더라도 유형 시스템에 결함이있어 정확성을 피할 수 있기 때문입니다. 그들이이 중 하나를 발견했을 가능성이 있습니다.

추가 질문이있는 경우 유형 및 프로그래밍 언어 는이 주제에 관한 정식 책이며 사물을 설명하는 데 도움이되는 일부 용어뿐만 아니라 학자가 필요로하는 엄격한 일부를 배우는 데 도움이 될 수 있습니다.


3
"귀하의 환경에 따라 해당 유형 시스템에서 더 많은 형식주의를 원했을 수 있습니다." 아마 그거야. 나는 타입 시스템으로 증명할 수있는 것에 집중하지 않고 도구로 생각했다. 책 추천에 감사드립니다!
Mael

1
@Mael 일부 유형 시스템은 논리로 사용됩니다 ( 논리 프레임 워크 참조 ). 그래서 기본적으로 유형이 공식을 제공하고 프로그램이 그 공식의 증거이다 (예를 들어, 함수 유형 a -> b으로 볼 수있다 a가 b 의미 당신은 나에게 형의 값을 주면, 즉 a내가 유형의 값을 얻을 수 있습니다 b). 그러나 이것이 일관성을 유지하려면 언어가 총체적이어야하며 따라서 튜링이 완전하지 않아야합니다. 따라서 모든 실제 유형 시스템은 실제로 일관성이없는 논리를 정의합니다.
Bakuriu

20

나는 공식주의에 대한 학문적 관심에 대한 언급 때문에 @Telastyn의 답변을 특히 좋아합니다.

토론에 추가하겠습니다.

타입 시스템이란 무엇입니까?

유형 시스템은 불법 프로그램 상태를 정의, 감지 및 방지하기위한 메커니즘입니다. 제약 조건을 정의하고 적용하여 작동합니다. 제약 조건 정의는 유형 이며, 제약 조건 애플리케이션은 예를 들어 변수 선언에서 유형의 사용법입니다 .

유형 정의는 일반적으로 작성 연산자 (예 : 구조, 서브 클래 싱 및 분리, 열거 형, 공용체와 같은 다양한 형태의 연결)를 지원합니다.

제약 조건, 유형의 사용법은 때로는 컴포지션 연산자 (예 : 적어도 이것, 정확히 이것, 이것 또는 다른 것)를 허용합니다.

유형 시스템이 언어로 제공되고 컴파일 타임 오류를 발행 할 수 있도록 컴파일 타임에 적용되는 경우 정적 유형 시스템입니다. 이렇게하면 많은 불법 프로그램이 실행되는 것만으로 컴파일되는 것을 방지 할 수 있으므로 불법 프로그램 상태가 방지됩니다.

(정적 유형 시스템은 프로그램이 문제가되는 소리가 들리지 않는 코드에 도달 할 것이라는 사실을 알 수 있는지 (또는 결정 불가능한지) 여부에 관계없이 프로그램 실행을 중지합니다. 프로그램이 실행되기 전에 오류가 있다고 판단합니다.)

유형 시스템이 런타임에 적용되는 경우, 이는 잘못된 프로그램 상태를 방지하는 동적 유형 시스템입니다. 그러나 프로그램이 처음에 실행되지 않도록하는 대신 중간 실행에서 프로그램을 중지합니다.

상당히 일반적인 유형 시스템 오퍼링은 정적 및 동적 기능을 모두 제공하는 것입니다.


나는 이른바 하이브리드 타입 시스템이 전혀 일반적이라고 생각하지 않습니다. 어떤 언어를 염두에두고 있습니까?
gardenhead

2
@gardenhead, 다운 캐스트 기능은 정적 유형 시스템 기능이 아니므로 일반적으로 런타임시 동적으로 검사됩니다.
Erik Eidt

1
@gardenhead : 대부분의 정적으로 유형이 지정된 언어를 사용하면 C의 void *포인터 (매우 약한), C #의 동적 객체 또는 Haskell의 기존 수량 GADT (간단히 다른 유형의 정적 유형 값보다 훨씬 강력한 보장을 제공함) 를 사용하여 런타임에 입력을 연기 할 수 있습니다 언어).
leftaroundabout

사실, 나는 "캐스팅"을 잊었다. 그러나 캐스팅은 약한 유형 시스템의 목발 일뿐입니다.
gardenhead

@gardenhead 동적 옵션을 제공하는 정적 언어뿐만 아니라 많은 동적 언어는 정적 입력을 제공합니다. 예를 들어 Dart, Python 및 Hack에는 모두 "점진적 타이핑"개념을 기반으로 정적 분석을 수행하기위한 모드 또는 도구가 있습니다.
IMSoP

14

오,이 질문에 최선을 다해 답변을 드리겠습니다. 나는 내 생각을 순서대로 알 수 있기를 바랍니다.

@Doval이 언급하고 질문자가 지적했듯이 (무례한 것은 아니지만) 실제로 유형 시스템이 없습니다. 태그를 사용하는 동적 검사 시스템이 있습니다. 일반적으로 훨씬 약하고 흥미도 덜합니다.

"유형 시스템이란 무엇인가"라는 질문은 매우 철학적 일 수 있으며, 그 문제에 대해 다른 견해로 책을 채울 수 있습니다. 그러나 이것은 프로그래머를위한 사이트이므로 가능한 한 실용적으로 답변하려고 노력할 것입니다 (실제로 유형은 프로그래밍에 매우 실용적입니다.

개요

보다 공식적인 토대에 뛰어 들기 전에 바지 자리부터 시작하여 유형 시스템의 장점을 이해하십시오. 타입 시스템은 프로그램에 구조를 부과합니다 . 그들은 우리가 어떻게 다양한 기능과 표현을 함께 연결할 수 있는지 알려줍니다. 구조가 없다면, 프로그램은 불가능하고 매우 복잡하여 프로그래머의 작은 실수로 피해를 입을 수 있습니다.

타입 시스템으로 프로그램을 작성하는 것은 브레이크가 작동하고 문이 안전하게 닫히고 엔진이 기름칠되는 등 박하 상태에서 돌보는 것과 같습니다. 타입 시스템이없는 프로그램을 작성하는 것은 헬멧이없고 바퀴가 달린 모터 사이클을 타는 것과 같습니다 스파게티에서. 당신은 당신을 절대적으로 통제 할 수 없습니다.

토론을 접지하기 위해, 우리는 문자 식으로 언어가 있다고 가정하자 num[n]str[s]그 숫자 n 및 문자열의 각각과 기본 기능을 나타냅니다 plusconcat의도 된 의미를. 분명히, 당신은 plus "hello" "world"또는 같은 것을 쓸 수 있기를 원하지 않습니다 concat 2 4. 그러나 어떻게 이것을 막을 수 있습니까? 선험적으로는 , 문자열 리터럴 "세계"에서 숫자 2를 구별 할 방법이 없습니다. 우리가 말하고 싶은 것은이 표현들이 다른 상황에서 사용되어야한다는 것입니다. 그들은 다른 유형이 있습니다.

언어와 유형

조금 뒤로 물러서 보자 : 프로그래밍 언어 란 무엇인가? 일반적으로 우리는 프로그래밍 언어를 구문과 의미론의 두 계층으로 나눌 수 있습니다. 이것을 각각 staticsdynamics 라고도합니다 . 이 두 부분 사이의 상호 작용을 중재하기 위해 유형 시스템이 필요하다는 것이 밝혀졌습니다.

통사론

프로그램은 나무입니다. 컴퓨터에 쓰는 텍스트 줄에 속지 마십시오. 이들은 사람이 읽을 수 있는 프로그램의 표현 일뿐 입니다. 프로그램 자체는 추상 구문 트리 입니다. 예를 들어 C에서는 다음과 같이 작성할 수 있습니다.

int square(int x) { 
    return x * x;
 }

이것이 프로그램 의 구체적인 구문입니다 (조각). 트리 표현은 다음과 같습니다.

     function square
     /     |       \
   int   int x    return
                     |
                   times
                  /    \
                 x      x

프로그래밍 언어는 제공 문법 해당 언어의 유효한 나무 정의 (콘크리트 또는 추상 구문 중 하나를 사용할 수있다)를. 이것은 일반적으로 BNF 표기법과 같은 것을 사용하여 수행됩니다. 나는 당신이 만든 언어에 대해 이것을했다고 가정합니다.

의미론

좋아, 우리는 프로그램이 무엇인지 안다. 그러나 그것은 단지 정적 트리 구조 일 뿐이다. 아마도 우리는 프로그램이 실제로 무언가를 계산하기를 원합니다. 의미론이 필요합니다.

프로그래밍 언어의 의미론은 풍부한 연구 분야입니다. 대체로 두 가지 접근 방식이 있습니다 : dendomtional semanticsoperating semantics . 명칭 의미론은 프로그램을 기본 수학 구조 (예 : 자연수, 연속 함수 등)에 매핑하여 프로그램을 설명합니다. 그것은 우리 프로그램에 의미를 제공합니다. 반대로 작동 의미론은 프로그램 실행 방법을 자세히 설명하여 프로그램을 정의합니다. 내 생각에, 운영 의미론은 프로그래머 (나 자신을 포함하여)에게 더 직관적이므로 그렇게 생각해 봅시다.

공식적인 운영 의미론을 정의하는 방법은 다루지 않지만 (세부 사항은 약간 관련되어 있음) 기본적으로 다음과 같은 규칙을 원합니다.

  1. num[n] 가치이다
  2. str[s] 가치이다
  3. 경우 num[n1]와은 num[n2]정수로 평가 n_1$ and $n_2$, then플러스 (NUM [N1], NUM [N2])`정수 $로 평가는 n_1 + n_2를 $.
  4. 경우 str[s1]와는 str[s2]문자열 S1과 S2로 평가 한 후 concat(str[s1], str[s2])문자열 s1s2로 평가합니다.

등 규칙은 실제로 훨씬 공식적이지만 요점을 얻습니다. 그러나 곧 문제가 발생합니다. 다음을 쓸 때 어떤 일이 발생합니까?

concat(num[5], str[hello])

흠. 이것은 수수께끼입니다. 우리는 숫자를 문자열로 연결하는 방법에 대한 규칙을 정의하지 않았습니다. 이러한 규칙을 만들려고 시도 할 수 있지만이 작업이 의미가 없음을 직관적으로 알고 있습니다. 이 프로그램이 유효하지 않기를 바랍니다. 따라서 우리는 유형에 필연적으로 인도됩니다.

종류

프로그램은 언어 문법에 의해 정의 된 트리입니다. 프로그램은 실행 규칙에 의해 의미가 부여됩니다. 그러나 일부 프로그램은 실행할 수 없습니다. 즉, 일부 프로그램은 의미가 없습니다 . 이러한 프로그램은 잘못된 유형입니다. 따라서 입력은 언어로 의미있는 프로그램을 특징 짓습니다. 프로그램의 형식이 잘 잡히면 실행할 수 있습니다.

몇 가지 예를 들어 봅시다. 평가 규칙과 마찬가지로 입력 규칙을 비공식적으로 제시하지만 엄격하게 만들 수 있습니다. 다음은 몇 가지 규칙입니다.

  1. 형식의 토큰 num[n]은 유형이 nat있습니다.
  2. 형식의 토큰 str[s]은 유형이 str있습니다.
  3. 표현하면 e1유형이 nat표현은 e2유형이 nat다음 식을 plus(e1, e2)입력했다 nat.
  4. 표현하면 e1유형이 str표현은 e2유형이 str다음 식을 concat(e1, e2)입력했다 str.

따라서 이러한 규칙에 따라 plus(num[5], num[2])유형 nat이 있지만에 유형을 할당 할 수 없습니다 plus(num[5], str["hello"]). 우리는 프로그램 (또는 표현식)이 어떤 유형을 할당 할 수 있다면 잘 타이핑되고 그렇지 않으면 잘못 타이핑된다고 말합니다. 형식이 잘 잡힌 프로그램을 모두 실행할 수 있으면 형식 시스템은 소리납니다 . 하스켈은 소리입니다. C는 아닙니다.

결론

유형에 대한 다른 견해가 있습니다. 어떤 의미에서 유형은 직관 논리에 해당하며 범주 이론에서 객체로 볼 수도 있습니다. 이러한 연결을 이해하는 것은 매혹적이지만 프로그래밍 언어를 작성하거나 디자인하려는 경우에만 필수적인 것은 아닙니다. 그러나 프로그램의 형성을 제어하기위한 도구로 유형을 이해하는 것입니다 프로그래밍 언어 설계 및 개발에 필수적인. 나는 표현할 수있는 유형의 표면 만 긁었다. 나는 그들이 당신의 언어에 통합 할만큼 가치가 있다고 생각하기를 바랍니다.


4
+1. 역동적 인 타이핑 애호가가 뽑은 가장 큰 트릭은 타입 시스템없이 "타입"을 가질 수있는 세계를 설득하는 것입니다. :-)
ruakh

1
이후 자동 흥미로운 아무것도 확인할 수없는 임의의 프로그램을, 모든 유형의 시스템은 캐스트 연산자 (또는 도덕적 상당)을 제공해야합니다, 그렇지 않으면 그것은 튜링 완전성을 희생한다. 여기 에는 물론 Haskell포함됩니다 .
Kevin

1
@ 케빈 나는 쌀의 정리를 잘 알고 있지만 당신이 생각하는 것만 큼 관련이 없습니다. 우선, 대부분의 프로그램에는 무한 재귀가 필요하지 않습니다. Godel의 시스템 T와 같이 원시 재귀 만있는 언어로 작업하는 경우 정지를 포함하여 유형 시스템을 사용하여 흥미로운 속성을 확인할 수 있습니다. 실제 세계의 대부분의 프로그램은 다소 단순합니다. 실제로 실제로 캐스팅이 필요한 시점은 생각할 수 없습니다. 튜링 완성도가 과대 평가되었습니다.
gardenhead

9
“동적 타이핑은 실제로 타이핑이 아닙니다”는“팝 음악은 실제로는 음악이 아닙니다”라고 말하는 클래식 뮤지션이나“가톨릭은 실제로 기독교인이 아닙니다”라고 말하는 복음 주의자들처럼 항상 보였습니다. 예, 정적 유형 시스템은 강력하고 매력적이며 중요하며 동적 유형은 다릅니다. 그러나 (다른 답변에서 설명 하듯이) 전통적으로 타이핑이라고하는 정적 유형 시스템 외에도 중요한 공통점을 공유하는 유용한 유형이 있습니다. 왜 우리의 타이핑 유형을 진정한 타이핑이라고 주장해야합니까?
Peter LeFanu Lumsdaine

5
@IMSoP : 책보다 짧은 무언가를 위해 Chris Smith의 에세이 타입 시스템에 대해 토론하기 전에 알아야 할 것은 동적 타이핑이 정적 타이핑과 정말 다른 이유를 설명합니다.
Peter LeFanu Lumsdaine
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.