Haskellファンクターのターゲットカテゴリーに派生型のみがあるのはなぜですか?


12

Haskellでは、Functorタイプクラスファンクターは次のように定義されます(Haskell wikiなどを参照)。

class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b 

これまで(私が間違っているなら、私を修正してください)私は理解したように、このようなファンクタは唯一のカテゴリは型コンストラクタを使用して構築され、例えば、対象カテゴリとして持つことができるよう[]Maybe一方、など、1は任意のカテゴリを持つファンクタを考えることファンクターのターゲットとして、すべてのHaskellタイプのカテゴリーなど。たとえば、またはIntだけでなく、ファンクターのターゲットカテゴリのオブジェクトになります。Maybe Int[Int]

Haskellファンクターに対するこの制限の動機は何ですか?


4
シンプル?Haskellにはファーストクラス型の関数がないため、すべての関数は実際には単なる型コンストラクターです。
ダニエル・グラッツァー14

2
@jozefg:私の無知を許してください:「ファーストクラス型関数」とは何ですか?
ジョルジオ14

4
それで、その機能では、私たちはf権利を投げ回していますか?そして、あなたのシナリオでfは、通常のHaskell関数のように、型を型にマップする必要があります。Haskellでは、種類を持つことができるの* -> *は型コンストラクタのみです。タイプファミリはより一般的ですが、常に完全に適用する必要があります
ダニエルグラッツァー14


@jozefg:私は時折この質問について何度も考えます。Haskellの制限はファンクターの表現力には影響しないと思います。たとえば、リストファンクターと同型であるが、たとえばInt-> [Int]ではなくInt-> <型コンストラクターを使用しない派手な型>をマップしないファンクターがあるとします。次に、<型コンストラクタを使用しない派手な型>が[Int]と同型であることを証明できると思います。したがって、型コンストラクターを使用して定義されたオブジェクトを選択することは便利であり、表現力を犠牲にしません。
ジョルジオ

回答:


1

制限はありません!型コンストラクタのカテゴリ理論の基礎を学び始めたとき、この点も私を混乱させました。それに行きます。しかし、最初に、混乱を解消させてください。これらの2つの引用符:

そのようなファンクターは、タイプコンストラクターを使用して構築されたカテゴリをターゲットカテゴリとしてのみ持つことができます

そして

ファンクターは、すべてのHaskellタイプのカテゴリーなど、任意のカテゴリーをファンクターのターゲットとして考えることができます。

ファンクタとは何かを誤解していることを示します(少なくとも、用語を誤用している)。

ファンクターはカテゴリーを構築しません。ファンクターは、カテゴリーのマッピングです。ファンクターは、ソースカテゴリのオブジェクトと射(型と関数)をターゲットカテゴリのオブジェクトと射にもたらします。

これは、ファンクターが実際にはマッピングのペアであることに注意してください:オブジェクトF_objのマッピングと射F_morphのマッピング。Haskellでは、ファンクターのオブジェクト部分F_objは型コンストラクターの名前(例:)Listあり、モーフィズム部分は関数ですfmapfmap指定された式で参照しているものを選別するのはHaskellコンパイラ次第です)。したがって、それがListファンクターであると言うことはできません。のみの組み合わせListfmapファンクタです。それでも、人々は表記法を乱用しています。プログラマーListはファンクターを呼び出しますが、カテゴリー理論家はファンクターの両方の部分を参照するために同じ記号を使用します。

さらに、プログラミングでは、ほぼすべてのファンクターがエンドファンクターです。つまり、ソースとターゲットのカテゴリーは同じです。つまり、言語のすべてのタイプのカテゴリーです。このカテゴリをTypeと呼びましょう。タイプの内積関数Fは、タイプTを別のタイプFTにマップし、関数T-> Sを別の関数FT-> FSにマップします。もちろん、このマッピングはファンクターの法則に従う必要があります。

List例として使用すると、一緒にファンクターを形成する型コンストラクターList : Type -> Typeと関数がfmap: (a -> b) -> (List a -> List b)あります。T

解決すべき最後のポイントが1つあります。書き込みList intは、整数のリストの新しいタイプを作成しません。このタイプはすでに存在していました。これは、カテゴリTypeのオブジェクトでした。List Int単にそれを参照する方法です。

さて、なぜファンクターは型を、たとえば、Intまたはにマッピングできないのか疑問に思っていますString。しかし、できます!アイデンティティファンクタを使用する必要があります。任意のカテゴリCに対して、アイデンティティファンクターはすべてのオブジェクトをそれ自体に、射を自身にマッピングします。このマッピングがファンクターの法則を満たしていることを検証するのは簡単です。Haskellでは、これはid : * -> *すべてのタイプをそれ自体にマップするタイプコンストラクターになります。たとえば、とid int評価されintます。

さらに、すべての型を単一の型にマップする定数ファンクターを作成することもできます。たとえば、functor ToInt : * -> *、ここToInt a = intですべての型a、およびすべての射を整数恒等関数にマッピングします: fmap f = \x -> x


回答ありがとうございます。この質問は2年以上前のものです。「ファンクターはカテゴリーを構築しません。」:私はそれを言わなかった。私はファンクタは、目標カテゴリがフォーム持たなければならない2つのカテゴリー、マップと述べf af、私の知る限り、型コンストラクタです。カテゴリ理論から私が覚えていることから、これはある種の正準表現でなければなりません(カテゴリのカテゴリ内の最初のオブジェクト?多分、用語を誤用しています)。とにかく、私はあなたの答えを注意深く読みます。どうもありがとう。
ジョルジオ

@Giorgioおっと、それが何歳だったのか気づかなかった。「未回答の質問」に表示されました。「正規表現」とはどういう意味かわかりません。私の知る限り(そして、ここで間違っている可能性があります)、ファンクターと初期/終端オブジェクトの間に関係はありません。
ガーデンヘッド

つまり、en.wikipedia.org / wiki / Initial_algebra(コンピューターサイエンスでの使用を参照)です。Haskellでは(ほとんどの)ファンクターは代数データ型で定義されています。このようなファンクターのターゲットオブジェクトは初期代数です。初期代数は、値コンストラクターを使用して構築された用語のセットと同型です。たとえば、リスト、[]および:。これは標準的な表現によって意味されました。
ジョルジオ

ええ、私は初期オブジェクトが何であるかを知っています、そして帰納的データ型はカテゴリーのF代数の初期オブジェクトです。多くの型コンストラクタが帰納的に定義されているのは正しいです。しかし、これは厳密には必要ありません。たとえば(_, int)、型aを製品型(a, int)に、関数f : 'a -> 'bを型にするファンクターg : 'a * int -> 'a * intは帰納的ではありません。
ガーデンヘッド

もしかして:「...に機能f : 'a -> 'bを取りますg : 'a * int -> 'b * intか?
ジョルジオ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.