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

Recursing with typed as well as types #134

Open
PPKFS opened this issue Jul 3, 2021 · 3 comments
Open

Recursing with typed as well as types #134

PPKFS opened this issue Jul 3, 2021 · 3 comments

Comments

@PPKFS
Copy link

PPKFS commented Jul 3, 2021

data A = A deriving Generic
data B = B deriving Generic
data C = C deriving Generic
data D = D deriving Generic
data E = E deriving Generic
data F = F deriving Generic
data G = G deriving Generic

data A1 = A1 A B C  deriving Generic
data A2 = A2 A
data A3 = A3 B C D
data A4 = A4 D E F  deriving Generic
data A5 = A5 A1 A4 G deriving Generic
data A6 = A6 A1 A2 deriving Generic

-- examples
    let a5 = A5 (A1 A B C) (A4 D E F) G
    let a6 = A6 (A1 A B C) (A2 A)
    -- OK!
    let f = a5 ^. typed @A1
    -- OK!
    let g = a5 ^. typed @A1 . typed @B
    -- OK!
    let h = safeHead $ a5 ^.. types @B
    -- Not OK - A5 has no field B
    let i = a5 ^. typed @B
    -- Not OK - A6 has no field A, but ideally it should be Not OK - A6 has duplicate A
    let j = a6 ^. typed @A

I noticed there was #75 which seems to suggest it's possible, but having scoured the linked issues and pull requests I can't quite find out how.

In retrospect, I think this probably falls into problems with sum types; there is no Lens' (Maybe A1) B...

@kcsongor
Copy link
Owner

kcsongor commented Jul 3, 2021

I implemented this feature a while ago (it might be on a branch? I can't remember), but never merged it because of how brittle I thought it was. Since the lens focuses on a single element, it only makes sense if the whole type has exactly one value of that type (as your A6 example shows). We have to look deep, and if any type in the tree has no Generic instance then the procedure fails. (though the "types" combinator suffers from the same issue, and that has a workaround)

I thought about maybe taking an additional numeric argument to specify the maximum depth, but that seemed inelegant.
Since then, I've actually whished for this feature a few times myself, and I'm now thinking that this might be a good thing to do after all.

I won't have too much time/energy in the near future to work on it though. I'll keep it in mind the next time I come back here!

@PPKFS
Copy link
Author

PPKFS commented Jul 3, 2021

Makes sense, thanks! I'll have a peruse and see if it's on a branch somewhere :)

@raehik
Copy link
Contributor

raehik commented Aug 2, 2021

I just bumped into this -- I wanted a setup where I could "peel off" layers of the environment in a MonadReader (the regular Has pattern I think), started doing it manually, found that generic-lens could automate it for me. typed not recursing means it's a bit off the behaviour I wanted. I tried providing an instance HasType Outer Inner that would go through a Middle type, but of course it overlaps.

I think a deep search would give me the exact functionality I want, since if I did end trying to use a Has instance where the type has != 1 value of the type, I'd want a type error (in other words, if I was doing it manually, I wouldn't have written such an instance). If I could receive a few pointers for this I might be able to look into it? Not done generics before though...!

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

No branches or pull requests

3 participants