2016-12-08 9 views
4

私は、リストを含む2つのオブジェクトの違いを得るために、Haskellの汎用diffライブラリであるgdiff 1.1を使用しようとしています。しかし、私はそれを働かせることができないと私は[FooEnvVar]Type FooFamilyのインスタンスを定義する方法がわからないためだと思う。gdiffのリストを含むオブジェクトの一般的なdiff

module Main where 

import Data.Generic.Diff 

data Foo = Foo { fooEnv :: [FooEnvVar] } 
    deriving (Show, Eq) 

data FooStr = FooStr String 
    deriving (Show, Eq, Ord) 

data FooEnvVar = FooEnvVar { fooEnvName :: FooStr } 
    deriving (Show, Eq, Ord) 

data FooFamily :: * -> * -> * where 
    FooF :: FooFamily Foo (Cons [FooEnvVar] Nil) 
    FooStrF :: FooFamily FooStr (Cons String Nil) 

instance Family FooFamily where 
    decEq FooF FooF = Just (Refl, Refl) 
    decEq FooStrF FooStrF = Just (Refl, Refl) 
    decEq _ _ = Nothing 
    fields FooF (Foo fe) = Just (CCons fe CNil) 
    fields FooStrF (FooStr str) = Just (CCons str CNil) 
    apply FooF (CCons fe CNil) = Foo fe 
    apply FooStrF (CCons str CNil) = FooStr str 
    string FooF = "FooF" 
    string FooStrF = "FooStrF" 

instance Type FooFamily Foo where 
    constructors = [Concr FooF] 

instance Type FooFamily [FooEnvVar] where 
    constructors = [] -- what should I put here? 

main :: IO() 
main = 
    putStrLn $ show ((diff a b) :: EditScript FooFamily Foo Foo) 
    where 
    a = Foo [FooEnvVar (FooStr "hello"), FooEnvVar (FooStr "world")] 
    b = Foo [FooEnvVar (FooStr "hi"), FooEnvVar (FooStr "world")] 

このコードは-Wallオプション付きのGHC 8.0.1の下で警告なしでコンパイルします。ここに私はこれまで持っているコードです。私はこのコードを実行すると、私はそれがabの違いを見せたいだろうが、その代わり、それは、この出力を示しています。場合

test_gdiff: Incorrect Family or Type instance. 
CallStack (from HasCallStack): 
    error, called at src/Data/Generic/Diff.hs:313:22 in gdiff-1.1-KTbM5AUQcBxD5ewDUGZ4O3:Data.Generic.Diff 

をそれが重要、私はこれらの拡張子を持つHas​​kell2010言語使用しています:GADTsを、 LambdaCase、MultiParamTypeClasses、オーバーロードされた文字列、FlexibleInstances。

このエラーを修正するにはどうすればよいですか?

答えて

2

gdiffのポリモーフィックリストは直接サポートされていません。

リストを使用するすべてのタイプについて、リストタイプとそのコンストラクタ([](:))をファミリの一部として扱う必要があります。

data FooFamily :: * -> * -> * where 
    FooF  :: FooFamily Foo   (Cons [FooEnvVar] Nil) 
    FooEnvVarF :: FooFamily FooEnvVar (Cons FooStr Nil) 
    FooStrF :: FooFamily FooStr  (Cons String Nil) 
    NilF  :: FooFamily [FooEnvVar] Nil 
    ConsF  :: FooFamily [FooEnvVar] (Cons FooEnvVar (Cons [FooEnvVar] Nil)) 
    String  :: String -> FooFamily String Nil 

instance Family FooFamily where 
    decEq FooF FooF = Just (Refl, Refl) 
    decEq FooEnvVarF FooEnvVarF = Just (Refl, Refl) 
    decEq FooStrF FooStrF = Just (Refl, Refl) 
    decEq NilF NilF = Just (Refl, Refl) 
    decEq ConsF ConsF = Just (Refl, Refl) 
    decEq (String x) (String y) 
    | x == y = Just (Refl, Refl) 
    | otherwise = Nothing 
    decEq _ _ = Nothing 

    fields FooF (Foo fe) = Just (CCons fe CNil) 
    fields FooEnvVarF (FooEnvVar ev) = Just (CCons ev CNil) 
    fields FooStrF (FooStr x) = Just (CCons x CNil) 
    fields NilF [] = Just CNil 
    fields ConsF (x : xs) = Just (CCons x (CCons xs CNil)) 
    fields (String _) _ = Just CNil 
    fields _ _ = Nothing 

    apply FooF (CCons fe CNil) = Foo fe 
    apply FooEnvVarF (CCons ev CNil) = FooEnvVar ev 
    apply FooStrF (CCons x CNil) = FooStr x 
    apply NilF CNil = [] 
    apply ConsF (CCons x (CCons xs CNil)) = x : xs 
    apply (String x) CNil = x 

    string FooF = "FooF" 
    string FooEnvVarF = "FooEnvVarF" 
    string FooStrF = "FooStrF" 
    string NilF = "[]" 
    string ConsF = "(:)" 
    string (String x) = show x 

instance Type FooFamily Foo where 
    constructors = [Concr FooF] 

instance Type FooFamily [FooEnvVar] where 
    constructors = [Concr NilF, Concr ConsF] 

instance Type FooFamily FooEnvVar where 
    constructors = [Concr FooEnvVarF] 

instance Type FooFamily FooStr where 
    constructors = [Concr FooStrF] 

instance Type FooFamily String where 
    constructors = [Abstr String] 

は、ここではあなたの例のために働くべきで宣言されています

関連する問題