“증거는 프로그램입니다. 그것이 증명하는 공식은 프로그램의 유형입니다”


37

이것은 철학적 인 종류의 질문 일지 모르지만 이에 대한 객관적인 답변이 있다고 생각합니다.

Haskell에 대한 Wikipedia 기사를 읽으면 다음을 찾을 수 있습니다.

이 언어는 Haskell Curry와 그의 지적 후손들의 관찰에 근거하고있다. "증명은 프로그램이다. 증명하는 공식은 프로그램의 유형이다"

자, 내가 묻는 것은 이것이 거의 모든 프로그래밍 언어에 적용되지 않습니까? Haskell의 어떤 기능 (또는 기능 세트)이이 진술을 준수하게합니까? 다시 말해,이 진술이 언어의 디자인에 영향을 미치는 눈에 띄는 방법은 무엇입니까?


4
왜 "가까운"투표가 필요한지 설명해 주시겠습니까?

1
@Grigory Javadyan : 마감에 투표하지는 않았지만 아마도 문제는 SO에 대한 경계선을 벗어난 주제이기 때문일 것입니다. 이 경우에는 답변이 Haskell이 실제로 어떻게 사용되는지에 대한 실질적인 영향을 미치기 때문에 정당하다고 생각합니다.

2
@Grigory :이 질문이 실제 솔루션 (코드)에 실제로 문제가 있다면 SO에 머물 수 있습니다. 프로그래머를 닫고 이사하기로 결정했습니다.

9
이 질문에 대한 답은 어려운 CS 연구에 대한 언급과 그 의미에서 SO의 90 %보다 "객관적"입니다. 더욱이, 6 자 변수의 기준 (솔루션에 코드가 필요함)은 주관적이거나 주제를 벗어난 광범위한 진정한 프로그래밍 질문에 대해 엄청나게 좁습니다. 나는 포용
주의자

2
나는 일종의 컨텐츠의 무엇에 정말 불분명 해요 주로하기 때문에, 여기서이 끝 약 용납 해요 되어 SO 대 Programmers.SE에있을 수 있습니다. 하지만 프로그래머는이 질문은 단호하다 "주관적인 질문"을위한 것으로 여러 곳에서 설명 말할 것 없습니다 . 내 대답은 가능한 한 비공식적이고 손으로 쓰는 것입니다. 심지어 Wikipedia 편집자들도 받아 들일 수있는 참고 자료로 여전히 쉽게 백업 할 수 있습니다.
CA McCann 2016 년

답변:


38

필수 개념은 보편적으로 어떤 방식 으로든 적용되지만 거의 유용한 방식은 아닙니다.

우선, 유형 이론 관점에서 "동적"언어는 단일 유형 을 갖는 것으로 가장 잘 간주 되는데, 여기에는 동적 인 언어가 호출하는 것을 포함하여 프로그래머가 보는 가치의 본질에 대한 메타 데이터가 포함됩니다. "유형"자체 (개념적으로 같은 것은 아님) 이러한 증거는 흥미롭지 않을 수 있으므로이 개념은 주로 정적 유형 시스템을 사용하는 언어와 관련이 있습니다.

또한 "정적 유형 시스템"이있는 것으로 추정되는 많은 언어는 런타임시 유형을 검사하고 변환 할 수 있기 때문에 실제로는 동적으로 간주해야합니다. 특히, 이것은 기본적으로 "반사"등을 기본적으로 지원하는 모든 언어를 의미합니다. 예를 들어 C #.

Haskell은 유형이 제공 할 정보의 양이 많지 않습니다. 특히 함수는 인수로 지정된 값 이외의 값에 의존 할 수 없습니다. 반면에 가변 글로벌 변수가있는 언어에서는 모든 함수가 (잠재적으로) 해당 값을 검사하고 그에 따라 동작을 변경할 수 있습니다. 따라서 유형이있는 Haskell 함수는 다음 A -> BA의미 하는 소형 프로그램으로 간주 될 수 있습니다 B. 다른 많은 언어들에서 동등한 기능은 우리에게 말할 것이며 그 A범위 안에있는 모든 국가는 암시 B합니다.

