Generic diff objects that include lists with gdiff

I am trying to use gdiff 1.1, the general diff library for Haskell, to get the difference between two objects that contain a list. However, I can’t get it to work, and I think it’s because I don’t know how to determine the instance for . Here is the code that I still have: Type FooFamily[FooEnvVar]

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")]

This code compiles without warning in GHC 8.0.1 with the option -Wall. When I run this code, I would like it to show the differences between aand b, but instead it shows this output:

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

In case it matters, I use the Haskell2010 language with these extensions: GADT, LambdaCase, MultiParamTypeClasses, OverloadedStrings, FlexibleInstances.

?

+4
1

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]
+2

Source: https://habr.com/ru/post/1663189/


All Articles