制限はありません!型コンストラクタのカテゴリ理論の基礎を学び始めたとき、この点も私を混乱させました。それに行きます。しかし、最初に、混乱を解消させてください。これらの2つの引用符:
そのようなファンクターは、タイプコンストラクターを使用して構築されたカテゴリをターゲットカテゴリとしてのみ持つことができます
そして
ファンクターは、すべてのHaskellタイプのカテゴリーなど、任意のカテゴリーをファンクターのターゲットとして考えることができます。
ファンクタとは何かを誤解していることを示します(少なくとも、用語を誤用している)。
ファンクターはカテゴリーを構築しません。ファンクターは、カテゴリー間のマッピングです。ファンクターは、ソースカテゴリのオブジェクトと射(型と関数)をターゲットカテゴリのオブジェクトと射にもたらします。
これは、ファンクターが実際にはマッピングのペアであることに注意してください:オブジェクトF_objのマッピングと射F_morphのマッピング。Haskellでは、ファンクターのオブジェクト部分F_objは型コンストラクターの名前(例:)でList
あり、モーフィズム部分は関数ですfmap
(fmap
指定された式で参照しているものを選別するのはHaskellコンパイラ次第です)。したがって、それがList
ファンクターであると言うことはできません。のみの組み合わせList
とfmap
ファンクタです。それでも、人々は表記法を乱用しています。プログラマー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