Haskell은 리플렉션 및 동적 유형 과 같은 기능을 지원하지만 이러한 기능의 사용 은 함수의 유형 서명에 표시되어야합니다. 글로벌 상태의 사용에 대해서도 마찬가지입니다. 기본적으로 어느 것도 사용할 수 없습니다.

있습니다 런타임 예외를 허용하거나, 컴파일러가 제공하는 표준이 아닌 기본 작업을 사용하여 하스켈에서뿐만 아니라, 예를 들어 물건을 파괴하는 방법이 있지만, 사람들은 '그들 만 원이 방법으로 완전한 이해와 함께 사용됩니다 강한 기대와 함께 외부 코드의 의미를 손상시킵니다. 이론적으로 다른 언어들도 마찬가지 일 수 있지만, 대부분의 다른 언어들에서는 실제로 "속임수"없이 일을 달성하기가 더 어렵고 "치트"에 덜 어리둥절하지 않습니다. 물론 진정한 "동적"언어에서는 모든 것이 관련이 없습니다.

이 개념은 Haskell보다 훨씬 더 발전 될 수 있습니다.


예외는 형식 시스템에 완전히 통합 될 수 있습니다.
gardenhead

18

Curry-Howard 서신은 매우 일반적인 것입니다. http://en.wikipedia.org/wiki/Curry-Howard_correspondence : 역사에 대해 약간의 지식이 필요합니다 .

처음에 공식화 된 것처럼,이 대응 관계는 한쪽의 직관 논리와 다른 쪽의 단순 람다 미적분학 (STLC)에 특히 적용되었습니다.

클래식 하스켈 (98 년 또는 그 이전 버전)은 STLC와 매우 밀접한 관계가 있었으며, 대부분 하스켈의 주어진 표현과 STLC의 해당 용어 사이에 매우 간단하고 직접적인 번역이있었습니다 (재귀와 몇 가지 기본 유형). 그래서 이것은 Curry-Howard를 매우 명백하게 만들었습니다. 오늘날 확장 기능 덕분에 이러한 번역은 다소 까다로운 작업입니다.

어떤 의미에서, Haskell이 STLC에 그렇게 간단하게“탈당”하는 이유가 문제입니다. 두 가지가 생각납니다.

  • 유형. 설탕이 달린 람다 미적분학 인 Scheme과는 달리 Haskell은 강력하게 유형이 지정됩니다. 이는 고전적인 Haskell 에는 STLC에서 잘 정의 된 용어를 정의 할 수없는 용어가 존재하지 않음을 의미합니다 .
  • 청정. 마찬가지로 Scheme과는 달리 STLC와 마찬가지로 Haskell은 순수하고 참조가 투명한 언어입니다. 이것은 매우 중요합니다. 부작용이없는 언어는 부작용이없는 언어에 포함시킬 수 있습니다. 그러나 그렇게하는 것은 단순히 지역적 설탕 제거가 아닌 전체 프로그램 변환입니다. 따라서 직접 통신하려면 순전히 기능적인 언어로 시작해야합니다.

대부분의 언어와 마찬가지로 Haskell이 Curry-Howard 서신의 직접적인 적용과 관련하여 실패하는 중요한 방법도 있습니다. 튜링 완료 언어 인 Haskell은 무제한 재귀 가능성과 종료되지 않을 가능성을 포함합니다. STLC에는 픽스 포인트 연산자가없고 튜링이 완료되지 않았으며 강력하게 정규화 되고 있습니다. 즉, STLC에서 용어의 감소가 종료되지 않습니다. 재귀 가능성은 Curry-Howard를 속일 수 있음을 의미합니다. 예를 들어 let x = x in x유형이forall a. a즉, 그것은 결코 돌아 오지 않기 때문에 나에게 아무것도주는 척 할 수 있습니다! 우리는 항상 Haskell에서이 작업을 수행 할 수 있기 때문에 프로그램 자체가 종료된다는 별도의 증거가없는 한 Haskell 프로그램에 해당하는 모든 증거를 완전히 "믿을 수"없습니다.

