정적으로 형식화 된 전체 Lisp 변형이 가능합니까?


107

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


10
나는 Lisp의 자유형 매크로를 좋아하지만 Haskell의 유형 시스템의 견고 함을 좋아합니다. 정적으로 형식화 된 Lisp가 어떻게 생겼는지보고 싶습니다.
mcandre

4
좋은 질문! 나는 shenlanguage.org 가 그렇게 한다고 믿습니다 . 더 주류가 되었으면합니다.
Hamish Grubijan 2013


Haskell로 기호 컴퓨팅을 어떻게 수행합니까? (해결 'x'(= (+ xy) (* xy))). 문자열에 넣으면 검사가 없습니다 (매크로를 사용하여 검사를 추가 할 수있는 Lisp와 달리). 대수 데이터 유형이나 목록을 사용하는 경우 ... 매우 장황 할 것입니다. solve (Sym "x") (Eq (Plus (Sym "x") (Sym "y")) (Mult (Sym "x") (Sym을 "Y")))
aoeu256

답변:


57

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


1
여기서 문제는 유형화 된 라켓 프로그램의 전체 소스 코드를 구성하는 목록의 유형이 무엇입니까?
Zorf

18
일반적으로 Sexpr.
Eli Barzilay

하지만 coerce :: a->beval로 쓸 수 있습니다 . 유형 안전은 어디에 있습니까?
ssice

2
@ssice : eval결과를 테스트하여 결과를 확인해야하는 것과 같이 유형이 지정되지 않은 함수를 사용할 때 Typed Racked에서 새로운 것은 아닙니다 ( Stringand 의 공용체 유형을 취하는 함수와 동일한 거래 Number). 이것이 수행 될 있음 을 확인하는 암시 적 방법 은 HM 정적 유형 언어로 동적 유형 언어를 작성하고 사용할 있다는 사실입니다 .
Eli Barzilay

37

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이 취하는 접근 방식 입니다.


16
이 답변에는 근본적인 문제가 있습니다. 정적 유형 시스템 이 HM 스타일 이어야 한다고 가정합니다 . 여기서 표현할 수없고 Lisp 코드의 중요한 기능인 기본 개념은 서브 타이핑입니다. 같은 것들을 포함 - 사용자가 입력 라켓 살펴 보겠습니다 경우에, 당신은 쉽게 목록의 모든 종류 표현할 수있는 것을 볼 수 있습니다 (Listof Integer)(Listof Any). 분명히 유형에 대해 아무것도 모르기 때문에 후자가 쓸모 없다고 의심하지만 TR에서는 나중에 사용할 수 (if (integer? x) ...)있으며 시스템은 이것이 x첫 번째 분기에서 정수임을 알 것 입니다.
Eli Barzilay

5
아, 그리고 그것은 유형이 지정된 라켓의 나쁜 특성입니다 (어떤 곳에서 찾을 수있는 불건전 한 유형 시스템과 다릅니다). 형식화 된 라켓 입니다 정적으로 입력 된 입력 된 코드에 대한 어떤 런타임 오버 헤드, 언어. Racket은 여전히 ​​일부 코드를 TR로 작성하고 일부는 일반적인 유형이 지정되지 않은 언어로 작성할 수 있으며, 이러한 경우 계약 (동적 검사)을 사용하여 잠재적으로 오작동하는 유형이 지정되지 않은 코드로부터 유형이 지정된 코드를 보호합니다.
Eli Barzilay

1
@Eli Barzilay : 거짓말을했습니다. 네 부분이 있습니다. 4. 업계에서 인정하는 C ++ 코딩 스타일이 서브 타이핑에서 제네릭으로 점진적으로 이동하는 방식이 흥미 롭습니다. 약점은 언어가 제네릭 함수가 사용할 인터페이스를 선언하는 데 도움이되지 않는다는 것입니다. 유형 클래스는 확실히 도움이 될 수 있습니다. 또한 C ++ 0x는 유형 추론을 추가 할 수 있습니다. HM은 아니지만 그 방향으로 기어 다니는 것입니까?
Owen S.

1
Owen : (1) 요점은 코드리스 퍼 작성의 종류를 표현하기 위해 하위 유형 이 필요 하다는 것입니다. HM 시스템에서는이를 가질 수 없기 때문에 각 용도에 맞게 유형과 생성자를 사용자 지정해야합니다. 모든 것을 사용하기 훨씬 더 어색하게 만듭니다. 하위 유형이있는 시스템을 사용하는 유형화 된 라켓에서는 의도적 인 디자인 결정의 결과가있었습니다. 결과는 코드 변경하거나 사용자 정의 유형을 만들지 않고도 그러한 코드 유형을 표현할 수 있어야한다는 것 입니다.
Eli Barzilay

1
(2) 예, dynamic유형은 동적 유형 언어의 이점 중 일부를 얻기위한 일종의 해결 방법으로 정적 언어에서 인기를 얻고 있습니다. 이러한 값의 일반적인 트레이드 오프는 유형을 식별 할 수있는 방식으로 래핑됩니다. 그러나 여기서 너무 유형이 지정된 라켓은 언어 내에서 편리하게 만드는 데 아주 좋은 일을하고 있습니다. 유형 검사기는 유형에 대해 더 많이 알기 위해 술어 발생을 사용합니다. 예를 들어, 라켓 페이지 에 입력 된 예를 보고 string?문자열 및 숫자 목록을 문자열 목록으로 "줄이는" 방법을 확인하십시오 .
Eli Barzilay

10

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

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

E : T :: K

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

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


Qi 이후의 다음 반복 은 같은 사람이 개발 한 Shen 입니다.
Diagon 2019-08-23

4

링크가 끊어졌습니다. 그러나 어쨌든 Dylan은 정적으로 입력되지 않습니다.
Björn Lindqvist

@ BjörnLindqvist : 그 링크는 Dylan에 점진적인 타이핑을 추가하는 것에 대한 논문이었습니다.
라이너 Joswig

1
@ BjörnLindqvist : 개요 문서에 연결했습니다.
Rainer Joswig

그러나 점진적 타이핑은 정적 타이핑으로 간주되지 않습니다. 만약 그렇다면 Pypy는 점진적인 타이핑을 사용하기 때문에 정적으로 파이썬으로 타이핑 될 것입니다.
Björn Lindqvist

2
@ BjörnLindqvist : 점진적 유형을 통해 정적 유형을 추가하고 컴파일 중에 이러한 유형을 확인하면 정적 유형입니다. 전체 프로그램이 정적으로 입력되는 것이 아니라 부분 / 영역입니다. homes.sice.indiana.edu/jsiek/what-is-gradual-typing '점진적 타이핑은 내가 2006 년에 Walid Taha와 함께 개발 한 타입 시스템으로, 프로그램의 일부는 동적으로 타이핑되고 다른 부분은 정적으로 타이핑 될 수 있습니다.'
Rainer Joswig
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.