gpt4 book ai didi

haskell - 包含带有 gdiff 的列表的对象的通用差异

转载 作者:行者123 更新时间:2023-12-01 03:26:38 25 4
gpt4 key购买 nike

我正在尝试使用 gdiff 1.1 是 Haskell 的通用 diff 库,用于获取恰好包含列表的两个对象之间的差异。但是,我无法让它工作,我认为这是因为我不知道如何定义 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")]

此代码在 GHC 8.0.1 下编译时没有警告,带有 -Wall选项。当我运行此代码时,我希望它显示 a 之间的差异和 b ,但它显示了这个输出:
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

如果重要,我使用 Haskell2010 语言和这些扩展:GADTs、LambdaCase、MultiParamTypeClasses、OverloadedStrings、FlexibleInstances。

我该如何解决这个错误?

最佳答案

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]

关于haskell - 包含带有 gdiff 的列表的对象的通用差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41031207/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com