2016-06-27 10 views
3

私はyou can add constraints on associated type families and data familiesを認識しています。これが行うことは、あなたのクラスのインスタンスすべてに制約を適用することです。関連する型ファミリを使用するときの型のクラス制約を推測する

しかし、私はこれらの制約をどのように推論するのかを把握することはできませんインスタンスの導出または関数の宣言。たとえば、このコードはチェックを入力して失敗します。

{-# LANGUAGE FlexibleContexts #-} 
{-# LANGUAGE TypeFamilies #-} 

import Data.Proxy (Proxy) 

class Eq (FooT a) => Foo a where 
    type FooT a :: * 

-- Can't infer it in an instance derivation 
data CantInferEq a = CantInferEq (FooT a) deriving Eq 

-- Also can't infer it in a function declaration. 
-- The Proxy is there to avoid non-injectivity issues. 
cantInferEq :: Proxy a -> FooT a -> FooT a -> Bool 
cantInferEq _ x y = x == y 

エラーメッセージは以下のとおりです。

Test.hs:11:52: No instance for (Eq (FooT a)) … 
     arising from the first field of ‘CantInferEq’ (type ‘FooT a’) 
    Possible fix: 
     use a standalone 'deriving instance' declaration, 
     so you can specify the instance context yourself 
    When deriving the instance for (Eq (CantInferEq a)) 

Test.hs:16:23: No instance for (Eq (FooT a)) arising from a use of ‘==’ … 
    In the expression: x == y 
    In an equation for ‘cantInferEq’: cantInferEq _ x y = x == y 

Compilation failed. 

ここで何が起こっていますか?希望の動作を得るための回避策はありますか?

答えて

5

問題の要点は、ちょうどFooT aの場合、Eqインスタンス辞書を取得できません。

この問題を回避するには、それによってEq辞書が渡された所を有する、あなたの型クラスの必要条件で明示的になることです。

{-# LANGUAGE StandaloneDeriving, UndecidableInstances #-} 

data CantInferEq a = CantInferEq (FooT a)  
deriving instance (Eq (FooT a)) => Eq (CantInferEq a) 

cantInferEq :: (Eq (FooT a)) => Proxy a -> FooT a -> FooT a -> Bool 
cantInferEq _ x y = x == y 

それともCantInferEqEq (FooT a)辞書をパッケージングすることによりUndecidableInstancesを使用することを避けることができますコンストラクタ:

{-# LANGUAGE GADTs, StandaloneDeriving #-} 
data CantInferEq a where 
    CantInferEq :: (Eq (FooT a)) => FooT a -> CantInferEq a 
deriving instance Eq (CantInferEq a) 
関連する問題