리스프와 구성표의 유형


10

라켓에는 유형이 있습니다. 언뜻보기에 Haskell 타이핑과 거의 같은 것으로 보입니다. 그러나 Lisp의 CLOS는 Haskell 유형의 공간 중 일부를 다루고 있습니까? 매우 엄격한 Haskell 유형과 모든 OO 언어로 된 객체를 만드는 것은 모호하게 유사 해 보입니다. 그것은 단지 Haskell kool-aid의 일부를 마 셨기 때문에 Lisp 도로를 따라 가면 역동적 인 타이핑으로 인해 망할 것이라는 완전히 편집증입니다.

답변:


6

CL 유형 시스템은 Haskell 시스템보다 표현력 이 뛰어납니다. 예를 들어, (or (integer 1 10) (integer 20 30))값에 대한 유형 을 가질 수 있습니다 1,2,...9,10,20,21,...,30.

당신이 그들의 "노트"를 무시할 수 있도록 그러나 리스프 컴파일러는, 당신의 목구멍 형 안전에 대한 이해를 강요하지 않는다 - 당신의 자신의 위험에 .

즉, 모든 값 유형을 선언하고 필요한 모든 유형이 유추되었는지 확인하여 Haskell을 Lisp로 작성할 수 있습니다 (그러나 말할 필요도 있음). 우선 Haskell을 사용하는 것이 더 쉽습니다.

기본적으로 강력한 정적 타이핑을 원하면 Haskell 또는 OCaml을 사용하고 강력한 동적 타이핑을 원하면 Lisp를 사용하십시오. 약한 정적 입력을 원하면 C를 사용하고 약한 동적 입력을 원하면 Perl / Python을 사용하십시오. 각 경로에는 장단점과 단점이 있으므로 모든 것을 배우면 도움이됩니다.


19
"목구멍 아래의 힘 유형 안전"과 같은 용어를 사용하는 사람은 유형 안전성이 무엇인지 또는 왜 유용한 지 이해하지 못합니다.
메이슨 휠러

11
@MasonWheeler : 하나의 문구로 결론을 내리는 사람은 다른 것보다 더 자주 자신을 잘못 발견 할 것입니다. 예를 들어이 경우처럼.
sds

4
주제는 언어이므로 "목 아래로"라는 용어는 적절하고 적절한 이미지입니다.
luser droog

1
@KChaloux : 예에서 알 수 있듯이 "표현"을 의미했습니다.
sds

4
당신은 모든 것을 거꾸로 가지고 있습니다. 동적 타이핑은 정적 타이핑의 특수한 경우로, 프로그래머가 모든 유형에 대해 1 가지 유형을 사용하도록합니다. 모든 정적 변수를 유형으로 선언 Object하거나 유형 트리의 루트가 무엇이든 선언하여 대부분의 정적으로 유형이 지정된 언어에서 동일한 작업을 수행 할 수 있습니다 . 이다 적은 당신이 있기 때문에, 표현 박탈옵션을 특정 변수가 특정 값을 포함 할 수 있음을 말하는.
Doval

5

Typed Racket은 Haskell과 매우 다릅니다. Lisp 및 Scheme의 유형 시스템과 실제로는 전통적으로 유형이 지정되지 않은 언어 생태계의 유형 시스템은 다른 유형 시스템이 기존의 유형이 지정되지 않은 코드와 상호 운용 되지 않는다는 기본 목표를 가지고 있습니다 . 예를 들어 Typed Racket은 다양한 라켓 관용구를 수용하기 위해 완전히 새로운 타이핑 규칙을 도입했습니다. 이 기능을 고려하십시오.

(define (first some-list)
  (if (empty? some-list)
      #f
      (car some-list)))