Haskell (특히 ML 제품군) 이전의 기능적 프로그래밍의 계보는 언어를 구축하는 데 중점을 둔 CS 연구의 결과로, 무엇보다도 (중요한 것)에 대해 쉽게 증명할 수 있고 CH에 대해 잘 알고 연구 할 수 있습니다. 반대로, Haskell은 CH의 계보와 매우 관련이있는 형식 이론의 개발에 뿌리를 둔 Agda 및 Epigram과 같은 개발중인 많은 증거 보조자에게 호스트 언어 및 영감을 제공했습니다.


1
논 터미네이션은 논리적 인 관점에서 명백히 치명적이지만 많은 다른 속성을 보존하는 특정 방식으로 증거를 손상 시킨다는 점을 강조하는 것이 좋습니다. 특히,가 A -> B주어진 함수 AB전혀 생성 하지 않거나 전혀 생성 하지 않습니다. 결코을 생성하지 않으며 제공 C하는 유형의 값 B또는 분기하는 경우 여전히 A제공된 값 에 전적으로 의존합니다 .

@camccann-약간의 nitpicky이지만 바닥과 "아무것도"를 구별 Void하지 않습니까? 게으름은 점점 더 복잡해집니다. 함수는 A -> B 항상 type의 값을 생성 B하지만 해당 값은 예상보다 적은 정보를 가질 수 있다고 말하고 싶습니다 .
sclv

Nitpicking은 재미 있습니다! 내가 "아무것도"라고 말할 때, 나는 평가를 수행하는 맥락에서 가치 수준을 의미하는 반면, 하한은 실질적인 것이 아니라 추상화로만 존재합니다. 평가되는 표현식은 결코 bottom 값을 "보지"않으며, 사용하지 않는 (아래에있을 수있는) 용어와 사용하는 용어 (하단이 아닌 값) 만 볼 수 있습니다. 바닥 "사용하지 않음"을 사용하려고하면 사용하기 전에 전체 표현식의 평가가 종료되므로 어떤 의미로도 사용하지 마십시오.

12

1 차 근사치로, 대부분의 다른 (약한 및 / 또는 단일 유형) 언어는 언어 수준 사이의 엄격한 언어 수준 묘사를 지원하지 않습니다.

  • 제안 (예 : 유형)
  • 증거 (즉, 우리가 원시 및 / 또는 기타의 세트에서 제안을 만들 수있는 방법을 프로그램 시연 고차 구조)

그리고 둘 사이의 엄격한 관계. 다른 언어가 제공하는 가장 좋은 보장은

  • 입력 환경에 제한적인 제약이 주어 졌을 때, 당시 환경에 발생하는 모든 것들과 함께, 제한된 제약 조건으로 가치를 창출 할 수 있습니다. (전통적인 정적 유형, cf C / Java)
  • 모든 구문은 동일한 유형입니다 (동적 유형, cf ruby ​​/ python)

참고하여 해당 유형 , 우리는 참조 제안 따라서 다음 단지 훨씬 더 많은 정보를 기술하는 일, 그리고 int 형 또는 부울을 . Haskell 에는 함수 의 침투 문화가 인수의 영향을 받음 - 예외는 없음 *.

좀 더 엄밀하게 말하면, 일반적인 아이디어는 모든 프로그램 구조에 대해 (직접적으로) 강건한 직관적 접근 방식을 시행함으로써 (즉, 우리가 구성 할 수있는 것만 증명할 수 있음) 그러한 기본 구조 세트를 제한한다는 것입니다. 우리가 가진 방식

  • 모든 언어 기본 요소에 대한 엄격한 명제
  • 프리미티브를 결합 할 수있는 제한된 메커니즘

하스켈 건축은 그들의 행동에 대한 추론에 매우 적합합니다. 을 A암시 하는 증명 (읽기 : 함수)을 구성 할 수 있다면 다음 B과 같은 매우 유용한 속성이 있습니다.

  • 그것은 항상 (긴 우리가이만큼 보유 A, 우리가를 구성 할 수 있습니다 B)
  • 이 의미는 의지 A, 그리고 아무것도 다른.

