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

HasField' and nested labels don't play along well #125

Open
googleson78 opened this issue Jul 15, 2020 · 2 comments
Open

HasField' and nested labels don't play along well #125

googleson78 opened this issue Jul 15, 2020 · 2 comments

Comments

@googleson78
Copy link
Sponsor

In this example:

{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE MonoLocalBinds #-}

import Data.Generics.Product (HasField', field')
import Data.Generics.Labels ()

g :: (HasField' "outer" s t, HasField' "inner" t a) => forall f. Functor f => (a -> f a) -> s -> f s
g = #outer . #inner

g' :: (HasField' "outer" s t, HasField' "inner" t a) => forall f. Functor f => (a -> f a) -> s -> f s
g' = field' @"outer" . field' @"inner"

g' typechecks, but g doesn't:

Collapsed error

blademaster :: ~ » stack ghci generic-labels.hs --package generic-lens --package microlens
[1 of 1] Compiling Main             ( /home/googleson78/generic-labels.hs, interpreted )

/home/googleson78/generic-labels.hs:11:5: error:
     Overlapping instances for HasField "outer" s s s0 t0
        arising from the overloaded label ‘#outer
      Matching instances:
        instance (HasTotalFieldP field (Rep s) ~~ 'Just a,
                  HasTotalFieldP field (Rep t) ~~ 'Just b,
                  HasTotalFieldP field (Rep (Indexed s)) ~~ 'Just a',
                  HasTotalFieldP field (Rep (Indexed t)) ~~ 'Just b',
                  t ~~ Infer s a' b, s ~~ Infer t b' a, HasField0 field s t a b) =>
                 HasField field s t a b
          -- Defined in ‘Data.Generics.Product.Fields’
        ...plus one instance involving out-of-scope types
        (use -fprint-potential-instances to see them all)
      (The choice depends on the instantiation of s, s0, t0
       To pick the first instance above, use IncoherentInstances
       when compiling the other instance declarations)
     In the first argument of (.), namely ‘#outer
      In the expression: #outer . #inner
      In an equation for g’: g = #outer . #inner
   |
11 | g = #outer . #inner
   |     ^^^^^^

/home/googleson78/generic-labels.hs:11:14: error:
     Overlapping instances for HasField "inner" s0 t0 a a
        arising from the overloaded label ‘#inner
      Matching instances:
        instance (HasTotalFieldP field (Rep s) ~~ 'Just a,
                  HasTotalFieldP field (Rep t) ~~ 'Just b,
                  HasTotalFieldP field (Rep (Indexed s)) ~~ 'Just a',
                  HasTotalFieldP field (Rep (Indexed t)) ~~ 'Just b',
                  t ~~ Infer s a' b, s ~~ Infer t b' a, HasField0 field s t a b) =>
                 HasField field s t a b
          -- Defined in ‘Data.Generics.Product.Fields’
        ...plus one instance involving out-of-scope types
        (use -fprint-potential-instances to see them all)
      (The choice depends on the instantiation of s0, t0, a
       To pick the first instance above, use IncoherentInstances
       when compiling the other instance declarations)
     In the second argument of (.), namely ‘#inner
      In the expression: #outer . #inner
      In an equation for g’: g = #outer . #inner
   |
11 | g = #outer . #inner
   |              ^^^^^^

Is this some known issue, and can it be worked around somehow? I think Lens'/HasField' is much more understandable to someone not familiar with optics, and really prefer using it whenever possible.

@friedbrice
Copy link

I doubt that it's fixable. It's similar to the problem of show . read. show . read can't compile because read gives a polymorphic output while show takes a polymorphic input, and there's no way for the compiler to infer the intermediate type.

@arybczak
Copy link
Contributor

It'll work with generic-optics (once #120 gets merged) since using % instead of . helps the compiler with type inference.

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