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.