Skip to content
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

Arg type prisms #642

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open

Arg type prisms #642

wants to merge 11 commits into from

Conversation

duog
Copy link
Contributor

@duog duog commented Apr 1, 2016

Hi,

This PR expands the capability of prism-generating template haskell. Constructors that take multiple arguments have data types for those arguments generated, and the prisms for those constructors target the generated data types instead of tuples. The generated data types also have lenses generated.

Two new functions, declareArgTypePrisms and makeArgTypePrisms, are added that take a Parameter of type Name -> Maybe (Name, LensRules). This function is applied to each constructor name. A result of Nothing will cause tuple prisms to be generated as usual, while a result of Just (n, lr) will cause a data type n to be generated, and lenses on that data type to be generated using lr.

e.g.

data A = A1 {_a :: Int, _b :: Int } | A2 {_c :: Int, _d :: Int}
makeArgTypePrisms argTypesRulesSelector ''A

Will generate:

data A1Args = A1Args Int Int
data A2Args = A2Args Int Int
_A1 :: Prism' A A1Args
a :: Lens' A1Args Int
b :: Lens' A1Args Int
_A2 :: Prism' A A2Args
c :: Lens' A2Args Int
d :: Lens' A2Args Int

I have added some tests to templates.hs to exercise the new functionality.
I'm not confident that the names of chosen are any good.

Please let me know if you are interested in merging this.

duog added 11 commits April 1, 2016 11:03
… they can be utilized in Control.Lens.Internal.PrismTH
…nstead of a tuple. E.g.

prs = --some suitable definition
data A = A1 {_a :: Int, _b :: Int } | A2 {_c :: Int, _d :: Int}
makeArgTypePrisms prs ''A

Will generate:
data A1Args = A1Args Int Int
data A2Args = A2Args Int Int
_A1 :: Prism' A A1Args
a :: Lens' A1Args Int
b :: Lens' A1Args Int
_A2 :: Prism' A A2Args
c :: Lens' A2Args Int
d :: Lens' A2Args Int

Add functions makeArgTypePrisms makeArgTypeDecPrisms and type PrismRulesSelector to interface of Control.Lens.Internal.PrismTH.
These functions take an additional parameter of type PrismRulesSelector (= Name -> Maybe (Name, LensRules)).
This function is applied to each constructor name. A Nothing causes the existing tuple behaviour to trigger, and a Just (n, rules) causes a data type and its lenses to be generated.

This required changes to much of PrismTH, threading the PrismRulesSelector through, then using it to compute a PrismTarget which is stored in the Stab.

This commit passes tests on GHC 7.10.3. So tuple prisms should still be working, but I don't expect ArgType prisms to be working yet.
…o exports of Control.Lens.TH.

Add argTypesRulesSelector :: PrismRulesSelector. This function appends Args to the name of the constructor and passes defaultFieldRules.

Add some tests to templates.hs to exercise the new prism code. These tests currently fail.
This might be a bit dodgy, needs a review.
uses lensRules, except names the lens by prepending an underscore to the field name.
Rename PrismTargetNewtype to PrismTargetDataType
Add a field of type [TyVarBndr] to PrismTargetDataType. This is required so that we can remember the order of type variables.
Add HasTypeVars and SubstType instances for PrismTarget
Fix targetType for the PrismTargetDataType case
Fix targetDecs
Fix computePrismStab and computeIsoType

Add tests for the Prism ArgTypes feature
Fix some lints
Attempt to fix failure to compile on ghc-8 caused by change to template-haskell, don't have this compiler so I haven't tested this.
@ekmett
Copy link
Owner

ekmett commented Jul 7, 2016

I confess to being a bit conflicted about this.

@duog
Copy link
Contributor Author

duog commented Sep 4, 2016

I did this work when I was working with the ghc api, and it's plethora of data types with many constructors of many arguments. In general I don't find the existing prisms particularly useful for constuctors with more than 2 or 3 arguments, and these arg type prisms were useful then.

I wasn't able to find a way to build this without copying a lot of the internal lens code

Feel free to close if you're not interested, or I'm happy to take direction on helping to turn this into something acceptable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants