2016-10-21 22 views
2

aとbの2つのパラメータを持つユーザー型を考えてみましょう。明らかに、これは、ユーザーが2つの異なる種類で構成することができます複数の型クラスを持つカスタムデータ型でファンクション/アプリケーションを使用しますか?

data Users a b = User a b deriving (Show, Eq, Ord) 

はどのように我々は、このインスタンスのファンクタと応用的に宣言することができますか?

私はこれらのアプローチはコンパイルされません試した:

instance Functor Users where 
    fmap f(User a b) = User (f a) (f b) 

instance Applicative Users where 
    pure a b = User a b 
    (<*>) User a b = (fmap a) (fmap b) 

これらはコンパイルされません理由は何ですか?

+1

は、のFunctorインスタンスは一種持っている必要があります種類の不整合があり、 '* - > *'あなた 'User'タイプは種類のものであるのに対し、' * - >:予想されるとして、(,)のためにそのインスタンスがあります* - > * '。あなたが望むのは[Profunctor](http://hackage.haskell.org/package/profunctors-5.2/docs/Data-Profunctor.html#t:Profunctor)です。 – baxbaxwalanuksiwe

+3

種類エラーだけでなく、定義に変数 'b'がないため、' pure'実装は機能しません。あなたは 'a - > User a b'という関数をどのように書くことができると思いますか? – Lee

+2

@baxbaxwalanuksiwe「Bifunctor」を意味しますか? – ThreeFx

答えて

5

両方の引数でfunctorialであるADTの型クラスについては、Data.Bifunctorを見てください。 Userはタプルの名前であり、すでにこのようなインスタンスをサポートしています。 bifunctorインスタンスを導出することはHaskellでも可能です。

@Bakuriuは、Usernewtypeと定義し、拡張子を使用してGeneralizedNewtypeDerivingと示唆しています。

第2のものについては、Biapplicativeを参照してください。

instance Biapplicative (,) where 
    pure = (,) 
    ap (f, g) (a, b) = (f a, g b) 
+1

'User'に' newtype'を使い、 'GeneralizedNewtypeDeriving'拡張を使うことで、おそらくペアのインスタンスを派生させることができます。 – Bakuriu