6

If I have two modules that both use Control.Lens.TH' makeFields to generate fields from a record, and a record in each of the different modules has the same field name, what's the best way of ensuring that the two modules are using the same definition of the name lens and the HasName class without having one of the modules depend on the other?

At the moment, I'm using another module named SharedFields with a single record with every field that needs shared, and then importing the SharedFields module in anything else that needs TH fields generated – but this is awkward and error-prone.

module First where

import Control.Lens

data First = First { firstName :: Bool }
  deriving (Read, Show, Eq)
makeFields ''First

module Second where

import Control.Lens

data Second = Second { secondName :: () }
  deriving (Read, Show, Eq)
makeFields ''Second

module Third (name) where

import First
import Second
bheklilr
  • 53,530
  • 6
  • 107
  • 163
Fraser
  • 1,521
  • 2
  • 14
  • 23
  • Have you tried manually defining the `HasName` class in another module imported by both `First` and `Second`? That would seem idiomatic to me, and I think the Lens TH would use the existing class. – Christian Conkle Oct 01 '14 at 17:55
  • It works, but it's awkward having to manually define the classes for each field. Another TH function for splicing in each name would be better, but ideally I wouldn't have to list out *every* shared field name that's in my library – Fraser Oct 01 '14 at 18:12
  • The problem is that the shared classes need to be defined in a module imported by both `First` and `Second`--you can't have "the same definition" defined in two modules. And of course that module can't know what fields are in either `First` or `Second` without getting into an impossible circularity problem. – Christian Conkle Oct 01 '14 at 20:19
  • Incidentally, I notice that I've just been echoing your second paragraph back to you. Sorry. – Christian Conkle Oct 01 '14 at 20:28
  • I encountered this same problem and resorted to a writing a bunch of gross Template Haskell. I ended up with a function that checks for the lens class and defines it if it doesn't exist yet. https://github.com/tfausak/strive/blob/v1.0.1/library/Strive/Internal/TH.hs#L46 – Taylor Fausak Jun 05 '15 at 13:27
  • I actually made a simple library that does exactly this: https://github.com/intolerable/shared-fields – Fraser Jun 05 '15 at 20:36

0 Answers0