정적으로 형식화 된 전체 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.