따라서 지역 / 글로벌 불변량에 대해 효과적으로 추론 할 수 있습니다. 원래 질문으로 돌아가려면; 이 사고 방식을 가장 잘 활용하는 Haskell의 언어 기능은 다음과 같습니다.

  • 명시 적 구성으로 효과의 순도 / 분할 (효과는 모두 설명되고 입력됩니다!)
  • Haskell 컴파일러의 타입 추론 / 확인
  • 프로그램이 입증하기 위해 제안 / 유형에 제어 및 / 또는 데이터 흐름 불변을 포함시키는 기능 : (다형성, 유형 가족, GADT 등)
  • 참조 무결성

하스켈 만의 독특한 것은 없습니다 (이러한 아이디어 중 상당수는 엄청나게 오래되었습니다). 그러나 표준 라이브러리 (일반적으로 유형 클래스에서 발견됨)의 다양한 추상화 세트, 다양한 구문 레벨 당화 및 프로그램 설계의 순도 에 대한 엄격한 헌신 과 결합되면 결국 우리는 둘 다가 될 수있는 언어로 끝납니다 실제 응용 프로그램 에는 충분히 실용적 이지만 동시에 대부분의 전통적인 언어에 대해 추론하기가 더 쉽습니다.

이 질문은 충분히 깊은 답을 얻을 수 있으며,이 맥락에서 정의를 할 수 없었습니다. 위키 백과 / 문헌에 대한 자세한 내용을 읽어 보길 권한다.

* NB : 나는 논쟁을 복잡하게 만드는 Haskell의 불순물 (예외, 비 종료 등)의 까다로운 측면을 무시하고 무시하고 있습니다.


4

어떤 기능? 유형 시스템 (정적, 순수, 다형성). 좋은 출발점은 Wadler의 "무료 정리"입니다. 언어 디자인에 눈에 띄는 영향? IO 유형, 유형 클래스.


0

Kleene 계층 구조는 증거는 프로그램이 아니라는 것을 우리에게 보여줍니다.

첫 번째 재귀 관계는 다음 중 하나입니다.

R1( Program , Iteration )  Program halts at Iteration.
R2( Theorem , Proof ) Proof proves a Theorem.

재귀 적으로 열거 가능한 첫 번째 관계는 다음과 같습니다.

(exists x) R1( Program , x )  Program Halts.
(exists x) R2( Theorem , x)   Theorem is provable.

따라서 프로그램은 정리이고 프로그램이 정지되는 반복은 정리를 증명하는 존재와 같습니다.

Program = Theorem
Iteration = Proof

프로그램이 규격에서 올바르게 생산 될 때, 우리는 그것이 규격을 만족한다는 것을 증명할 수 있어야하고, 우리가 프로그램이 규격을 만족한다는 것을 증명할 수 있다면 그것은 올바른 프로그램 합성입니다. 따라서 프로그램이 사양을 충족한다는 것을 증명할 경우 프로그램 합성을 수행합니다. 프로그램이 규격을 만족시키는 정리는 정리가 합성 된 프로그램을 참조한다는 점에서 프로그램이다.

Martin Lof의 잘못된 결론은 컴퓨터 프로그램을 만들어 본 적이 없으며 사람들이 프로그램 합성 방법론이라고 믿는 것은 놀라운 일입니다. 합성되는 프로그램에 대한 완전한 예는 없다. "유형 입력 및 해당 유형의 프로그램 출력"과 같은 사양은 기능이 아닙니다. 이러한 프로그램이 여러 개 있으며 하나를 임의로 선택하는 것은 재귀 함수 또는 함수가 아닙니다. 재귀 함수를 계산하는 실제 컴퓨터 프로그램을 나타내지 않는 바보 같은 프로그램으로 프로그램 합성을 보여주기위한 바보 같은 시도 일뿐입니다.


2
"이 문장이 언어의 디자인에 영향을 미치는 눈에 띄는 방법은 무엇입니까?"
gnat

1
@gnat-이 답변은 원래 질문 내에서 근본적인 가정을 다룹니다. " doesn't this really apply to pretty much all the programming languages?"이 답변은 가정이 유효하지 않다고 주장 / 보여주기 때문에 결함이있는 전제에 기초한 나머지 질문을 다루는 것은 합리적이지 않습니다. .
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.