Skip to content

Loading…

Add `makeExposed`? #197

Open
ekmett opened this Issue · 3 comments

2 participants

@ekmett
Owner

One common objection to lenses is that we can't do type changing assignment to multiple fields simultaneously.

We can. We just need to go into a more permissive type temporarily.

Lets define

class Exposed s t a b | s -> a, t -> b, a -> s, b -> t, s b -> t a, t a -> s b where
  exposed :: Iso s t a b

In general you can then perform polymorphic update with

flip (over exposed) foo $ \x -> x & bar .~ 2 & quux %~ length

as a class like Wrapped or Each, which is more symmetric about type inference.

Ideally if we had

data Quux a b = Quux { _foo :: a, _bar :: b, _baz :: Quux a b } deriving (Eq,Ord,Show,Read)
makeExposed ''Quux

It could generate something like the following test fragment:

{-# LANGUAGE TemplateHaskell, MultiParamTypeClasses, FunctionalDependencies, TypeFamilies, UndecidableInstances, FlexibleInstances #-}
module Tilt where

import Control.Lens

data Quux a b = Quux a b (Quux a b) deriving (Eq,Ord,Show,Read)

data TiltedQuux a b c d = TiltedQuux { _foo :: a, _bar :: b, _baz :: Quux c d }
makeClassy ''TiltedQuux

instance (c ~ a, d ~ b, e ~ g, f ~ h) => Tilted (Quux a b) (Quux e f) (TiltedQuux a b c d) (TiltedQuux e f g h) where
  tilted = iso hither yon where
    hither (Quux a b c) = TiltedQuux a b c
    yon (TiltedQuux a b c) = Quux a b c

instance HasTiltedQuux (Quux a b) a b a b where
  tiltedQuux = tilted

class HasTiltedQuux t a b a b => HasQuux t a b | t -> a b where
  quux :: Simple Lens t (Quux a b)

instance HasQuux (Quux a b) a b where
  quux = id

Here I've moved the definitions to TiltedQuux, but that was just so i could borrow makeClassy.

This requires more extensions than makeClassy does by default, so it shouldn't be the default definition.

But given this you can do polymorphic updates that require multiple fields to change by moving the type equality check to reassembly time.

@ekmett
Owner

For this to be useful we also need #128. Otherwise the HasExposedFoo and HasFoo instances will not be able to do type changing assignment.

@glguy
Collaborator

I've started on some code to explore this http://hpaste.org/81965

@ekmett
Owner

Nice!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.