1

I'd like to use Barbies-TH to create two Barbie records, where one is used as a field type in the other:

data Player = MkPlayer
  { playerLeft, playerRight, playerShoot, playerStart :: Bool
  } 

data Inputs = MkInputs
  { player1, player2 :: Player
  , dips :: BitVector 8
  , coin :: Bool
  } 

I can wrap the first one in declareBareB just fine:

import Barbies
import Barbies.Bare
import Barbies.TH

declareBareB [d|
  data Player = MkPlayer
    { playerLeft, playerRight, playerShoot, playerStart :: Bool
    } |]

However, because now the kind of Player is Type -> (Type -> Type) -> Type, I can't use it inside a declareBareB for Inputs, where the whole point is to pretend that there's no wrapper functor:

declareBareB [d|
  data Inputs = MkInputs
    { player1, player2 :: Player
    , dips :: BitVector 8
    , coin :: Bool
    } |]

This gives the, quite unsurprising, type error:

src/Hardware/SpaceInvaders/Input.hs:11:1: error:

     • Expecting two more arguments to ‘Player’
       Expected a type, but
       ‘Player’ has kind
       ‘Type -> (Type -> Type) -> Type’
     • In the third argument of ‘Wear’, namely ‘Player’
       In the type ‘(Wear sw_aRck h_aRcl Player)’
       In the definition of data constructor ‘MkInputs’
    |
 11 | declareBareB [d|
    | ^^^^^^^^^^^^^^^^...

What I'd like is to somehow propagate the clothes of Inputs to the Player, so that the type coming out of Barbies-TH would be

data Inputs cover f = MkInputs
    { player1, player2 :: Player cover f
    , dips :: Wear cover f (BitVector 8)
    , coin :: Wear cover f Bool
    }

(and NOT player1, player2 :: Wear cover f (Player Bare Identity))

Cactus
  • 27,075
  • 9
  • 69
  • 149
  • 1
    I expect there’s no way to do this with the basic Template Haskell API; you can pass multiple declarations in the `[d| … |]` quote, but it looks like the library just processes them all separately. Can you instead use the `Generic`/`DeriveAnyClass` API, writing the wrappers out explicitly but deriving all the other stuff? Or inline `Player` into `Inputs` (as 4 fields or 1 4-tuple) if you don’t need it to be separate. – Jon Purdy Nov 29 '20 at 05:39
  • @JonPurdy sure I could always just inline `Player`, but I'd rather not... – Cactus Nov 30 '20 at 03:02

0 Answers0