2016-03-28 16 views
3

悪いタイトルについて申し訳ありません。問題のあるデータ型がありますが、これはファンクタのインスタンスとして定義しようとしています。ハスケル:このデータ型のファンクタ?

だから基本的に、私が持っているもの

sample_logp :: s a -> a 

を持っているものであり、そしてそれは

sample_logp :: s b -> b 

(a -> b) 

を使用して変換する必要があります。次のコードはこれを達成していません。

sample_logp :: s a -> b 

でのみ成功します。

data Model s a = Model { 
    sample_logp :: s a -> a 
} 

instance Functor (Model s) where 
    fmap f m = Model { 
    sample_logp = sample_logp' 
    } where sample_logp' x = (f . (sample_logp m)) x 

私も可能なことは何ですか?もしそうなら、これを達成するためにこのコードをどのように更新できますか?

+8

ファンクタにすることはできません。「a」は共変および反変の両方の位置にあります。 – zakyggaps

+0

ありがとうございました!その場合、これを実現する他の型クラスがありますか? – tero

+3

あなたは[Profunctor](http://hackage.haskell.org/package/profunctors-5.2/docs/Data-Profunctor.html)にチェックを入れることができますが、デザインの選択は 's'が何であるかによって大きく異なります。 – zakyggaps

答えて

9

ここでの標準的なアプローチは、より多くの型変数を追加することです。

data Model s a b = Model { 
    sample_logp :: s a -> b 
} 

タイプ変数を分割すると、より多くのツールにアクセスできます。ここではProfunctorクラスが適切です。 (私はこのシステムでGHCを持っていないので、型検査はありません - 。コメントや私の実装がオフになっている場合は、単にそれを修正)

instance (Functor s) => Profunctor (Model s) where 
    dimap f g (Model h) = Model $ g . h . fmap f 
    lmap f (Model h) = Model $ h . fmap f 
    rmap g (Model h) = Model $ g . h 

さて、あなたはModel s a aを持っていることを考えると、あなたのModel s aの等価です、 dimap bToA aToBを使用してModel s b bに変換できます。

コメントで言うように、元のデータ型は正と負の位置で同じ型変数を使用するため不変です。これは、変換関数を各方向に供給する必要があることを意味します。余分なタイプ変数を追加すると、既存のツール(例えばProfunctor)を活用できます。


上記のすべてがあなたがsのための共変の型を使用しているという仮定に基づいていることに注意してください。 sが反反例である場合、chiのコメントには、元のタイプの直接のFunctorインスタンスを書くことができます。しかしそれははるかに一般的ではない状況です。

関連する問題