Closed ekmett closed 11 years ago
For the record, here were some of the things that could then be deleted: https://github.com/ekmett/lens/commit/c2619c49fb1c2c5bfb660ac84dd7313241b015ed
Also, I thought about it a little more, and am now in favor of "wrap" and "unwrap", because they are used surprisingly little:
http://holumbus.fh-wedel.de/hayoo/hayoo.html#0:%22unwrap%22 http://holumbus.fh-wedel.de/hayoo/hayoo.html#0:%22wrap%22
The only one that's at all worrisome is both "unwrapping" and "unwrap" in the free library. I'm sure the author of that library won't mind aliasing his identifiers ;)
The other reason for my change of tack is that the Control.Newtype library provides many transformations that are more concise because they are specific to newtype Isos.
Control.Newtype | Control.Lens | using under | using operators |
---|---|---|---|
op | view . unwrap | unwrap Foo ^. | |
over | over . wrap | under . unwrap | wrap Foo %~ |
under | over . unwrap | under . wrap | unwrap Foo %~ |
overF | over . mapping . wrap | under . mapping . unwrap | mapping (wrap Foo) %~ |
underF | over . mapping . unwrap | under . mapping . wrap | mapping (unwrap Foo) %~ |
We may also want to document these equivalences, for those who are already familiar with Control.Newtype, etc. I think they ought to be correct, but I could be wrong - I don't have GHC atm.
I'm definitely tempted to add op
.
I'm somewhat torn about alpha-reducing the names to wrap
/unwrap
, in part due to the conflict with the free
package, which is heavily used.
EDIT: Nevermind, this would make it non-composable. hrmm
One way to avoid the unwrap
/ unwrapping
issue is to change the type to Isomorphism
, allowing the use of from
. Is there a use case at all for a more generic Isomorphic k
for newtypes?
This would make instances half as big and also remove the redundancy in the chart above - unwrap isn't actually useful! This would also motivate inclusion of op
, as its definition would then be view . from . wrap
Isomorphism
no longer exists.
Really??? Should really update the code instead of just having gists ;)
Ahh, what about this solution?
class Wrapped s t a b | a -> s, b -> t, a t -> s, b s -> t where
wrapped :: Isomorphism s t a b
wrap :: Wrapped s s a a => (s -> a) -> Simple Iso s a
wrap _ = via wrapped
wraps :: Wrapped s s a a => (s -> a) -> (t -> b) -> Iso s t a b
wraps _ _ = via wrapped
Then, the user can just do from (wrapped Sum)
, and there's no need for unwrap
.
I'm not too worried about taking unwrap
if we decide to also take wrap
.
I'm mostly on the fence about whether wrap
is the name we want to take.
I'm more worried about the redundancy of the Wrapped
class. It's very ugly, and means that there are more laws about it than there need to be. (better to have all of the laws just be expressed by types)
Isn't Isomorphism s t a b
just Functor f => Forging f f s t a b
?
class Wrapper s t a b | a -> s, b -> t, a t -> s, b s -> t where
wrapper :: Isomorphism s t a b
wrapping :: Wrapped s s a a => (s -> a) -> Simple Iso s a
wrapping _ = via wrapper
wrappings :: Wrapped s t a b => (s -> a) -> (t -> b) -> Iso s t a b
wrappings _ _ = via wrapper
unwrapping :: Wrapped s s a a => (s -> a) -> Simple Iso a s
unwrapping _ = from wrapper
unwrappings :: Wrapped s t a b => (s -> a) -> (t -> b) -> Iso a b s t
unwrappings _ _ = from wrapper
The Forging experiment didn't work, you may want to update your repo. The gist doesn't reflect reality. ;)
The current Iso design uses a data type named Isos in Control.Lens.Internal.
unwrapped = from wrapped
would be fine default definitions to add to the class or separate definition for unwrapping. Having both, while technically redundant makes for a nice vocabulary. I'm partial to splitting unwrapped out to a separate function so we get a single member typeclass, which optimizes differently.
This could reduce the repetition for end users somewhat an should definitely be done.
I would be rather strongly against removing the un- variants completely -- a minimalist vocabulary has never been a design goal of lenses.
On Nov 27, 2012, at 4:49 PM, mgsloan notifications@github.com wrote:
I'm more worried about the redundancy of the Wrapped class. It's very ugly, and means that there are more laws about it than there need to be. (better to have all of the laws just be expressed by types)
Isn't Isomorphism s t a b just Functor f => Forging f f s t a b?
class Wrapper s t a b | a -> s, b -> t, a t -> s, b s -> t where wrapper :: Isomorphism s t a b
wrapping :: Wrapped s s a a => (s -> a) -> Simple Iso s a wrapping _ = via wrapper
wrappings :: Wrapped s t a b => (s -> a) -> (t -> b) -> Iso s t a b wrappings = via wrapper
unwrapping :: Wrapped s s a a => (s -> a) -> Simple Iso a s unwrapping _ = from wrapper
unwrappings :: Wrapped s t a b => (s -> a) -> (t -> b) -> Iso a b s t unwrappings = from wrapper — Reply to this email directly or view it on GitHub.
So this is why "Isomorphism no longer exists" confuses me. Maybe it's just on the way out the door?
https://github.com/ekmett/lens/blob/master/src/Control/Lens/Iso.hs#L63
On Tue, Nov 27, 2012 at 2:18 PM, Edward A. Kmett notifications@github.comwrote:
The Forging experiment didn't work, you may want to update your repo. The gist doesn't reflect reality. ;)
The current Iso design uses a data type named Isos in Control.Lens.Internal.
unwrapped = from wrapped
would be fine default definitions to add to the class or separate definition for unwrapping. Having both, while technically redundant makes for a nice vocabulary. I'm partial to splitting unwrapped out to a separate function so we get a single member typeclass, which optimizes differently.
This could reduce the repetition for end users somewhat an should definitely be done.
I would be rather strongly against removing the un- variants completely -- a minimalist vocabulary has never been a design goal of lenses.
On Nov 27, 2012, at 4:49 PM, mgsloan notifications@github.com wrote:
I'm more worried about the redundancy of the Wrapped class. It's very ugly, and means that there are more laws about it than there need to be. (better to have all of the laws just be expressed by types)
Isn't Isomorphism s t a b just Functor f => Forging f f s t a b?
class Wrapper s t a b | a -> s, b -> t, a t -> s, b s -> t where wrapper :: Isomorphism s t a b
wrapping :: Wrapped s s a a => (s -> a) -> Simple Iso s a wrapping _ = via wrapper
wrappings :: Wrapped s t a b => (s -> a) -> (t -> b) -> Iso s t a b wrappings = via wrapper
unwrapping :: Wrapped s s a a => (s -> a) -> Simple Iso a s unwrapping _ = from wrapper
unwrappings :: Wrapped s t a b => (s -> a) -> (t -> b) -> Iso a b s t unwrappings = from wrapper — Reply to this email directly or view it on GitHub.
— Reply to this email directly or view it on GitHubhttps://github.com/ekmett/lens/issues/141#issuecomment-10780060.
That isn't the Isomorphism we used to have. The old Isomorphism was very simple.
data Isomorphism a b = Isomorphism (a -> b) (b -> a)
The new Isomorphism can't be used directly to make a "reversible function" the way the old one could be abused - it only exists to facilitate pattern matching like how Getting
, Projecting
, etc. build on Accessor
and Project
.
From a discussion on
#haskell-lens
, we should:Control.Lens.Wrapped
module with something like:ala
to usewrapping
to match the existingControl.Newtype
behavior.ala
toau
.Data.Monoid.Lens
isomorphisms,identity
,_const
, etc.This will greatly reduce the need for the million different newtype isomorphisms we have scattered throughout the codebase, clearing up the namespace for users.