Trees that Grow and constraints

At the moment the Trees that Grow implementation in GHC master makes use of massive constraint types to provide Data instances for the hsSyn AST. I am trying to remove the need for this, and have hit a problem. The example I have reduced it to is here [1] The essence of the problem is ------------------- data Experiment p = Experiment { e_ext :: (XEOverLit p), e_val :: Int } | XExperiment (XXOverLit p) deriving instance (Data (GhcPass p)) => Data (Experiment (GhcPass p)) type family XEOverLit x type family XXOverLit x -- The following line works -- type instance XEOverLit (GhcPass _) = PlaceHolder -- The following 3 lines do noe type instance XEOverLit (GhcPass 'Parsed ) = PlaceHolder type instance XEOverLit (GhcPass 'Renamed ) = PlaceHolder type instance XEOverLit (GhcPass 'Typechecked) = PlaceHolder type instance XXOverLit (GhcPass _) = PlaceHolder ------------------- Where specifying the type instance with a wild card keeps GHC happy (the XXOverLit case), but specifying for each of the three constructors for pass does not (the XEOverLit case) The exact error message is ------------------------------ Experiment.hs:34:1: error: • Could not deduce (Data (XEOverLit (GhcPass p))) arising from a use of ‘k’ from the context: Data (GhcPass p) bound by the instance declaration at Experiment.hs:34:1-69 • In the first argument of ‘k’, namely ‘(z Experiment `k` a1)’ In the expression: ((z Experiment `k` a1) `k` a2) In an equation for ‘gfoldl’: gfoldl k z Experiment a1 a2 = ((z Experiment `k` a1) `k` a2) When typechecking the code for ‘gfoldl’ in a derived instance for ‘Data (Experiment (GhcPass p))’: To see the code I am typechecking, use -ddump-deriv | 34 | deriving instance (Data (GhcPass p)) => Data (Experiment (GhcPass p)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------------------ Alan [1] http://lpaste.net/360017

And it seems that
--------------------------------------
data Experiment p
= Experiment {
e_ext :: (XEOverLit p),
e_val :: Int }
| XExperiment (XXOverLit p)
deriving instance (Data GhcPs) => Data (Experiment GhcPs)
deriving instance (Data GhcRn) => Data (Experiment GhcRn)
deriving instance (Data GhcTc) => Data (Experiment GhcTc)
----------------------------------------
works, but only for GHC 8.2.1, not GHC 8.0.2
Alan
On 13 November 2017 at 11:23, Alan & Kim Zimmerman
At the moment the Trees that Grow implementation in GHC master makes use of massive constraint types to provide Data instances for the hsSyn AST.
I am trying to remove the need for this, and have hit a problem.
The example I have reduced it to is here [1]
The essence of the problem is
------------------- data Experiment p = Experiment { e_ext :: (XEOverLit p), e_val :: Int } | XExperiment (XXOverLit p) deriving instance (Data (GhcPass p)) => Data (Experiment (GhcPass p))
type family XEOverLit x type family XXOverLit x
-- The following line works -- type instance XEOverLit (GhcPass _) = PlaceHolder
-- The following 3 lines do noe type instance XEOverLit (GhcPass 'Parsed ) = PlaceHolder type instance XEOverLit (GhcPass 'Renamed ) = PlaceHolder type instance XEOverLit (GhcPass 'Typechecked) = PlaceHolder
type instance XXOverLit (GhcPass _) = PlaceHolder -------------------
Where specifying the type instance with a wild card keeps GHC happy (the XXOverLit case), but specifying for each of the three constructors for pass does not (the XEOverLit case)
The exact error message is
------------------------------ Experiment.hs:34:1: error: • Could not deduce (Data (XEOverLit (GhcPass p))) arising from a use of ‘k’ from the context: Data (GhcPass p) bound by the instance declaration at Experiment.hs:34:1-69 • In the first argument of ‘k’, namely ‘(z Experiment `k` a1)’ In the expression: ((z Experiment `k` a1) `k` a2) In an equation for ‘gfoldl’: gfoldl k z Experiment a1 a2 = ((z Experiment `k` a1) `k` a2) When typechecking the code for ‘gfoldl’ in a derived instance for ‘Data (Experiment (GhcPass p))’: To see the code I am typechecking, use -ddump-deriv | 34 | deriving instance (Data (GhcPass p)) => Data (Experiment (GhcPass p)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------------------
Alan

Where specifying the type instance with a wild card keeps GHC happy (the XXOverLit case), but specifying for each of the three constructors for pass does not (the XEOverLit case) Well, of course! The derived data instance looks something like instance (Data (GhcPass p)) => Data (Experiment (GhcPass p)) where gfoldl = ….Needs (Data (XEOverLit (GhcPass p)))… How can GHC solve the wanted constraint Data (XEOverlit (GhcPass p)) With three equations, it can’t. With one, it can. So why not use one? Simon From: ghc-devs [mailto:ghc-devs-bounces@haskell.org] On Behalf Of Alan & Kim Zimmerman Sent: 13 November 2017 09:24 To: ghc-devs@haskell.org Subject: Trees that Grow and constraints At the moment the Trees that Grow implementation in GHC master makes use of massive constraint types to provide Data instances for the hsSyn AST. I am trying to remove the need for this, and have hit a problem. The example I have reduced it to is here [1] The essence of the problem is ------------------- data Experiment p = Experiment { e_ext :: (XEOverLit p), e_val :: Int } | XExperiment (XXOverLit p) deriving instance (Data (GhcPass p)) => Data (Experiment (GhcPass p)) type family XEOverLit x type family XXOverLit x -- The following line works -- type instance XEOverLit (GhcPass _) = PlaceHolder -- The following 3 lines do noe type instance XEOverLit (GhcPass 'Parsed ) = PlaceHolder type instance XEOverLit (GhcPass 'Renamed ) = PlaceHolder type instance XEOverLit (GhcPass 'Typechecked) = PlaceHolder type instance XXOverLit (GhcPass _) = PlaceHolder ------------------- Where specifying the type instance with a wild card keeps GHC happy (the XXOverLit case), but specifying for each of the three constructors for pass does not (the XEOverLit case) The exact error message is ------------------------------ Experiment.hs:34:1: error: • Could not deduce (Data (XEOverLit (GhcPass p))) arising from a use of ‘k’ from the context: Data (GhcPass p) bound by the instance declaration at Experiment.hs:34:1-69 • In the first argument of ‘k’, namely ‘(z Experiment `k` a1)’ In the expression: ((z Experiment `k` a1) `k` a2) In an equation for ‘gfoldl’: gfoldl k z Experiment a1 a2 = ((z Experiment `k` a1) `k` a2) When typechecking the code for ‘gfoldl’ in a derived instance for ‘Data (Experiment (GhcPass p))’: To see the code I am typechecking, use -ddump-deriv | 34 | deriving instance (Data (GhcPass p)) => Data (Experiment (GhcPass p)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------------------ Alan [1] http://lpaste.net/360017https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Flpaste.net%2F360017&data=02%7C01%7Csimonpj%40microsoft.com%7C805caf6c0aac49f030ee08d52a785574%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636461618682611590&sdata=VxK0zeEmVsEahWRYMJ6xAG2gZviqGCd%2FHS4DrRXC0dM%3D&reserved=0

So why not use one?
Simon
If I do instance (Data p) => Data (Experiment p) then GHC does not know that the type instances for type instance XEOverLit (GhcPass 'Parsed ) = PlaceHolder type instance XEOverLit (GhcPass 'Renamed ) = PlaceHolder type instance XEOverLit (GhcPass 'Typechecked) = PlaceHolder apply. Or do I misunderstand your advice? Alan

Just to clarify, this example is a simplification, in practice we would be
applying different type for each type instance
e.g.
type instance XEOverLit (GhcPass 'Parsed ) = PlaceHolder
type instance XEOverLit (GhcPass 'Renamed ) = PlaceHolder
type instance XEOverLit (GhcPass 'Typechecked) = Type
(modelling existing PostTc)
Alan
On 13 November 2017 at 11:23, Alan & Kim Zimmerman
At the moment the Trees that Grow implementation in GHC master makes use of massive constraint types to provide Data instances for the hsSyn AST.
I am trying to remove the need for this, and have hit a problem.
The example I have reduced it to is here [1]
The essence of the problem is
------------------- data Experiment p = Experiment { e_ext :: (XEOverLit p), e_val :: Int } | XExperiment (XXOverLit p) deriving instance (Data (GhcPass p)) => Data (Experiment (GhcPass p))
type family XEOverLit x type family XXOverLit x
-- The following line works -- type instance XEOverLit (GhcPass _) = PlaceHolder
-- The following 3 lines do noe type instance XEOverLit (GhcPass 'Parsed ) = PlaceHolder type instance XEOverLit (GhcPass 'Renamed ) = PlaceHolder type instance XEOverLit (GhcPass 'Typechecked) = PlaceHolder
type instance XXOverLit (GhcPass _) = PlaceHolder -------------------
Where specifying the type instance with a wild card keeps GHC happy (the XXOverLit case), but specifying for each of the three constructors for pass does not (the XEOverLit case)
The exact error message is
------------------------------ Experiment.hs:34:1: error: • Could not deduce (Data (XEOverLit (GhcPass p))) arising from a use of ‘k’ from the context: Data (GhcPass p) bound by the instance declaration at Experiment.hs:34:1-69 • In the first argument of ‘k’, namely ‘(z Experiment `k` a1)’ In the expression: ((z Experiment `k` a1) `k` a2) In an equation for ‘gfoldl’: gfoldl k z Experiment a1 a2 = ((z Experiment `k` a1) `k` a2) When typechecking the code for ‘gfoldl’ in a derived instance for ‘Data (Experiment (GhcPass p))’: To see the code I am typechecking, use -ddump-deriv | 34 | deriving instance (Data (GhcPass p)) => Data (Experiment (GhcPass p)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------------------
Alan

Isn't the solution always
if generic programming makes things complicated, avoid it!
Here generic programming is where you define instances parametric on the
phase index.
Why not defining three instances of the type class, one per each phase?
Yes, we get code duplication (which in this case is still not much as we
use automatic deriving), but the compilation gets faster (which is the
motivation), like [2].
[2] http://lpaste.net/360019
/Shayan
On Mon, Nov 13, 2017 at 2:05 PM, Alan & Kim Zimmerman
Just to clarify, this example is a simplification, in practice we would be applying different type for each type instance
e.g.
type instance XEOverLit (GhcPass 'Parsed ) = PlaceHolder type instance XEOverLit (GhcPass 'Renamed ) = PlaceHolder type instance XEOverLit (GhcPass 'Typechecked) = Type
(modelling existing PostTc)
Alan
On 13 November 2017 at 11:23, Alan & Kim Zimmerman
wrote: At the moment the Trees that Grow implementation in GHC master makes use of massive constraint types to provide Data instances for the hsSyn AST.
I am trying to remove the need for this, and have hit a problem.
The example I have reduced it to is here [1]
The essence of the problem is
------------------- data Experiment p = Experiment { e_ext :: (XEOverLit p), e_val :: Int } | XExperiment (XXOverLit p) deriving instance (Data (GhcPass p)) => Data (Experiment (GhcPass p))
type family XEOverLit x type family XXOverLit x
-- The following line works -- type instance XEOverLit (GhcPass _) = PlaceHolder
-- The following 3 lines do noe type instance XEOverLit (GhcPass 'Parsed ) = PlaceHolder type instance XEOverLit (GhcPass 'Renamed ) = PlaceHolder type instance XEOverLit (GhcPass 'Typechecked) = PlaceHolder
type instance XXOverLit (GhcPass _) = PlaceHolder -------------------
Where specifying the type instance with a wild card keeps GHC happy (the XXOverLit case), but specifying for each of the three constructors for pass does not (the XEOverLit case)
The exact error message is
------------------------------ Experiment.hs:34:1: error: • Could not deduce (Data (XEOverLit (GhcPass p))) arising from a use of ‘k’ from the context: Data (GhcPass p) bound by the instance declaration at Experiment.hs:34:1-69 • In the first argument of ‘k’, namely ‘(z Experiment `k` a1)’ In the expression: ((z Experiment `k` a1) `k` a2) In an equation for ‘gfoldl’: gfoldl k z Experiment a1 a2 = ((z Experiment `k` a1) `k` a2) When typechecking the code for ‘gfoldl’ in a derived instance for ‘Data (Experiment (GhcPass p))’: To see the code I am typechecking, use -ddump-deriv | 34 | deriving instance (Data (GhcPass p)) => Data (Experiment (GhcPass p)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ------------------------------
Alan
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
participants (3)
-
Alan & Kim Zimmerman
-
Shayan Najd
-
Simon Peyton Jones