IDFunctorがうまく機能する簡単な例を次に示します。
newtype R a = R a
instance Functor R where
fmap f (R a) = R $ f a
しかし、中間型族を追加すると、物事が不安定になります。
data IntT
data a :-> b
type family Sem a :: *
type instance Sem IntT = Int
type instance Sem (a :-> b) = Sem a -> Sem b
newtype S a = S (Sem a)
そして今、私はSをファンクターにすることができません。ファンクターのようなものの新しいクラスを簡単に定義できますが、アプリケーションのようなものとモナドのようなもののクラスも必要になり、それは不幸な道のように思えます。特にとして
smap f (S a) = S $ f a
実際に私が望むタイプ、すなわちsmap :: (Sem a -> Sem b) -> S a -> S b
。しかし、もちろん、これはファンクターのタイプではありません。(「同じ」コードに2つの異なる互換性のないタイプがある場合、それを嫌いではありませんか?)
Data.Category.FunctorとGenerics.Pointless.Functorsを調べましたが、どちらも私の問題を完全に解決しているようには見えませんでした。 PointlessTypeFamiliesにはさらに良いアイデアがあるように見えましたが、それでも、これからファンクターのようなものを十分に引き出す方法がわかりません。
のコードはforのコードと同じですが、何が起こっているのかが少し異なることに気づきました。ある意味で、からへの自然変換があった場合、どういうわけかそれを持ち上げて取得できるはずです。その時点で、私はここで尋ねたほうがいいと思いました。それは私にかなりのトラブルを救うかもしれません!smap
fmap
R
Sem
S
smap