LispとSchemeの型


10

ラケットにはタイプがあります。一見すると、Haskellのタイピングとほとんど同じように見えます。しかし、LispのCLOSはHaskellタイプがカバーするいくつかのスペースをカバーしていますか?非常に厳密なHaskell型とオブジェクト指向言語でのオブジェクトの作成は、漠然と似ています。私がHaskellのクールエイドを飲んだだけで、Lispの道を進むと、動的なタイピングのために頭がおかしくなります。

回答:


6

CL型システムは、Haskellのシステムよりも表現力に優れて(or (integer 1 10) (integer 20 30))います1,2,...9,10,20,21,...,30。たとえば、値の型を持つことができます。

ただし、Lispコンパイラーは、タイプセーフについての理解を強制することはないので、自分のリスクで、それらの「メモ」を無視できます

つまり、すべての値の型を宣言し、必要なすべての型が推論されることを慎重に確認することで、Liskで(いわば)Haskellを記述できますが、そもそもHaskellを使用する方が簡単です。

基本的に、強力な静的型付けが必要な場合はHaskellまたはOCamlを使用し、強力な動的型付けが必要な場合はLispを使用します。弱い静的型付けが必要な場合はCを使用し、弱い動的型付けが必要な場合はPerl / Pythonを使用してください。それぞれの道には長所(と熱心)と短所(そして中傷者)があるので、あなたはそれらすべてを学ぶことから利益を得るでしょう。


19
「タイプセーフティを喉に押し付ける」などの用語を使用している人は、タイプセーフティとは何か、それがなぜ有用なのかを理解していません。
メイソンウィーラー

11
@MasonWheeler:単一のフレーズから抜本的な結論を出す人は、他の場合よりも頻繁に自分自身の間違いを見つけるでしょう。このように、例えば。
sds 2013

4
トピックは言語なので、「喉を下に」という用語は適切で適切なイメージです。
luser droog 2013

1
@KChaloux:例で明らかにしたように、私は「表現力豊か」を意味しました。
sds 2013年

4
あなたはそれをすべて逆に持っています。動的型付けは静的型付けの特殊なケースであり、プログラマーはすべてに対して1つの型を使用する必要があります。ほとんどの静的型付き言語では、すべての変数を型として宣言するObjectか、型ツリーのルートが何であれ、同じことを(冗長に)行うことができます。これは、より少ないあなたがしているので、表情豊か奪わオプション特定の変数は特定の値のみを含めることができるというの。
ドヴァル2014

5

型付きラケットはHaskellとは大きく異なります。LispとSchemeの型システム、そして伝統的に型なし言語エコシステムの実際の型システムは、一般に、他の型システムが既存の型なしコードと相互運用しないという基本的な目標を持っています。たとえば、型付きラケットは、さまざまなラケットイディオムに対応するために、まったく新しい型規則を導入しました。この関数を考えてみましょう:

(define (first some-list)
  (if (empty? some-list)
      #f
      (car some-list)))

空でないリストの場合、これは最初の要素を返します。空のリストの場合、これはfalseを返します。これは、型なし言語では一般的です。型付き言語は、ラッパー型を使用するかMaybe、空の場合にエラーをスローします。この関数にタイプを追加したい場合、どのタイプを使用する必要がありますか?[a] -> afalseを返す可能性があるため、(Haskell表記では)そうではありません。また[a] -> Either a Boolean、(1)空の場合は常にfalseを返します。任意のブール値ではなく、(2)Eitherタイプは要素をラップしLeftてfalseにRightするため、実際の要素に到達するには「どちらかをアンラップする」必要があります。代わりに、値は真のユニオンを返します-ラッピングコンストラクターはありません。単に1つの型を返す場合と、別の場合を返す場合があります。型付きラケットでは、これは共用体型コンストラクターで表されます。

(: first (All (A) (-> (Listof A) (U A #f))))
(define (first some-list)
  (if (empty? some-list)
      #f
      (car some-list)))

この型(U A #f)は、関数がリストの要素を返すか、Eitherインスタンスをラップせずにfalseを返す可能性があることを示しています。型チェッカーはsome-list、型(Pair A (Listof A))または空のリストのいずれかであると推測できます。さらに、ifステートメントの2つの分岐で、どちらがそうであるかがわかっていると推測します。型チェッカーは、if条件がそれを保証するため、(car some-list)式では、リストに型が必要であることを認識して(Pair A (Listof A))います。これは出現タイピングと呼ばれ、型なしコードから型付きコードへの移行を容易にするように設計されています。

問題は移行です。型付けされていないラケットのコードはたくさんあります。型付けされたラケットは、お気に入りの型なしライブラリをすべて放棄して、コードベースに型を追加するために1か月を費やすことを強制することはできません。この問題は、既存のコードベースに徐々に型を追加する場合に常に当てはまります。これらのアイデアのJavaScriptアプリケーションについては、TypeScriptとそのAny型を参照してください。

段階的型システムは、一般的な型なしイディオムを処理し、既存の型なしコードと対話するためのツールを提供する必要があります。そうでなければ、それを使用するのは非常に苦痛です。Clojureの例については、「なぜCore.typedを使用しないのか」を参照してください。


1
経済学では、これはとして知られているグレシャムの法則良いアウト悪貨ドライブ。 それはエンジニアリングにも応用を見つける傾向があります。ここに見られるように、システム内に2つの理論的に同等のサブシステムがある場合、悪いものはあまりにも多くの問題を引き起こし、優れたものを使用する価値があります。
メイソンウィーラー

「型システムの設計例」:この文は完全ではありません
コアダンプ

@MasonWheelerもっと悪いのは、動的型チェックです。あなたがそれを導入したらすぐに、静的分析を実行する価値はありませんか?
コアダンプ2016年

1
@coredump-型付けされていないコードとのやり取りが不十分でない限り、段階的な型付けは価値があります。たとえば、TypeScriptのAny型はタイプチェッカーにあきらめるように指示するだけであり、静的にチェックされた大量のコードを通じて悪い値が伝播する可能性があるため、基本的に型システムの利点を捨てます。型付きラケットは、コントラクトとモジュール境界を使用してこの問題を回避します。
ジャック

1
@coredump Clojureの記事を読んでください。特に静的型を使用できないサードパーティのコードのすべてで動的型付けを行うと、静的型でコードベースを改善しようとする試みが本当に失敗しました。
メイソンウィーラー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.