Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
A simple problem is being solved here, but unfortunately it is a bit involved. The idea is to use the same haskell identifier for a lens and for other purposes. In other words, get the same behavior as:
x = hLens (Label :: Label "x") r ^. x
While still being able to extract the symbol "x" from x, so that things
like x .=. 123
could be acceptable. In this case we don't overload .=.
,
so instead you have to write x .==. 123
.
Elaboration of some ideas from edwardk.
Synopsis
- class SameLength s t => Labelable (x :: k) (r :: [*] -> *) s t a b | x s -> a, x t -> b, x s b -> t, x t a -> s where
- type LabelableTy r :: LabeledOpticType
- hLens' :: Label x -> LabeledOptic x r s t a b
- type LabeledOptic (x :: k) (r :: [*] -> *) (s :: [*]) (t :: [*]) (a :: *) (b :: *) = forall ty to p f. (ty ~ LabelableTy r, LabeledOpticF ty f, LabeledOpticP ty p, LabeledOpticTo ty x to) => (a `p` f b) `to` (r s `p` f (r t))
- (.==.) :: forall {k} {x} {l :: k} {v}. EnsureLabel x (Label l) => x -> v -> Tagged l v
- class Projected r s t a b where
- projected :: (ty ~ LabelableTy r, LabeledOpticP ty p, LabeledOpticF ty f) => (r a `p` f (r b)) -> r s `p` f (r t)
- projected' :: forall {r} {p} {f} {t :: [Type]} {b :: [Type]}. (LabeledOpticP (LabelableTy r) p, LabeledOpticF (LabelableTy r) f, Projected r t t b b) => p (r b) (f (r b)) -> p (r t) (f (r t))
- type LabeledCxt1 s t a b = (s ~ '[], t ~ '[], a ~ (), b ~ ())
- data LabeledTo (x :: k) (a :: *) (b :: *) = LabeledTo
- data LabeledR (x :: [*]) = LabeledR
- class ToSym label (s :: Symbol) | label -> s
- class EnsureLabel x y | x -> y where
- toLabel :: x -> y
- toLabelSym :: forall {x} {x :: Symbol}. EnsureLabel x (Label x) => x -> Label x
- data Identity a
- type LabelableTIPCxt x s t a b = (s ~ t, a ~ b, Label x ~ Label a, HLens x TIP s t a b)
- data LabeledOpticType
- type family LabeledOpticF (ty :: LabeledOpticType) :: (* -> *) -> Constraint
- type family LabeledOpticP (ty :: LabeledOpticType) :: (* -> * -> *) -> Constraint
- type family LabeledOpticTo (ty :: LabeledOpticType) (x :: k) :: (* -> * -> *) -> Constraint
Documentation
class SameLength s t => Labelable (x :: k) (r :: [*] -> *) s t a b | x s -> a, x t -> b, x s b -> t, x t a -> s where Source #
type LabelableTy r :: LabeledOpticType Source #
hLens' :: Label x -> LabeledOptic x r s t a b Source #
Instances
LabeledCxt1 s t a b => Labelable (x :: k) LabeledR s t a b Source # | |
Defined in Data.HList.Labelable type LabelableTy LabeledR :: LabeledOpticType Source # | |
HLens x Record s t a b => Labelable (x :: k) Record s t a b Source # | make a |
Defined in Data.HList.Labelable type LabelableTy Record :: LabeledOpticType Source # | |
(s ~ t, a ~ b, IArray UArray a, a ~ GetElemTy s, HLensCxt x RecordU s t a b) => Labelable (x :: k) RecordU s t a b Source # | make a |
Defined in Data.HList.RecordU type LabelableTy RecordU :: LabeledOpticType Source # | |
(TICPrism s t a b, Label x ~ Label a, a ~ b, s ~ t, SameLength s t) => Labelable (x :: k) TIC s t a b Source # | hLens' :: Label a -> Prism' (TIC s) a note that a more general function Note: `x :: k` according to the instance head, but the instance body forces the kind variable to be * later on. IE. (k ~ *) |
Defined in Data.HList.Labelable type LabelableTy TIC :: LabeledOpticType Source # | |
LabelableTIPCxt x s t a b => Labelable (x :: k) TIP s t a b Source # | make a
|
Defined in Data.HList.Labelable type LabelableTy TIP :: LabeledOpticType Source # | |
(HPrism x s t a b, to ~ (->)) => Labelable (x :: k) Variant s t a b Source # | make a |
Defined in Data.HList.Labelable type LabelableTy Variant :: LabeledOpticType Source # |
type LabeledOptic (x :: k) (r :: [*] -> *) (s :: [*]) (t :: [*]) (a :: *) (b :: *) = forall ty to p f. (ty ~ LabelableTy r, LabeledOpticF ty f, LabeledOpticP ty p, LabeledOpticTo ty x to) => (a `p` f b) `to` (r s `p` f (r t)) Source #
This alias is the same as Control.Lens.Optic, except the (->) in Optic
is a type parameter to
in LabeledOptic.
Depending on the collection type (see instances of LabelableTy
),
the type variables to, p, f
are constrained such that the resulting
type is a Lens (r s) (r t) a b
, Prism (r s) (r t) a b
or a
LabeledTo x _ _
. The latter can be used to recover the label (x
) when
used as an argument to .==.
or equivalently toLabel
.
(.==.) :: forall {k} {x} {l :: k} {v}. EnsureLabel x (Label l) => x -> v -> Tagged l v infixr 4 Source #
modification of .=.
which works with the labels from this module,
and those from Data.HList.Label6. Note that this is not strictly a
generalization of .=.
, since it does not work with labels like
Data.HList.Label3 which have the wrong kind.
multiple lookups
class Projected r s t a b where Source #
Sometimes it may be more convenient to operate on a record/variant
that only contains the fields of interest. projected
can then be used
to apply that function to a record that contains additional elements.
>>>
:set -XViewPatterns
>>>
import Data.HList.RecordPuns
>>>
let f [pun| (x y) |] = case x+y of z -> [pun| z |]
>>>
:t f
f :: Num v => Record '[Tagged "x" v, Tagged "y" v] -> Record '[Tagged "z" v]
>>>
let r = (let x = 1; y = 2; z = () in [pun| x y z |])
>>>
r
Record{x=1,y=2,z=()}
>>>
r & sameLabels . projected %~ f
Record{x=1,y=2,z=3}
projected :: (ty ~ LabelableTy r, LabeledOpticP ty p, LabeledOpticF ty f) => (r a `p` f (r b)) -> r s `p` f (r t) Source #
Instances
(H2ProjectByLabels (LabelsOf a) s a_ _s_minus_a, HRLabelSet a_, HRLabelSet a, HRearrange (LabelsOf a) a_ a, HLeftUnion b s bs, HRLabelSet bs, HRearrange (LabelsOf t) bs t, HRLabelSet t) => Projected Record s t a b Source # | Lens rs rt ra rb where |
Defined in Data.HList.Labelable projected :: forall (ty :: LabeledOpticType) p f. (ty ~ LabelableTy Record, LabeledOpticP ty p, LabeledOpticF ty f) => p (Record a) (f (Record b)) -> p (Record s) (f (Record t)) Source # | |
(ExtendsVariant b t, ProjectVariant s a, ProjectExtendVariant s t, HLeftUnion b s bs, HRLabelSet bs, HRearrange (LabelsOf t) bs t) => Projected Variant s t a b Source # | Prism (Variant s) (Variant t) (Variant a) (Variant b) |
Defined in Data.HList.Labelable projected :: forall (ty :: LabeledOpticType) p f. (ty ~ LabelableTy Variant, LabeledOpticP ty p, LabeledOpticF ty f) => p (Variant a) (f (Variant b)) -> p (Variant s) (f (Variant t)) Source # |
projected' :: forall {r} {p} {f} {t :: [Type]} {b :: [Type]}. (LabeledOpticP (LabelableTy r) p, LabeledOpticF (LabelableTy r) f, Projected r t t b b) => p (r b) (f (r b)) -> p (r t) (f (r t)) Source #
Lens' (Record s) (Record a)
Prism' (Variant s) (Variant a)
comparison with hLens
Note that passing around variables defined with hLens'
doesn't get
you exactly the same thing as calling hLens
at the call-site:
The following code needs to apply the x
for different Functor
f =>
, so you would have to write a type signature (rank-2) to allow this
definition:
-- with the x defined using hLens' let f x r = let a = r ^. x b = r & x .~ "6" in (a,b)
This alternative won't need a type signature
-- with the x defined as x = Label :: Label "x" let f x r = let a = r ^. hLens x b = r & hLens x .~ "7" in (a,b)
It may work to use hLens'
instead of hLens
in the second code,
but that is a bit beside the point being made here.
likely unneeded (re)exports
type LabeledCxt1 s t a b = (s ~ '[], t ~ '[], a ~ (), b ~ ()) Source #
sets all type variables to dummy values: only the Labeled x
part is actually needed
data LabeledR (x :: [*]) Source #
Instances
LabeledCxt1 s t a b => Labelable (x :: k) LabeledR s t a b Source # | |
Defined in Data.HList.Labelable type LabelableTy LabeledR :: LabeledOpticType Source # | |
type LabelableTy LabeledR Source # | |
Defined in Data.HList.Labelable |
class EnsureLabel x y | x -> y where Source #
Convert a type to Label :: Label blah
toLabel :: LabeledTo x _ _ -> Label (x :: Symbol) toLabel (hLens' lx) = (lx :: Label x) toLabel :: Label x -> Label x toLabel :: Proxy x -> Label x
Instances
EnsureLabel (Label x) (Label x) Source # | |
EnsureLabel (Proxy x) (Label x) Source # | |
ToSym (a b c) x => EnsureLabel (a b c) (Label x) Source # | get the Label out of a |
Defined in Data.HList.Labelable |
toLabelSym :: forall {x} {x :: Symbol}. EnsureLabel x (Label x) => x -> Label x Source #
fix the k
kind variable to Symbol
Identity functor and monad. (a non-strict monad)
Since: base-4.8.0.0
Instances
type family LabeledOpticF (ty :: LabeledOpticType) :: (* -> *) -> Constraint Source #
Instances
type LabeledOpticF 'LabelableLabel Source # | |
Defined in Data.HList.Labelable | |
type LabeledOpticF 'LabelableLens Source # | |
Defined in Data.HList.Labelable | |
type LabeledOpticF 'LabelablePrism Source # | |
Defined in Data.HList.Labelable |
type family LabeledOpticP (ty :: LabeledOpticType) :: (* -> * -> *) -> Constraint Source #
Instances
type LabeledOpticP 'LabelableLabel Source # | |
Defined in Data.HList.Labelable | |
type LabeledOpticP 'LabelableLens Source # | |
Defined in Data.HList.Labelable | |
type LabeledOpticP 'LabelablePrism Source # | |
Defined in Data.HList.Labelable |
type family LabeledOpticTo (ty :: LabeledOpticType) (x :: k) :: (* -> * -> *) -> Constraint Source #
Instances
type LabeledOpticTo 'LabelableLabel (x :: k) Source # | |
Defined in Data.HList.Labelable | |
type LabeledOpticTo 'LabelableLens (x :: k) Source # | |
Defined in Data.HList.Labelable | |
type LabeledOpticTo 'LabelablePrism (x :: k) Source # | |
Defined in Data.HList.Labelable |
Orphan instances
(to ~ LabeledTo x, ToSym (to p q) x) => HExtend (to p q) (Proxy (x ': xs)) Source # | |
(to ~ LabeledTo x, ToSym (to p q) x) => HExtend (to p q) (Proxy (Lbl n ns desc ': xs)) Source # | if the proxy has Data.HList.Label3.Lbl, then everything has to be wrapped in Label to make the kinds match up. |
(to ~ LabeledTo x, ToSym (to p q) x) => HExtend (to p q) (Proxy ('[] :: [Type])) Source # | Together with the instance below, this allows writing
Or with HListPP p = `x .*. `y .*. `z .*. emptyProxy instead of p = Proxy :: Proxy ["x","y","z"] |