[programming-languages] 정적으로 형식화 된 전체 Lisp 변형이 가능합니까?

정적으로 형식화 된 전체 Lisp 변형이 가능합니까? 이와 같은 것이 존재하는 것이 의미가 있습니까? Lisp 언어의 장점 중 하나는 정의의 단순성이라고 생각합니다. 정적 입력이이 핵심 원칙을 손상시킬까요?



답변

예, 가능합니다. 표준 HM 스타일 유형 시스템은 일반적으로 대부분의 관용적 Lisp / Scheme 코드에 대해 잘못된 선택입니다. 정적 타이핑을 사용하는 “Full Lisp”(실제로 Scheme과 더 비슷 함) 인 최신 언어에 대해서는 Typed Racket 을 참조하십시오 .


답변

Lisp 처럼 보이는 정적으로 형식화 된 언어 만 원하는 경우 해당 언어 를 나타내는 추상 구문 트리를 정의한 다음 해당 AST를 S- 표현식으로 매핑하여 쉽게 수행 할 수 있습니다. 그러나 나는 결과를 Lisp라고 부르지 않을 것이라고 생각합니다.

구문 외에 실제로 Lisp-y 특성이있는 것을 원한다면 정적으로 형식화 된 언어로이를 수행 할 수 있습니다. 그러나 Lisp에는 많은 유용한 정적 타이핑을 얻기 어려운 많은 특성이 있습니다. 설명을 위해 Lisp의 기본 구성 요소를 형성하는 cons 라는 목록 구조 자체를 살펴 보겠습니다 .

