Scala の高階型とは何ですか? 質問する

Scala の高階型とは何ですか? 質問する

ウェブ上では以下が見つかります:

  1. 高次の型 == 型コンストラクタ?

    class AClass[T]{...} // For example, class List[T]
    

    定義に準拠する型を抽象化するため、これはより高次の型であると考える人もいます。

    高次の型とは、他の型を取って新しい型を構築する型である。

    これらは型コンストラクタとも呼ばれます。(例えば、Scalaでのプログラミング)。

  2. 高次の型 == 型コンストラクタを型パラメータとして受け取る型コンストラクタですか?

    論文ではより高次のジェネリック、 あなたは読むことができます

    ... 型を抽象化する型 (「高次の型」) を抽象化する型 ..."

    これは、

    class XClass[M[T]]{...} // or
    
    trait YTrait[N[_]]{...} // e.g. trait Functor[F[_]]
    

    より高次の種類です。

したがって、これを念頭に置くと、型コンストラクタより高次の型、および型コンストラクタを型パラメータとして受け取る型コンストラクタを区別することが困難であり、そのため上記の質問が生じます。

ベストアンサー1

この混乱の原因となったことを埋め合わせるために、少し説明を加えたいと思います。私は、人々がより馴染みやすい傾向があるため、価値レベルとの類似性を使ってこれを説明するのが好きです。

型コンストラクタは、型引数に適用して型を「構築」できる型です。

値コンストラクターは、値引数に適用して値を「構築」できる値です。

値コンストラクタは通常、「関数」または「メソッド」と呼ばれます。これらの「コンストラクタ」は、「ポリモーフィック」(さまざまな「形状」の「もの」を構築するために使用できるため)、または「抽象化」(さまざまなポリモーフィックなインスタンス化間で異なるものを抽象化するため) とも呼ばれます。

抽象化/ポリモーフィズムのコンテキストでは、第一階は抽象化の「単一使用」を指します。つまり、型を一度抽象化しますが、その型自体は何も抽象化できません。Java 5 ジェネリックは第一階です。

上記の抽象化の特徴の第一階の解釈は次のとおりです。

型コンストラクタは、適切な型引数に適用して適切な型を「構築」できる型です。

値コンストラクターは、適切な値引数に適用して適切な値を「構築」できる値です。

1値や型などの抽象化が含まれていないことを強調するために (これを「ゼロ次」と呼ぶこともできると思いますが、これが使用されているのを私はどこでも見たことがありません)、String通常、何かが「適切な」値または型であると言います。

適切な値は、引数を待たない(引数を抽象化しない)という意味で「すぐに使用可能」です。簡単に印刷/検査できる値と考えてください(関数をシリアル化するのは不正行為です)。

適切な型とは、値を分類する型 (値コンストラクタを含む) のことです。型コンストラクタは値を分類しません (適切な型を生成するには、まず適切な型引数に適用する必要があります)。型をインスタンス化するには、適切な型であることが必要です (ただし、それだけでは十分ではありません)。(抽象クラスや、アクセスできないクラスの場合もあります。)

「高階」とは、単にポリモーフィズム/抽象化の繰り返し使用を意味する一般的な用語です。ポリモーフィックな型と値の場合も同じ意味です。具体的には、高階抽象化は何かを抽象化する何かを抽象化します。型の場合、「高階」という用語は、より一般的な「高階」の特殊目的バージョンです。

したがって、私たちの特徴付けの高次バージョンは次のようになります。

型コンストラクタは、型引数 (適切な型または型コンストラクタ) に適用して適切な型 (コンストラクタ) を「構築」できる型です。

値コンストラクターは、値引数 (適切な値または値コンストラクター) に適用して適切な値 (コンストラクター) を「構築」できる値です。

したがって、「高階」とは、単に「X を抽象化する」と言ったときに、本当にそれを意味していることを意味します。X抽象化された X は、自身の「抽象化権」を失うことはありません。つまり、必要なだけ抽象化できます。(ちなみに、ここで「抽象化」という動詞を使用するのは、値または型の定義に必須ではないものを省略し、抽象化のユーザーが引数として変更/提供できるようにすることを意味します。)

以下に、適切な、第一階および高階の値と型の例をいくつか示します (Lutz の電子メールでの質問に触発されたものです)。

                   proper    first-order           higher-order

values             10        (x: Int) => x         (f: (Int => Int)) => f(10)
types (classes)    String    List                  Functor
types              String    ({type λ[x] = x})#λ   ({type λ[F[x]] = F[String]})#λ

使用されるクラスは次のように定義されています。

class String
class List[T]
class Functor[F[_]]

クラス定義による間接参照を避けるには、Scalaでは直接表現できない匿名型関数を何らかの方法で表現する必要がありますが、構造型を使用すれば構文上のオーバーヘッドをあまりかけずに済みます(-stylehttps://stackoverflow.com/users/160378/retronym私の知る限り):

匿名型関数をサポートする Scala の将来のバージョンでは、例の最後の行を次のように短縮できます。

types (informally) String    [x] => x              [F[x]] => F[String]) // I repeat, this is not valid Scala, and might never be

(個人的には、「高次の型」について話したことを後悔しています。結局のところ、それらは単なる型です。 明確に区別する必要がある場合は、「型コンストラクタ パラメータ」、「型コンストラクタ メンバー」、または「型コンストラクタ エイリアス」などと言うことをお勧めします。これにより、適切な型について話しているのではないことを強調できます。)

追記: 事態をさらに複雑にしているのは、「多態的」という言葉が別の意味で曖昧であるということです。多態的型は、Forall T, T => T多態的値を分類するため適切な型である などの普遍量化型を意味することがあるからです (Scala では、この値は構造型 として記述できます{def apply[T](x: T): T = x})。

おすすめ記事