2013-04-17 11 views
10

複数パラメータ型の同義語のクラスインスタンスを定義することが可能かどうか(そしてその方法)を理解しようとしています。例えば複数パラメータ型同義語インスタンス

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-} 

type F a b = a -> b 
data DF a b = DF (a -> b) 

class C c a b where 
    doc :: c a b -> a -> b 

それはマルチのparam型インスタンスのために働く:

instance C DF a b where 
    doc (DF f) x = f x 
しかし、それは型シノニムには機能しません:

-- ERROR: 
-- 
-- Type synonym `F' should have 2 arguments, but has been given none 
-- In the instance declaration for `C F a b' 
-- 
instance C F a b where 
    doc f x = f x 

がそれですFの型クラスインスタンスを定義することは可能ですか?

答えて

14

書いたとおりのことはできません。タイプ同義語は、一般的にそれらを使用するために完全に適用されなければならず、特にas a type class parameterです。

タイプシノニムを十分に減らすことができれば、インスタンスが可能であることに注意してください。それはそれが指すタイプではなく、完全に適用されなければならない同義語です。だから、これは動作します:

type F = (->) 

instance C F a b where 
    doc f x = f x 

が型シノニムを展開する程度a LiberalTypeSynonyms extension that relaxes some of the rulesがあるが、それはここで助けにはならない - それはあなたが別の型の型パラメータとして、部分的に適用されるタイプの同義語を与えるようなことを行うことができますシノニム。そうでなければ、すべてをまだ完全に拡張して使用する必要があります。

type Flip f a b = f b a 

そして、次のインスタンス::も同じことをインスタンスFunctor (Either a)があること

instance Functor (Flip Either a) where 
    fmap _ (Right x) = Right x 
    fmap f (Left x) = Left (f x) 

リコールこの制限が必要な理由

一つの理由を確認するには、次のタイプの同義語を考えますミラーを除いて。どちらも意味をなさないFunctorインスタンスです。

newtypeとは異なり、タイプ同義語は参照するタイプと同じであるとみなされます。式fmap not (Right True :: Either Bool Bool)の値はどのようにする必要がありますか?

3

タイプのシノニムを完全に適用して、インスタンスを定義できるようにする必要があります。 Fの種類は* -> * -> *ではありませんが、2つ以上の型引数が指定されるまで無効です。代わりに

type F = (->) 

を試してください。

関連する問題