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

I like to barbie so I tried to barbie while I barbied; but I got a type error. #47

Closed
silky opened this issue Dec 18, 2023 · 7 comments
Closed

Comments

@silky
Copy link

silky commented Dec 18, 2023

I'm having trouble trying to wrap a barbie in a barbie, I think; but to me it's something htat seems pretty reasonable.

Consider:

data A' t f = A
    { name   :: Wear t f Int
    , thing  :: Wear t f [Wear t f Int]
    }
    deriving (Generic)
    
instance FunctorB (A' Bare)
instance FunctorB (A' Covered)

There is a type-error on the Covered instance:

<interactive>:7:10: error:
    • No instance for (barbies-2.0.4.0:Barbies.Generics.Functor.GFunctor
                         0
                         f
                         g
                         (Rec (barbies-2.0.4.0:Data.Generics.GenericN.Param 0 f [barbies-2.0.4.0:Data.Generics.GenericN.Param 0 f Int]) (f [f Int]))
                         (Rec (barbies-2.0.4.0:Data.Generics.GenericN.Param 0 g [barbies-2.0.4.0:Data.Generics.GenericN.Param 0 g Int]) (g [g Int])))
        arising from a use of ‘barbies-2.0.4.0:Barbies.Internal.FunctorB.$dmbmap’
    • In the expression: barbies-2.0.4.0:Barbies.Internal.FunctorB.$dmbmap @(*) @(A' Covered)
      In an equation for ‘bmap’: bmap = barbies-2.0.4.0:Barbies.Internal.FunctorB.$dmbmap @(*) @(A' Covered)
      In the instance declaration for ‘FunctorB (A' Covered)’

I'm not too sure how to go about solving this. Any advice would be appreciated!

Some more context: https://discourse.haskell.org/t/trouble-with-barbies/8344/4

@silky silky changed the title I like to barbie so I tried to barbie while barbie; but I got a type error. I like to barbie so I tried to barbie while I barbied; but I got a type error. Dec 18, 2023
@silky
Copy link
Author

silky commented Dec 18, 2023

Maybe this part of the documentation is relevant - https://hackage.haskell.org/package/barbies-2.0.0.0/docs/Barbies.html#g:3 - but the example doesn't compile, and the link to "see more" is empty 😅

@silky
Copy link
Author

silky commented Dec 18, 2023

data Person f

newtype Dependants f' f
  = Dependants { getDependants :: f' [Person f] }
  deriving (Generic)

instance Functor f' => FunctorB (Dependants f')
instance FunctorT Dependants

-- type Dependants f = Dependants f f
<interactive>:4:34: error:
    • Couldn't match kind ‘*’ with ‘k0 -> *’
      Expected kind ‘(k0 -> *) -> *’, but ‘Dependants f'’ has kind ‘* -> *’
    • In the first argument of ‘FunctorB’, namely ‘(Dependants f')’
      In the instance declaration for ‘FunctorB (Dependants f')’

@silky
Copy link
Author

silky commented Dec 18, 2023

Solved:

newtype Thing (f :: * -> *) =  Thing { getThing :: [f Int] }
  deriving (Generic, Typeable)

instance FunctorB Thing

deriving instance (Show (f Int)) => Show (Thing f)
deriving instance (Eq (f Int))   => Eq (Thing f)

data A' f' f = A
  { name  :: f' String
  , thing :: f' (Thing f) }
  deriving (Generic)

instance FunctorT A'
instance Functor f' => FunctorB (A' f')

deriving instance (Show (Thing f), Show (f' (Thing f)), Show (f' String)) => Show (A' f' f)

type A f = A' f f

a :: A Identity
a = A (pure "name") (pure $ Thing [pure 1, pure 2, pure 3])

b :: A Maybe
b = btmap1 (Just . runIdentity) a

@silky silky closed this as completed Dec 18, 2023
@silky silky reopened this Dec 19, 2023
@silky
Copy link
Author

silky commented Dec 19, 2023

The trouble is that only works at one level, if you then go and embed A' in another barbie in a similar style things break again:

newtype Thing (f :: * -> *) =  Thing { getThing :: [f Int] }
  deriving (Generic, FunctorB)

deriving instance (Show (f Int)) => Show (Thing f)

data A' f' f = A
  { name  :: f' String
  , thing :: f' (Thing f)
  }
  deriving (Generic)

instance FunctorT A'
instance Functor f' => FunctorB (A' f')

deriving instance (Show (f' (Thing f)), Show (f' String)) => Show (A' f' f)


newtype B' f'' f' f = B
  { someA :: f'' (A' f' f)
  }
  deriving Generic

type A f = A' f f
type B f = B' f f f

a :: A Identity
a = A (pure "name") (pure $ Thing [pure 1, pure 2, pure 3])

a' :: A Maybe
a' = btmap1 (Just . runIdentity) a

--b :: B Identity
--b = B a

The trouble is how to define the FunctorT/B instances; it just doesn't seem there's a way.

instance FunctorT B'

is clearly wrong, as B' has the wrong kind.

What are the options here?

Thanks!

@jcpetruzza
Copy link
Owner

jcpetruzza commented Dec 21, 2023

Hi @silky, sorry for the late reply. As you probably noticed, it is not possible to have a FunctorB instance for something like:

data Foo f = Foo (f [f Int]))

This is not a limitation of the library, but it's just not possible to write a manual instance either. If you try, you'll end up wth something similar to:

instance FunctorB Foo where
  bmap h (Foo ffis) = Foo (h <$> h ffis)  -- doesn't work since h :: (forall x. f a -> g a), and you don't have a Functor instance for g

If you only need one level of this, then using btmap1, as you saw, does the trick. But this doesn't generalize to more levels.

edit: removed alternative suggestion that wouldn't really work

@silky
Copy link
Author

silky commented Feb 25, 2024

Thanks for the response @jcpetruzza .

I'm revisiting this now and still looking around for an answer :) I tried barbies-layered but I didn't have much luck (there's no default bmap implementation and I wasn't sure what to write); now looking at the hypertypes library.

Would be lovely if there was a solution :)

@jcpetruzza
Copy link
Owner

As I said, I don't think you'll be able to make this work given the type of bmap.

One could define a different class hierarchy, e.g one where bmap requires a Functor constraint on the input or the output, and you'd be able to define your instances there, but that'd come with other trade-offs.

@jcpetruzza jcpetruzza closed this as not planned Won't fix, can't repro, duplicate, stale Feb 27, 2024
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

2 participants