Haskell、Lisp、および冗長性[終了]


104

HaskellといくつかのLispのフレーバーの両方で経験した人にとって、HaskellとLispのどちらでコードを書くのが(恐ろしい用語を使用するのが)どれほど「楽しい」かが気になります。

背景:今はHaskellを学んでいます。以前にSchemeとCLを使用していた(そしてClojureに少し進出した)。伝統的に、あなたは私が動的言語のファンをそれらが提供する簡潔さと迅速さのためにファンであると考えることができました。Lispマクロにすぐに夢中になりました。冗長性とボイラープレートを回避するためのもう1つの方法になったからです。

Haskellは信じられないほど興味深いものだと思います。これは、存在することを知らなかったコーディング方法を紹介するものです。確かに、部分的な関数を簡単に記述できるなど、俊敏性の実現に役立つように見えるいくつかの側面があります。しかし、私はLispマクロ(私はそれらを失うと思います。真実はまだそれらについて学んでいないかもしれないと言われています)と静的型付けシステムを失うことについて少し心配しています。

両方の世界でまともな量のコーディングを行った人は、経験がどのように異なるのか、好みが状況に応じてコメントすることを気にかけますか?

回答:


69

短い答え:

  • マクロでできることはほとんど何でも高階関数でできます(そしてモナドや矢印などを含みます)。それのためのより良いプログラマ)、そして
  • 静的システムは十分に一般的であり、邪魔になることはありませんが、やや驚くべきことに、実際に「俊敏性の達成を支援する」(前述のとおり)ので、プログラムのコンパイル時に正しいことがほぼ確実になるため、この確実性を試すことができますLispの場合とは異なりますが、プログラミングには「動的」な感覚があります。

[注:Lispと同じようにマクロを記述できる「テンプレートHaskell」がありますが、厳密に言うと、それを必要することはありません。]


15
ドン・スチュワートが引用したコナー・マクブライドから:「私はタイプを重力を歪めるものとして考えたいので、[正しいプログラムを書くために]移動する必要がある方向は「下り坂」になります。」 型システムにより、正しいプログラムを驚くほど簡単に作成できます。この投稿とその再共有を参照してください。
ShreevatsaR 2011年

3
高次関数はマクロを置き換えることはできません。実際、CLは何らかの理由で両方を備えています。CLのマクロの真の力は、HaskellやJavaのような新しいバージョンの言語を待たずに、開発者が問題の解決策をよりよく表現するのに役立つ新しい言語機能を導入できることです。たとえば、Haskellにこの機能がある場合、Haskellの作成者がGHC拡張を作成する必要はなく、開発者自身がいつでもマクロとして実装できます。
mljrg

@mljrg具体的な例はありますか?疑わしい例が疑わしいことが判明した、以下のHibou57の回答に関するコメントを参照してください。私はあなたが何を意味しているのかを知りたいと思います(例えば、マクロの有無にかかわらずHaskellコード)。
ShreevatsaR

4
Haskellからカレーを取り出してください。Haskellに残されたものでそれを実装できますか?別の例:Haskellがパターンマッチングをサポートしていない場合、GHCの開発者がパターンマッチングをサポートしなくても、パターンマッチングを自分で追加できますか?CLでは、マクロを使用して自由に言語を拡張できます。そのため、CLの言語は90年代の標準以来変更されていませんが、HaskellにはGHCで拡張機能の終わりのない流れがあるようです。
mljrg

64

まず第一に、動的タイピングのような特定の機能を失う心配はありません。非常によく設計された言語であるCommon Lispに精通しているので、言語をその機能セットに限定できないことに気付いていると思います。すべてがまとまりのあるものですね。

この点で、HaskellはCommon Lispと同じくらい明るく輝きます。その機能を組み合わせて、コードを非常に短くエレガントにするプログラミング方法を提供します。マクロの欠如は、モナドや矢印などのより複雑な(ただし、同様に理解および使用が難しい)概念によってある程度緩和されます。静的型システムは、ほとんどのオブジェクト指向言語のように邪魔になるのではなく、あなたの力を高めます。

