-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Patching an isomorphic structure #10
Comments
@schell you might get inspirations from my slides http://bobkonf.de/2015/slides/greif.pdf |
@ggreif thank you! This looks great. I'll let you know if I have questions. Is that okay? |
@schell yea, sure, keep asking! |
👍 |
I'm definitely interested in the polymorphic containers addition - is that available now? Are there any examples you have of using located values? I'm a little confused about calling diff on an (IO Configtree) - how can diff compare IO actions? |
@schell regarding data Fam t ts where
Just' :: Fam el elts -> Fam (Maybe el) elts
Nothing' :: Fam (Maybe el) CNil Writing the |
Thank you! And yes, please start the wiki, that would be very helpful. |
@schell I have written https://github.com/eelco/gdiff/wiki/PolymorphicContainers. For now it explains |
Thank you :) |
@ggreif I think I've come up with another way of doing polymorphic containers without data ListFam a t ts where
Nil' :: ListFam a [a] Nil
Cons' :: ListFam a a Nil -> ListFam a [a] (a `Cons` [a] `Cons` Nil)
Val' :: a -> ListFam a a Nil
instance (Eq a, Show a) => Family (ListFam a) where
decEq (Cons' a) (Cons' a') = do (Refl, Refl) <- decEq a a'; Just (Refl, Refl)
decEq Nil' Nil' = Just (Refl, Refl)
decEq (Val' a) (Val' a') | a == a' = Just (Refl, Refl)
| otherwise = Nothing
decEq _ _ = Nothing
fields (Cons' _) (a:as) = Just (a `CCons` as `CCons` CNil)
fields Nil' [] = Just CNil
fields (Val' _) _ = Just CNil
fields _ _ = Nothing
apply (Cons' _) (a `CCons` as `CCons` CNil) = a : as
apply Nil' CNil = []
apply (Val' a) CNil = a
string (Cons' _) = "Cons"
string (Val' a) = show a
string Nil' = "Nil"
instance (Eq a, Show a) => Type (ListFam a) a where
constructors = [Abstr Val']
instance (Eq a, Show a) => Type (ListFam a) [a] where
constructors = [ Concr Nil', Abstr $ \(x : _) -> Cons' $ Val' x ] After that it's business as usual as far as I can tell. fmapEditList f (Ins (Val' a) es) = Ins (Val' $ f a) (fmapEditList f es)
fmapEditList f (Cpy (Val' a) es) = Cpy (Val' $ f a) (fmapEditList f es)
fmapEditList f (Del (Val' a) es) = Del (Val' $ f a) (fmapEditList f es)
fmapEditList f (CpyTree es) = CpyTree $ fmapEditList f es But it isn't! Thoughts? |
I guess since the types in the AST can be heterogeneous, a transformation may not be possible. I'm not sure... |
@schell I think what is tripping you over are the List (ListFam b) (b `Cons` [b] `Cons` Nil) on your |
Hi @schell, I am trying to do exactly the same thing. Did you have any success patching the isomorphic structure, or even just defining |
@rvl - no! Sorry! tldr; I gave up on this approach and switched to an entirely different strategy. I was building a tree of datatypes that represent graphical elements in a scene, and then attempting to use gdiff to create an edit script to apply to an isomorphic tree of renderers that would render the 'elements' to the screen. My new strategy is to write Hashable instances for all elements and hold them in a flat list with a transformation and hold the renderers in a map keyed by the elements' hashes. When an element is updated its hash changes and its previous renderer can be removed from the map (and dealloc'd). The strategy is less elegant but also less 'deep'. I hope you figure it out! |
Thanks for your help @schell. I am diffing something like Text.XML.HXT.DOM.TypeDefs.XmlTrees and want to apply the edit script to an actual DOM. If possible I will persist with this strategy. My plan is to parse the edit script with Parsec to produce a list of DOM operations. For this, I need a function similar to import Text.Parsec.Prim
type XmlDiff = EditScript XmlTreeFamily XmlTree XmlTree
instance Monad m => Stream XmlDiff m XmlDiff where
uncons = return . diffUncons
diffUncons :: XmlDiff -> Maybe (XmlDiff, XmlDiff)
diffUncons x@(Ins _ d) = Just (x, diffUncons d)
diffUncons x@(Del _ d) = Just (x, diffUncons d)
diffUncons x@(Cpy _ d) = Just (x, diffUncons d)
diffUncons x@(CpyTree d) = Just (x, diffUncons d)
diffUncons End = Nothing The problem is that the type of the |
@rvl What about setting up a small concrete example of what you want to accomplish (as a gist with MIT license) and give me perms? Then I can give it a try. I spent a few months of my life gdiff-whispering all kinds of GADTs, so there is a fair chance that I can help you. |
Hi @ggreif, thanks for your generous offer. I have put the essence of my plan and some context in a standalone script: PatchDom.hs. |
Cool. I doubt you'll get far with the "parse . show" approach. I'll try the Em sábado, 9 de janeiro de 2016, Rodney Lorrimar [email protected]
|
Has anyone had any luck with this? I'm revisiting with a new project and am now in need of the ability to patch a separate structure. I think this would be the defacto operation in this library. It seems to me that |
I have a remote data structure that is isomorphic to the local structure I'm diff'ing and I'd like to use the edit script to patch the remote structure (in an effect-full way). @eelco - in your paper you describe the edit script referring to an internal stack that pushes and pops subtrees from the source and target tree. Is there any more information about that process you could provide me?
The text was updated successfully, but these errors were encountered: