Haskell, Lisp 및 자세한 정보 [닫힘]


104

Haskell과 Lisp의 어떤 맛을 경험 한 분들에게 Haskell 대 Lisp로 코드를 작성하는 것이 얼마나 "즐거운"(끔찍한 용어를 사용하는지) 궁금합니다.

몇 가지 배경 : 저는 지금 Haskell을 배우고 있으며, 이전에 Scheme 및 CL과 함께 작업했습니다 (그리고 Clojure에 대해 약간의 진출). 전통적으로, 당신은 그들이 제공하는 간결함과 신속성 때문에 저를 동적 언어의 팬이라고 생각할 수있었습니다. Lisp 매크로는 장황함과 상용구를 피할 수있는 또 다른 방법을 제공했기 때문에 금방 사랑에 빠졌습니다.

나는 Haskell이 내가 존재하는지 몰랐던 코딩 방법을 소개하면서 매우 흥미 롭다는 것을 발견 하고 있습니다. 부분 함수 작성의 용이성과 같이 민첩성을 달성하는 데 도움이 될 것 같은 측면이 분명히 있습니다. 그러나 나는 Lisp 매크로를 잃어 버리는 것에 대해 약간 걱정하고 있습니다 (나는 그것들을 잃어버린 것으로 가정합니다; 진실은 아직 그것들에 대해 배우지 않았을 수도 있다는 말입니까?)과 정적 타이핑 시스템.

양 세계에서 상당한 양의 코딩을 해본 사람이 경험이 어떻게 다른지, 당신이 선호하는 것이 무엇인지, 그리고 선호가 상황에 따른 것인지에 대해 언급 할 수 있습니까?

답변:


69

짧은 답변:

  • 매크로로 할 수있는 거의 모든 것을 고차 함수 (그리고 모나드, 화살표 등을 포함)로 할 수 있지만 더 많은 생각이 필요할 수 있습니다 (하지만 처음에만, 재미 있고 당신은 더 나은 프로그래머),
  • 정적 시스템은 결코 당신의 방식으로 얻을 수 없다는 것을 충분히 일반적이며, 다소 놀랍게도 실제로 프로그램은 올바른 거의 확신 할 수 컴파일 할 때 때문에, 그래서 (당신이 말한대로) "민첩성을 달성 보조" 확신은 할 수 있습니다 당신은 시도 다른 방법으로는 시도하기가 두려울 수있는 것들-Lisp와 같지는 않지만 프로그래밍에 "동적"느낌이 있습니다.

[참고 : Lisp 에서처럼 매크로를 작성할 수 있는 " Template Haskell "이 있지만 엄밀히 말하면 절대 필요 하지 않습니다 .]


15
Don Stewart가 인용 한 Conor McBride에서 : '나는 유형이 중력을 왜곡하는 것으로 생각하여 [올바른 프로그램을 작성하기 위해] 이동해야하는 방향이 "내리막"이되도록하는 것을 좋아합니다. 유형 시스템은 올바른 프로그램을 작성하는 것을 놀라 울 정도로 쉽게 만듭니다. 이 게시물 과 그 재 공유를 참조하십시오 .
ShreevatsaR 2011

3
고차 함수는 매크로를 대체 할 수 없으며 실제로 CL에는 어떤 이유로 든 둘 다 있습니다. CL에서 매크로의 진정한 힘은 개발자가 Haskell 또는 Java와 같은 언어의 새 버전을 기다릴 필요없이 문제에 대한 솔루션을 더 잘 표현하는 데 도움이되는 새로운 언어 기능을 도입 할 수 있다는 것입니다. 예를 들어, Haskell이 이러한 권한을 가지고 있다면 Haskell 작성자가 GHC 확장을 작성할 필요가 없을 것입니다. 개발자가 언제든지 매크로로 구현할 수 있습니까?
mljrg 2015 년

@mljrg 구체적인 예가 있습니까? 의심스러운 예가 밝혀진 Hibou57의 답변에 대한 의견을 참조하십시오. 나는 당신이 의미하는 것의 종류를 알고 싶습니다 (예 : 매크로가 있거나없는 Haskell 코드).
ShreevatsaR