一方、HaskellでのプログラミングはLispよりもはるかにインタラクティブではなく、Lispのような言語に存在する膨大な量のリフレクションは、Haskellが前提としている世界の静的なビューに適合しません。したがって、使用できるツールセットは2つの言語間でかなり異なりますが、互いに比較することは困難です。

個人的には、プログラミングのLispの方法が一般的に好きです。それは、自分の作業方法に適していると感じているからです。ただし、これはあなたがそうする義務があるという意味ではありません。


4
「Haskellでのプログラミングはあまりインタラクティブではない」についてもう少し詳しく説明してください。GHCiは本当に必要なものすべてを提供していないのですか?
Johannes Gerer 2013

3
@JohannesGerer:私は試していませんが、読んだ限りでは、GHCiは実行中のイメージのシェルではありません。実行中のプログラム全体の任意の部分を再定義および拡張できます。また、Haskell構文では、replとエディター間でプログラムのフラグメントをプログラムでコピーするのがはるかに困難になります。
Svante 2013

13

そこ多くはモナドを中心に構成することができますので、Common LispではよりもHaskellでメタプログラミングのためのより少ない必要がありますし、追加の構文は、組み込みのDSLが少ないツリー状に見えるのですが、で述べたように、テンプレートHaskellは、常にありますShreevatsaR、とさえLiskell(Haskellのセマンティクス+ Lispの構文)かっこが必要な場合。


1
Liskell リンクは機能していませんが、最近はHackettがあります。
ネスは

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

そしてボイラ


17
それはよくある誤解です。はい、Haskellの遅延とは、式の一部を評価したくない場合にマクロを必要としないことを意味しますが、それらはすべてのマクロ使用の中で最も重要なサブセットにすぎません。「The Swine Before Perl」のGoogleは、怠惰では実行できないマクロを説明する講演を行いました。また、少し厳密にたい場合は、それを関数として実行することはできません。Schemeは関数にdelayはなれないという事実を反映しています。
Eli Barzilay、2010

8
@Eli Barzilay:この例はあまり説得力がないと思います。スライド40の完全で単純なHaskellの翻訳は次のとおりです。pastebin.com
Reid Barton

5
@Eli Barzilay:私はあなたの反応をまったく理解していません。accept である(E)DSLが。このaccept関数は、前のページで概説したマクロに類似vしており、の定義はv、スライド40のScheme の定義とまったく同じです。Haskell関数とScheme関数は、同じものを同じ評価戦略で計算します。せいぜい、マクロを使用すると、プログラムの構造のより多くをオプティマイザに公開できます。マクロが遅延評価によって複製されない方法で言語の表現力を高める例としてこれを主張することはほとんどできません。
リードバートン

5
@Eli Barzilay:架空の怠惰なスキームでは、あなたはこの書くことができるpastebin.com/TN3F8VVE私の一般的な主張は非常に少ない。このマクロ買物はあなたのことです:わずかに異なる構文とオプティマイザのために簡単に時間(しかし、それが問題ではないだろうが「十分にスマートなコンパイラ」)。その代わり、あなたは自分を表現力のない言語に閉じ込めました。すべてをリストせずに任意の文字に一致するオートマトンをどのように定義しますか?また、「すべてのサブリストで使用する」または「独自のスコープでwhereを使用する必要がある」という意味がわかりません。
リードバートン

15
はい、あきらめます。どうやらあなたのDSLの定義は「マクロへの引数」であり、元の構文と同型であるにも関わらず(このバージョンではにautomatonなるletrec、に:なるaccept->何もなくなる)にもかかわらず、私の怠惰なSchemeの例はDSLではありません。なんでも。
リードバートン

9

私はCommon Lispプログラマーです。

