web-dev-qa-db-ja.com

Scalaの上位の種類とは何ですか?

Webで以下を見つけることができます。

  1. より高い種類の型==型コンストラクタ?

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

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

    上位の種類は、他の型を取り、新しい型を構築する型です

    これらはtype constructorとも呼ばれます。 (たとえば、 Scalaでのプログラミング )。

  2. より高い種類のタイプ==タイプコンストラクタをタイプパラメータとして受け取るタイプコンストラクタ?

    論文では Generics of a Higher Kind で読むことができます

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

    それはそれを示唆しています

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

    上位の種類です。

したがって、これを念頭に置いて、型コンストラクタより高い種類の型、およびを区別することは困難です型コンストラクターを型パラメーターとして受け取る型コンストラクター、したがって上記の質問です。

256
Lutz

多少の曖昧さをなくしてピッチングすることで、この混乱のいくつかを開始することを補います。人々はそれに慣れる傾向があるので、私はこれを説明するために値レベルへの類推を使用するのが好きです。

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

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

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

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

上記の抽象化の特性化の1次解釈は次のとおりです。

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

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

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

適切な値は、引数を待機していないという意味で「即座に使用可能」です(引数を抽象化しません)。それらを簡単に印刷/検査できる値と考えてください(関数のシリアル化は不正です!)。

適切なタイプとは、値を分類するタイプ(値コンストラクターを含む)であり、タイプコンストラクターは値を分類しません(適切なタイプを得るために適切なタイプ引数に最初に適用する必要があります)。型をインスタンス化するには、適切な型である必要があります(十分ではありません)。 (抽象クラ​​ス、またはアクセスできないクラスの場合があります。)

「高次」とは、単に多型/抽象化を繰り返し使用することを意味する一般的な用語です。多態的な型と値についても同じことを意味します。具体的には、高次の抽象化は、何かを抽象化するものを抽象化します。型の場合、「高次」という用語は、より一般的な「高次」の専用バージョンです。

したがって、特性評価の高次バージョンは次のようになります。

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

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

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

以下に、適切な1次および高次の値とタイプのいくつかの例を示します(電子メールによる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で直接表現できない匿名型関数を何らかの形で表現する必要がありますが、構文オーバーヘッドをあまり使わずに構造型を使用できます(- styleの原因は- https://stackoverflow.com/users/160378/retronym afaik):

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

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

(個人的な注意として、私はこれまで「高種類の型」について話したことを後悔しています。それらは結局のところ型です!明確に区別する必要がある場合は、「型コンストラクタパラメータ」、「型コンストラクタメンバー」 、または「タイプコンストラクターエイリアス」。適切なタイプについてだけではないことを強調します。)

ps:問題をさらに複雑にするため、「多態的」とは異なる方法であいまいです。多態的な型は、多態的な値を分類するため、適切な型であるForall T, T => Tなどの普遍的に数量化された型を意味することがあるためです(Scalaで、この値は構造タイプ{def apply[T](x: T): T = x})として記述できます

260
Adriaan Moors

(この回答は、いくつかのグラフィカルな情報と歴史的な情報によって、アドリアーンムーアズの回答を装飾する試みです。)

より高い種類の型は、2.5以降のScalaの一部です。

  • その前のScalaでは、Javaのように、型コンストラクター(Javaの「ジェネリック」)を型コンストラクターの型パラメーターとして使用することを許可していませんでした。例えば.

     trait Monad [M[_]]
    

    不可能でした。

    Scala 2.5では、型システムは、より高いレベルで型を分類する機能によって拡張されていました(型コンストラクターポリモーフィズム)。これらの分類は種類として知られています。

    Type and kind realtion, **derived** from "Generics of a Higher Kind" ( 高次のジェネリック )から派生した画像

    その結果、そのタイプコンストラクター(例:List)は、タイプコンストラクターの型パラメーターの位置で他の型と同じように使用できるため、Scala 2.5以降、ファーストクラス型になりました。 (Scalaのファーストクラス値である関数に似ています)。

    より高い種類をサポートする型システムのコンテキストでは、適切な型IntList[Int]などの型とListや-などの1次型を区別できます。 より高い種類のタイプFunctorまたはMonad(タイプを抽象化するタイプ、タイプを抽象化するタイプ)など。

    反対側のJavaの型システムは種類をサポートしないため、「より高い種類」の型はありません。

    だから、これはサポートする型システムの背景に対して見なければなりません。

  • Scalaの場合、次のような型コンストラクタの例をよく見ます。

     trait Iterable[A, Container[_]]
    

    見出しが「上位の種類」、たとえばin 汎用プログラマ向けのスカラ、セクション4.

    多くの場合、ContainerIterableではなくより高い種類のタイプとして参照しますが、より正確なのは、

    Containerを、より高い種類(高階)の型コンストラクターのパラメーターとして使用する場合は、Iterableを使用します。

96
Lutz

インスタンスが値であるIntCharなどの通常のタイプの kind は、*です。 Maybeのような単項型コンストラクタの種類は* -> *です。 Eitherなどのバイナリ型コンストラクターには、( curried )kind * -> * -> *などがあります。 MaybeEitherなどの型は、型レベルの関数として表示できます。1つ以上の型を取り、型を返します。

関数は、orderが1より大きい場合、higher-orderです。 、順序は(非公式に)関数矢印の左側の入れ子の深さです:

  • 注文0:1 :: Int
  • 注文1:chr :: Int -> Char
  • 順序2:fix :: (a -> a) -> amap :: (a -> b) -> [a] -> [b]
  • 注文3:((A -> B) -> C) -> D
  • 注文4:(((A -> B) -> C) -> D) -> E

要するに、higher-kinded型は単なる型レベルの高階関数です。

  • 注文0:Int :: *
  • 注文1:Maybe :: * -> *
  • 次数2:Functor :: (* -> *) -> Constraint—高次:単項型コンストラクタを型クラス制約に変換します
71
Jon Purdy

私は言うだろう:より高い種類の型は型コンストラクタを抽象化する。例えば。考える

trait Functor [F[_]] {
   def map[A,B] (fn: A=>B)(fa: F[A]): F[B]
}

ここでFunctorは、「より高い種類のタイプ」です( 「Generics of a Higher Kind」論文 )。 List(適切な型のみを抽象化する)のような具象(「一次」)型コンストラクターではありません。すべての単項(「一次」)型コンストラクター(F[_]で示される)を抽象化します。

または、別の言い方をすれば、Javaには明確に型コンストラクター(例:List<T>)がありますが、それらを抽象化できない(たとえば、記述できない)ため、「より親切な型」はありません上記で定義されたFunctorインターフェイス-少なくとも 直接 ではありません。

「高次(型コンストラクター)ポリモーフィズム」という用語は、「より高い種類の型」をサポートするシステムを表すために使用されます。

31
Landei