4
Haskell에서 카레를 꺼내십시오. Haskell에 남겨진 것으로 구현할 수 있습니까? 또 다른 예 : Haskell이 패턴 매칭을 지원하지 않는다고 가정합니다. GHC 개발자가 지원할 필요없이 직접 추가 할 수 있습니까? CL에서는 매크로를 사용하여 원하는대로 언어를 확장 할 수 있습니다. 이것이 바로 CL 언어가 90 년대의 표준 이후로 변경되지 않은 이유 인 반면 Haskell은 GHC에서 끝없는 확장의 흐름을 가지고있는 것처럼 보입니다.
mljrg 2015 년

64

우선, 동적 타이핑과 같은 특정 기능을 잃어 버릴 염려가 없습니다. 놀랍도록 잘 설계된 언어 인 Common Lisp에 대해 잘 알고 있기 때문에 언어를 기능 세트로 축소 할 수 없다는 것을 알고 있다고 가정합니다. 그것은 모두 일관된 전체에 관한 것입니다.

이와 관련하여 Haskell은 Common Lisp만큼 밝게 빛납니다. 이 기능이 결합되어 코드를 매우 짧고 우아하게 만드는 프로그래밍 방법을 제공합니다. 매크로의 부족은 모나드 및 화살표와 같은보다 정교한 (그러나 이해하고 사용하기 더 어려운) 개념으로 다소 완화됩니다. 정적 유형 시스템은 대부분의 객체 지향 언어 에서처럼 방해가되지 않고 힘을 더합니다.

반면에 Haskell의 프로그래밍은 Lisp보다 훨씬 덜 상호 작용하며 Lisp와 같은 언어에 존재하는 엄청난 양의 반사는 Haskell이 가정하는 세계의 정적 인 관점에 맞지 않습니다. 따라서 사용할 수있는 도구 세트는 두 언어간에 상당히 다르지만 서로 비교하기는 어렵습니다.

저는 개인적으로 Lisp 방식의 프로그래밍을 선호합니다. 제가 더 잘 일하는 방식에 적합하다고 생각하기 때문입니다. 그러나 이것이 당신이 그렇게 할 의무가 있음을 의미하지는 않습니다.


4
"Haskell에서의 프로그래밍은 훨씬 덜 상호 작용 적"에 대해 좀 더 자세히 설명해 주시겠습니까? GHCi가 실제로 필요한 모든 것을 제공하지 않습니까?
요하네스 Gerer

3
@JohannesGerer : 나는 그것을 시도하지 않았지만 내가 읽은 한, GHCi는 실행중인 이미지에 대한 쉘이 아니므로 실행하는 동안 전체 프로그램의 임의의 부분을 재정의하고 확장 할 수 있습니다. 또한 Haskell 구문은 프로그래밍 방식으로 repl과 편집기간에 프로그램 조각을 복사하는 것을 훨씬 더 어렵게 만듭니다.
Svante

13

많은 것이 모나드를 중심으로 구조화 될 수 있고 추가 된 구문으로 인해 임베디드 DSL이 트리처럼 보이지 않기 때문에 Haskell에서 메타 프로그래밍에 대한 필요성이 Common Lisp보다 적습니다. 그러나 ShreevatsaR 에서 언급했듯이 항상 Template Haskell, 심지어 Liskell (Haskell semantics + Lisp 구문) 괄호가 마음에 들면.


1
Liskell 링크 는 죽었지 만 요즘에는 Hackett이 있습니다.
Will Ness

10

매크로와 관련하여 여기에 대해 설명하는 페이지가 있습니다. Hello Haskell, Goodbye Lisp . Haskell에서 매크로가 필요하지 않은 관점을 설명합니다. 비교를위한 간단한 예가 함께 제공됩니다.

두 인수의 평가를 피하기 위해 LISP 매크로가 필요한 경우의 예 :