少し前にHaskellを試してみて、私の個人的な利益はCLに固執することでした。

理由:

  • 動的型付け(動的型と静的型付けの比較— Pascal Costanzaによるパターンベースの分析を確認してください)
  • オプションおよびキーワード引数
  • マクロを使用した統一ホモニコニックリスト構文
  • プレフィックス構文(優先ルールを覚えておく必要はありません)
  • 不純であるため、迅速なプロトタイピングに適している
  • メタオブジェクトプロトコルを備えた強力なオブジェクトシステム
  • 成熟した標準
  • 幅広いコンパイラ

Haskellにはもちろん独自のメリットがあり、根本的に異なる方法でいくつかのことを行いますが、長期的にはそれを削減しません。


ねえ、あなたはたまたまあなたがリンクしたそのコスタンツァの論文のタイトルを持っていますか?そのファイルは移動されたようです。
michiakig 2010

2
haskellもプレフィックス構文をサポートしていますが、モナド>> =は非常に醜く使用すると思います。P:また、私は祝福され、不純物に反対
代替

2
このサイドノートが好きです。この問題が実際のプログラムで深刻な問題を引き起こすかどうかについては、まだ実証的なデータを収集していません。
Jerome Baum

22
その論文の例(Pascal Costanza、動的型と静的型の比較—パターンに基づく分析)はHaskellには当てはまりません。これらはすべてJava固有(より正確には「オブジェクト指向プログラミング」に固有)であり、Haskellでこれらの問題が発生することはありません。同様に、他のすべての引数は議論の余地があります。Haskellは「純粋であり、迅速なプロトタイピングに適している」と言えるでしょう。そのプレフィックス構文は必須ではなく、さまざまなことを実行するさまざまなコンパイラがないためです。 、など
ShreevatsaR

11
その論文は確かにほぼ完全にHaskellとは無関係です。「dilbert = dogbert.hire(dilbert);」私は多くのHaskellプログラマーが少しひっくり返すことなくこれを読むことさえできないと思います。
leftaroundabout

6

Haskellでは、LISPでは不可能なif関数を定義できます。これは、プログラムのモジュール化を可能にする遅延のために可能です。この古典的な論文:ジョンヒューズによるFPが重要である理由は、遅延が構成可能性をどのように向上させるかを説明しています。


5
Scheme(2つの主要なLISP方言のうちの1つ)は実際には遅延評価を行いますが、Haskellのようにデフォルトではありません。
Randy Voet

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

4
マクロは関数と同じではありませfoldたとえば、マクロはのような高次の関数ではうまく機能しませんが、厳密でない関数で機能しません
Tikhon Jelvis 2013年

5

Haskellで(可能であれば)煩雑なマクロを使用してLispで実現できる本当に素晴らしいものがあります。たとえば、「メモ化」マクロを使用します(Peter NorvigのPAIPの第9章を参照)。これを使用すると、fooなどの関数を定義して、評価(メモ化 'foo)できます。これにより、fooのグローバル定義がメモ化されたバージョンに置き換えられます。高階関数を使用してHaskellで同じ効果を達成できますか?


3
完全ではありませんが(AFAIK)、関数を変更して(再帰的であると仮定して)同様のことを行うことができます。単に名前で自分自身を呼び出すのではなく、関数をパラメータとして再帰的に呼び出す(!):haskell.org/haskellwiki/Memoization
j_random_hacker

6
fooを遅延データ構造に追加できます。値は計算されると格納されます。これは事実上同じです。
Theo Belaire、2011

Haskellのすべてがメモされ、おそらくHaskellコンパイラによってデフォルトで必要なときにインライン化されます。
aoeu256

4

私がHaskell学習の旅を続けると、マクロを「置き換える」のに役立つ1つのことは、独自のインフィックス演算子を定義し、それらの優先順位と結合性をカスタマイズする機能です。ちょっと複雑ですが、興味深いシステムです!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.