したがって、f
とg
が適切な関手でforall a. f a -> g a
あると仮定すると、自然な変換になります。もう少しきれいにすることができます:
type f ~> g = forall a. f a -> g a
このような自然な変換により、Haskell Functor のカテゴリを形成できます。そのため、そこから他のカテゴリへの Functor が得られます。
通常の Haskell Functor の手順に従ってx
、Functor を他の Functor にマッピングする endfunctor を持つことはおそらく理にかなっているでしょう。これはあなたが持っているものと似ていますが、同一ではありません:
class FFunctor x where
ffmap :: (f ~> g) -> (x f ~> x g)
ただし、あなたの場合x f
、 andx g
はファンクターでx f -> x g
はなく、自然な変換ではなく通常の関数です。それでも、パターンは興味をそそるほど十分に近いです。
これを念頭に置いて、これx
はまだ 2 つの異なるカテゴリの間のちょうどファンクタの例のようです。Functor のカテゴリから、x
さまざまな構造を持つ s のカテゴリに移動します。x
のような可能な各は、 と のようFoo
なオブジェクトFoo []
とFoo Maybe
、それらの間の変換 ( Foo [] -> Foo Maybe
) を含むカテゴリを形成します。通常の ( ) 関数をファンクター ( ) のイメージの関数に「リフト」するのと同じように、関数はinterleaveHomomorphism
自然な変換をこれらのに「リフト」します。x-morphisms
fmap
a -> b
f a -> f b
そうです: あなたの型クラスは、Functor
2 つの異なるカテゴリの間を除いて、 と同じようにファンクターです。主に のような構造の特定の名前がわからないため、特定の名前はわかりませんx
。
より一般的に言えば、特定の名前が意味を成すかどうかさえわかりません。この時点で、おそらく、任意の 2 つのカテゴリ間を行き来する優れたジェネリック ファンクター型クラスが必要になります。たぶん次のようなもの:
class (Category catA, Category catB) => GFunctor f catA catB where
gfmap :: catA a b -> catB (f a) (f b)
これはおそらくどこかのライブラリに既に存在します。
(->)
残念ながら、異なるファンクターを定義するこの特定のアプローチは、すでにカテゴリであるため、余分な newtype ノイズの束を必要とします。実際、すべてのタイプを適切に並べるのは少し面倒です。
したがって、それを anXFunctor
または something と呼ぶのがおそらく最も簡単です。さらに、しゃれの可能性を想像してみてください。
編集:このようなタイプをcategories
提供するように見えますCFunctor
が、少し賢いです:
class (Category r, Category s) => CFunctor f r s | f r -> s, f s -> r where
cmap :: r a b -> s (f a) (f b)
ただし、これでも一般的かどうかはわかりません。種類よりも多形性を高めたいと思うかもしれません。