(defmacro doif (x y) `(if ,x ,y))

Haskell이 매크로 정의와 같은 것이 필요하지 않고 두 인수를 체계적으로 평가하지 않는 경우의 예 :

doif x y = if x then (Just y) else Nothing

그리고 voilà


17
그것은 일반적인 오해입니다. 예, Haskell에서 게으름은 표현식의 일부를 평가하지 않으려 고 할 때 매크로가 필요하지 않다는 것을 의미하지만 모든 매크로 사용 중 가장 사소한 부분 일뿐입니다. 게으름으로 할 수없는 매크로를 보여주는 강연의 "The Swine Before Perl"을위한 Google. 당신이 경우에도 않는 일부 비트는 엄격한되고 싶어, 당신은 함수로 할 수 없어 - 계획의가 있다는 사실 미러링 delay기능 할 수 없습니다.
Eli Barzilay

8
@Eli Barzilay :이 예가 그다지 설득력이 없다고 생각합니다. 다음은 슬라이드 40의 완전하고 간단한 Haskell 번역입니다. pastebin.com/8rFYwTrE
Reid Barton

5
@Eli Barzilay : 귀하의 답변을 전혀 이해하지 못합니다. accept 이다 제 (E) DSL은. 이 accept함수는 이전 페이지에 설명 된 매크로 v와 유사하며의 정의는 v슬라이드 40의 Scheme에 있는 정의와 정확히 유사합니다 . Haskell 및 Scheme 함수는 동일한 평가 전략으로 동일한 것을 계산합니다. 기껏해야 매크로를 사용하면 프로그램의 구조를 더 많이 최적화 프로그램에 노출 할 수 있습니다. 매크로가 게으른 평가에 의해 복제되지 않는 방식으로 언어의 표현력을 증가시키는 예라고 주장 할 수 없습니다.
Reid Barton

5
@Eli Barzilay : 가상의 게으른 Scheme에서 다음과 같이 작성할 수 있습니다. pastebin.com/TN3F8VVE 내 일반적인 주장은이 매크로가 사용자를 거의 구입하지 않는다는 것입니다. 약간 다른 구문과 최적화 프로그램에 대한 더 쉬운 시간입니다 (하지만 중요하지 않습니다. "충분히 스마트 한 컴파일러"). 그 대가로 당신은 자신을 표현할 수없는 언어에 갇혔습니다. 모든 문자를 나열하지 않고 문자와 일치하는 자동 장치를 어떻게 정의합니까? 또한 "모든 하위 목록에서 사용"또는 "자신의 범위에서 필요한 곳에 사용"이 의미하는 바를 모르겠습니다.
Reid Barton

15
좋아요, 포기합니다. 분명히 DSL의 당신의 정의는 원래 구문 동형 인 (에도 불구하고, 나의 게으른 계획의 예는 DSL하지 그래서 "매크로에 대한 인수"입니다 automaton되고 letrec, :되고 accept, ->이 버전에서 아무것도되고 없음). 도대체 무엇이.
Reid Barton

9

저는 Common Lisp 프로그래머입니다.

얼마 전에 Haskell을 사용해 본 경험은 CL을 고수하는 것이 었습니다.

원인:

  • 동적 타이핑 (동적 타이핑 vs. 정적 타이핑 — Pascal Costanza의 패턴 기반 분석 확인 )
  • 선택적 및 키워드 인수
  • 매크로를 사용하는 균일 한 동음이 파 목록 구문
  • 접두사 구문 (우선 순위 규칙을 기억할 필요 없음)
  • 불순하므로 빠른 프로토 타이핑에 더 적합합니다.
  • Meta-Object 프로토콜을 사용하는 강력한 개체 시스템
  • 성숙한 표준
  • 다양한 컴파일러

Haskell은 물론 고유 한 장점을 가지고 있으며 근본적으로 다른 방식으로 몇 가지 일을 수행하지만 장기적으로는 그것을 줄이지 않습니다.


링크 한 Costanza 논문의 제목이 있으신가요? 파일이 이동 된 것 같습니다.
michiakig

2
haskell도 접두사 구문을 지원하지만 모나드 >> =는 그것을 사용하는 것이 매우 추악 할 것이라고 말하고 싶습니다. 또한 나는 불순물이 축복이라는 것에 동의하지 않습니다 : P
대안

2
나는이 부주를 좋아한다 : 우리는이 문제가 실제 프로그램에서 심각한 문제를 일으키는 지에 대한 경험적 데이터를 아직 수집하지 않았다.
Jerome Baum

22
해당 백서 (Pascal Costanza, Dynamic vs. Static Typing — A Pattern-Based Analysis )의 예는 Haskell에 적용되지 않습니다. 그것들은 모두 자바에 특화되어 있으며 (보다 정확하게는 "객체 지향 프로그래밍"에 특화되어 있음 ) 하스켈에서 이러한 문제가 발생하는 것을 볼 수 없습니다. 마찬가지로, 다른 모든 주장은 논란의 여지가 있습니다. Haskell이 "순수하고 따라서 빠른 프로토 타이핑에 더 적합하다"고 말할 수 있습니다. 접두사 구문은 필수가 아니며 다양한 작업을 수행하는 광범위한 컴파일러가 없습니다. , etc.
ShreevatsaR 2011-12-12

11
그 논문은 실제로 Haskell과 거의 전혀 관련이 없습니다. " dilbert = dogbert.hire(dilbert);"?? 나는 많은 Haskell 프로그래머들이 조금도 경련하지 않고 이것을 읽을 수 있을지 의심 스럽다.
leftaroundabout

6

Haskell에서는 LISP에서는 불가능한 if 함수를 정의 할 수 있습니다. 이는 프로그램에서 더 많은 모듈성을 허용하는 게으름 때문에 가능합니다. 이 고전적인 논문 : John Hughes가 FP가 중요한 이유 는 게으름이 구성 성을 향상시키는 방법을 설명합니다.


5
Scheme (두 가지 주요 LISP 방언 중 하나)에는 실제로는 지연 평가가 있지만 Haskell에서와 같이 기본값은 아닙니다.
Randy Voet

7
(defmacro doif (xy)`(if, x, y))
Joshua Cheek

4
매크로는 함수와 동일하지 않습니다. 매크로는와 같은 고차 함수에서 잘 작동하지 않는 fold반면 엄격 하지 않은 함수 .
Tikhon Jelvis 2013 년

5

Haskell에서는 (가능하다면) 성가신 매크로로 Lisp에서 얻을 수있는 정말 멋진 일들이 있습니다. 예를 들어 'memoize'매크로를 사용합니다 (Peter Norvig의 PAIP 9 장 참조). 그것으로, 당신은 foo라고하는 함수를 정의 할 수 있고, foo의 전역 정의를 메모 된 버전으로 대체하는 (memoize 'foo) 간단히 평가할 수 있습니다. 고차 함수를 사용하여 Haskell에서 동일한 효과를 얻을 수 있습니까?


3
정답은 아니지만 (AFAIK), 함수를 수정 (재귀 적이라고 가정)하여 단순히 이름으로 자신을 호출하는 대신 매개 변수 (!)로 재귀 적으로 호출하도록 함수를 수정하여 비슷한 작업을 수행 할 수 있습니다. haskell.org/haskellwiki/Memoization
j_random_hacker

6
게으른 데이터 구조에 foo를 추가하면 값이 계산되면 저장됩니다. 이것은 사실상 동일합니다.
Theo Belaire 2011

Haskell의 모든 내용은 기본적으로 Haskell 컴파일러에 의해 필요할 때 메모되고 인라인 될 수 있습니다.
aoeu256

4

Haskell 학습 여정을 계속하면서 매크로를 "교체"하는 데 도움이되는 한 가지는 자신의 중위 연산자를 정의하고 우선 순위와 연관성을 사용자 정의하는 기능인 것 같습니다. 다소 복잡하지만 흥미로운 시스템입니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.