단점을 목록이라고 부르는 것은 (1 2 3)마치 하나처럼 보이지만 약간 잘못된 이름입니다. 예를 들어, C ++ std::list또는 Haskell의 목록 과 같이 정적으로 형식화 된 목록과 전혀 비교할 수 없습니다 . 이들은 모든 셀이 동일한 유형 인 1 차원 연결 목록입니다. Lisp는 기꺼이 (1 "abc" #\d 'foo). 또한 정적 유형 목록을 목록 목록을 포함하도록 확장하더라도 이러한 개체 유형은 목록의 모든 요소가 하위 목록이어야합니다. 당신은 ((1 2) 3 4)그들에게 어떻게 표현 하겠습니까?

Lisp conses는 잎 (원자)과 가지 (conses)가있는 이진 트리를 형성합니다. 또한, 그러한 나무의 잎은 어떤 원자 (비 죄수) Lisp 유형을 포함 할 수 있습니다! 이 구조의 유연성으로 인해 Lisp는 기호 계산, AST를 처리하고 Lisp 코드 자체를 변환하는 데 매우 능숙합니다!

그렇다면 정적으로 형식화 된 언어로 그러한 구조를 어떻게 모델링할까요? 매우 강력하고 정확한 정적 유형 시스템을 가진 Haskell에서 시도해 보겠습니다.

type Symbol = String
data Atom = ASymbol Symbol | AInt Int | AString String | Nil
data Cons = CCons Cons Cons
            | CAtom Atom

첫 번째 문제는 Atom 유형의 범위입니다. 분명히, 우리는 우리가 빙빙 돌고 싶은 모든 유형의 물체를 포괄 할 수있는 충분한 유연성의 Atom 유형을 선택하지 않았습니다. 위에 나열된 Atom 데이터 구조를 확장하려고하는 대신 (분명히 깨지기 쉬운 Atomic것을 알 수 있음) 원자로 만들고자하는 모든 유형을 구별 하는 마법 유형 클래스가 있다고 가정 해 보겠습니다 . 그런 다음 시도해 볼 수 있습니다.

class Atomic a where ?????
data Atomic a => Cons a = CCons Cons Cons
                          | CAtom a

그러나 이것은 트리의 모든 원자가 동일한 유형 이어야하기 때문에 작동하지 않습니다 . 우리는 그들이 잎마다 다를 수 있기를 바랍니다. 더 나은 접근 방식은 Haskell의 실존 적 수량 자를 사용해야합니다 .

class Atomic a where ?????
data Cons = CCons Cons Cons
            | forall a. Atomic a => CAtom a 

그러나 이제 당신은 문제의 핵심에 도달했습니다. 이런 종류의 구조에서 원자로 무엇을 할 수 있습니까? 모델링 할 수있는 공통 구조는 무엇입니까 Atomic a? 이러한 유형으로 어떤 수준의 유형 안전성이 보장됩니까? 우리가 타입 클래스에 어떤 함수도 추가하지 않았 음을 주목하세요. 그리고 좋은 이유가 있습니다 : 원자들은 Lisp에서 공통점을 공유하지 않습니다. Lisp에서 그들의 슈퍼 타입은 단순히 t(즉, top) 이라고 불립니다 .

그것들을 사용하기 위해서는 원자의 가치를 실제로 사용할 수있는 것으로 동적으로 강요 하는 메커니즘을 생각해 내야 합니다. 그리고 그 시점에서 기본적으로 정적으로 입력 된 언어 내에서 동적으로 입력 된 하위 시스템을 구현했습니다! ( Greenspun의 10 번째 프로그래밍 규칙에 대한 가능한 결과에 주목할 수밖에 없습니다 .)

하스켈은 바로 그러한에 대한 지원을 제공하는 참고 동적 서브 시스템ObjA를 함께 사용 유형, Dynamic유형과 Typeable 클래스 우리의 교체 Atomic임의의 값이 해당 유형으로 보존 할 수 있도록 클래스를, 이러한 유형의 명시적인 강제 백을. 이것이 Lisp cons 구조를 전체적으로 일반화하기 위해 사용해야하는 종류의 시스템입니다.

또한 할 수있는 작업은 다른 방식으로 이동하여 기본적으로 동적으로 형식화 된 언어 내에 정적으로 형식화 된 하위 시스템을 포함하는 것입니다. 이를 통해보다 엄격한 유형 요구 사항을 활용할 수있는 프로그램 부분에 대한 정적 유형 검사의 이점을 얻을 수 있습니다. 예를 들어 이것은 CMUCL의 제한된 형식의 정확한 유형 검사 에서 취한 접근 방식 인 것 같습니다 .

마지막으로 계약 스타일 프로그래밍을 사용하여 둘 사이의 전환을 탐색하는 데 도움이되는 동적 및 정적으로 형식화 된 두 개의 개별 하위 시스템을 가질 가능성이 있습니다. 이런 식으로 언어는 정적 유형 검사가 도움말보다 더 방해가되는 Lisp의 사용과 정적 유형 검사가 유리한 사용을 수용 할 수 있습니다. 이것은 다음 주석에서 볼 수 있듯이 Typed Racket이 취하는 접근 방식 입니다.


답변

내 대답은 높은 수준의 자신감이 없으면 아마도 . 예를 들어 SML과 같은 언어를보고 Lisp와 비교하면 각 기능의 핵심은 거의 동일합니다. 결과적으로 Lisp의 핵심 (함수 응용 프로그램 및 기본 값)에 어떤 종류의 정적 유형을 적용하는 데 큰 문제가없는 것 같습니다.

귀하의 질문은 완전 하다고 말하고 있으며 문제가 발생하는 부분은 코드로서의 데이터 접근 방식입니다. 유형은 표현식보다 더 추상적 인 수준에 존재합니다. Lisp에는 이러한 구분이 없습니다. 모든 것이 구조적으로 “평평”합니다. 어떤 식 E : T (여기서 T는 그 유형의 일부 표현)를 고려 하고이 식을 일반 ol ‘데이터로 간주하면 여기서 T의 유형은 정확히 무엇입니까? 글쎄, 그것은 종류입니다! 종류는 더 높은 순서 유형이므로 계속 진행하여 코드에서 이에 대해 말하겠습니다.

E : T :: K

당신은 내가 이것으로 어디로 가고 있는지 볼 수 있습니다. 코드에서 유형 정보를 분리함으로써 이러한 유형의 자기 참조를 피하는 것이 가능할 것이라고 확신합니다. 이 문제를 해결하는 방법에는 여러 가지가있을 수 있지만 어떤 방법이 가장 좋은지는 분명하지 않습니다.

편집 : 아, 그래서 약간의 인터넷 검색을 통해 Qi를 찾았 습니다. 정적으로 입력된다는 점을 제외하고 Lisp와 매우 유사합니다. 아마도 정적 타이핑을 얻기 위해 어디에서 변경했는지 확인하기 시작하는 것이 좋습니다.


답변


답변