-
Notifications
You must be signed in to change notification settings - Fork 273
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
Add type families for concrete optics #736
base: master
Are you sure you want to change the base?
Conversation
It's occasionally useful to get one's hands on the concrete `Functor` or `Profunctor` of an `ALens`, `APrism`, etc., to use in constraints. Currently, the only built-in option is to import the relevant `.Internal` module and use the right one. But since these types are all concrete and transparent, it's actually possible to write type families to extract the relevant types. So let's do that, purely for convenience. Note: I believe it must be possible to use `TypeInType` to make the kinds of the results depend on the arguments. So we should be able to ask for something like `GetConcreteFunctor (AnEquality 'Bool 'Int 'Bool 'Int)`. But I don't yet know enough about `TypeInType` to be able to do that myself.
(Sorry for the churn. I got mixed up a couple times.) |
p and q change in things like indexed optics. e.g. Not entirely sold one way or the other on the utility provided here. |
@ekmett I just got the import Control.Lens
import Control.Lens.Reified
pattern Package :: Lens s t a b -> ReifiedLens s t a b
pattern Package f <- Lens f
where
Package :: ALens s t a b -> ReifiedLens s t a b
Package f = Lens $ cloneLens f Unfortunately, if the committee sticks to its guns and requires that the pattern signature and builder signature are the same modulo constraints, this will have to be expressed something like import Control.Lens.Internal.Context -- additionally
pattern Package :: c ~ Functor
=> (forall f. c f => LensLike f s t a b)
-> ReifiedLens s t a b
pattern Package f <- Lens f
where
Package :: c ~ ((~) (Pretext (->) a b))
=> (forall f. c f => LensLike f s t a b)
-> ReifiedLens s t a b
Package f = Lens $ cloneLens f The proposed type families allow this to be written without the Package :: c ~ ((~) (GetConcreteFunctor (ALens s t a b)))
=> .... Yes, the whole thing is horrible... |
Wouldn't the better solution here be to just re-export the types from non-Internal modules? |
@bennofs, that was my first thought, and may very well be the right one, but what if the definition of |
@treeowl What would a possible change of |
I don't know if either of these could ever actually be good ideas; I'm just thinking hypothetically. |
@bennofs, note that the type families leave the current abstraction barrier in exactly the same place; they're the most conservative way to solve the problem. That doesn't mean they're the right way! |
* For GHC 8.0 and above, we can calculate the result kind from the argument type. This allows us to use the type families with `AnEquality` at arbitrary kinds. * Get the original and transformed profunctors, and generally make fewer unnecessary assumptions about the argument structure.
I can't begin to understand the errors CI is getting on GHC 7.8 and 7.10. Was that a now-fixed GHC bug? |
@treeowl, you can work around one occurrence of that bug by sufficient kind monomorphization: type instance GetConcreteFunctor (pafb -> (p :: * -> * -> *) s (f t)) = f I'm not sure if you intended for it to actually be |
GHC 7.8 and 7.10 give a weird error claiming that the LHS purports to bind a type variable `k`, which is bogus. @RyanGlScott suggested a workaround.
type instance GetConcreteFunctor (pafb -> (p :: * -> * -> *) s ((f :: * -> *) t)) = f | ||
#endif | ||
|
||
-- | Extract the concrete 'Profunctor' from a concrete 'ALens', 'AnIso', etc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to fix up the documentation to reflect the split into GetConcreteArgProfunctor
and GetConcreteTransformedProfunctor
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could delegate to another type family recursively to handle (p s (f t)) which delegates to another to force p to have kind * -> * -> *. This would likely require ~3 type families though.
Why would I want to do that?
…On May 25, 2017 11:07 PM, "Edward Kmett" ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In src/Control/Lens/Type.hs
<#736 (comment)>:
> +-- GetConcreteFunctor (ALens s t a b) = Pretext (->) a b
+-- GetConcreteFunctor (AnIso s t a b) = Identity
+-- @
+#if __GLASGOW_HASKELL__ >= 800
+type family GetConcreteFunctor (x :: *) :: GetConcreteFunctorKind x
+type instance GetConcreteFunctor x = GetConcreteFunctorType (GetConcreteFunctorKind x) x
+type family GetConcreteFunctorKind (x :: *) :: *
+type instance GetConcreteFunctorKind (pafb -> p s ((f :: j -> k) t)) = j -> k
+type family GetConcreteFunctorType (k :: *) (x :: *) :: k
+type instance GetConcreteFunctorType (i -> o) (pafb -> p s ((f :: i -> o) t)) = f
+#else
+type family GetConcreteFunctor (x :: *) :: * -> *
+type instance GetConcreteFunctor (pafb -> (p :: * -> * -> *) s ((f :: * -> *) t)) = f
+#endif
+
+-- | Extract the concrete 'Profunctor' from a concrete 'ALens', 'AnIso', etc.
You could delegate to another type family recursively to handle (p s (f
t)) which delegates to another to force p to have kind * -> * -> *. This
would likely require ~3 type families though.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#736 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ABzi_cGQ4nhLqkba_1qliwQdpH9Y2xS-ks5r9kHigaJpZM4Nmv8E>
.
|
It's occasionally useful to get one's hands on the concrete
Functor
orProfunctor
of anALens
,APrism
, etc., to use in constraints. Currently,the only built-in option is to import the relevant
.Internal
module and usethe right one. But since these types are all concrete and transparent, it's
actually possible to write type families to extract the relevant types.
So let's do that, purely for convenience.
Note: I believe it must be possible to useTypeInType
to make the kindsof the results depend on the arguments. So we should be able to ask for
something like
GetConcreteFunctor (AnEquality 'True 0 'False' 1)
.But I don't yet know enough about
TypeInType
to be able to do that myself.