비어 있지 않은 목록의 경우 첫 번째 요소를 반환합니다. 빈 목록의 경우 false를 반환합니다. 이것은 형식화되지 않은 언어에서 일반적입니다. 유형이 지정된 언어는 랩퍼 유형을 사용 Maybe하거나 빈 경우에 오류를 발생시킵니다. 이 함수에 유형을 추가하려면 어떤 유형을 사용해야합니까? [a] -> a거짓을 반환 할 수 있기 때문에 하스켈 표기법 이 아닙니다 . 또한 [a] -> Either a Boolean(1) 임의의 부울이 아닌 빈 경우에 항상 false를 반환하고 (2) 두 유형 중 하나가 요소를 감싸고 Leftfalse로 Right만들고 실제 요소에 도달하려면 "둘 중 하나를 풀어야"하기 때문에 그렇지 않습니다. 대신, 값은 진정한 합집합을 반환합니다-래핑 생성자가 없으며 어떤 경우에는 한 유형을 반환하고 다른 경우에는 다른 유형을 반환합니다. Typed Racket에서 이것은 union 타입 생성자로 표현됩니다 :

(: first (All (A) (-> (Listof A) (U A #f))))
(define (first some-list)
  (if (empty? some-list)
      #f
      (car some-list)))

유형 (U A #f)은 함수가 목록의 요소를 리턴하거나 랩핑 Either인스턴스 없이 false를 리턴 할 수 있음을 나타냅니다 . 유형 검사기는 some-list유형 (Pair A (Listof A))또는 비어있는 목록을 유추 할 수 있으며, if 문의 두 가지 분기에서 어떤 경우 인지 알 수 있습니다. 유형 검사기는 (car some-list)표현식 에서 if 조건이 보장하기 때문에 목록 에 유형이 있어야 함 을 알고 (Pair A (Listof A))있습니다. 이를 발생 유형 이라고 하며 유형이 지정되지 않은 코드에서 유형이 지정된 코드로 쉽게 전환 할 수 있도록 설계되었습니다.

문제는 마이그레이션입니다. 형식화되지 않은 라켓 코드가 많이 있으며 Typed Racket을 사용하면 좋아하는 형식화되지 않은 라이브러리를 모두 포기하고 코드베이스에 유형을 추가하는 데 한 달을 소비 할 수는 없습니다. 이 문제는 기존 코드베이스에 유형을 점진적으로 추가 할 때마다 적용됩니다 . 이러한 아이디어를 자바 스크립트로 적용하려면 TypeScript 및 해당 유형을 참조하십시오.

점진적 형식 시스템은 일반적인 형식화되지 않은 관용구를 처리하고 기존 형식화되지 않은 코드와 상호 작용하기위한 도구를 제공해야합니다. 그렇지 않으면 Clojure 예제를 위해 "더 이상 Core.typed를 사용하지 않는 이유"를 참조하십시오 .


1
경제학에서 이것은 Gresham의 법칙으로 알려져 있습니다 . 나쁜 돈은 좋은 결과를 낳습니다. 엔지니어링 분야에서도 응용 프로그램을 찾는 경향이 있습니다. 시스템 내에 이론적으로 동등한 두 개의 서브 시스템이있는 경우, 여기에서 볼 수 있듯이 더 나쁜 시스템은 너무 많은 문제점을 일으켜 더 많은 것을 사용할 가치가 있습니다.
메이슨 휠러

"그 타입 시스템을 설계하는 예는"이 문장은하지 완료
코어 덤프

@MasonWheeler 더 나쁜 것은 동적 유형 검사입니다. 따라서 소개하자마자 정적 분석을 수행 할 가치가 없습니까?
코어 덤프

1
@coredump-형식화되지 않은 코드와 제대로 상호 작용하지 않는 한 점진적 타이핑이 가치가 있습니다. 예를 들어 TypeScript의 Any 유형은 유형 검사기에 포기하도록 지시합니다. 기본적으로 유형 시스템의 이점을 없애면 대량의 정적으로 검사 된 코드를 통해 나쁜 값이 전파 될 수 있기 때문입니다. Typed Racket은이 문제를 피하기 위해 계약 및 모듈 경계를 사용합니다.
Jack

1
@coredump Clojure 기사를 읽으십시오. 특히 정적 유형을 사용할 수없는 모든 타사 코드를 사용하여 동적으로 타이핑하면 정적 유형으로 코드베이스를 개선하려는 시도를 망쳤습니다.
메이슨 휠러
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.