使用具有多个数据构造函数的相同镜头

Use the same lens with multiple data constructors

假设我有这样的类型:

data Stock = Stock {
               _stockSymbol :: String,
               _stockFairValue :: Float,
               _stockBuyAt :: Float,
               _stockCurrentPrice :: Float
             } |
             Etf {
               _etfSymbol :: String,
               _etfFairValue :: Float,
               _etfBuyAt :: Float,
               _etfCurrentPrice :: Float
             } deriving (Eq)

StockEtf 都有相同的字段。现在我想访问其中之一的符号:

item ^. symbol -- don't care if stock or etf

我可以用类型类做到这一点,但我想知道镜头包是否可以自动为我构建这个镜头?我看过 makeFields 函数,但如果我单独定义构造函数,它似乎可以工作:

data Stock = Stock { ... }
data Etf   = Etf { ... }

有什么方法可以做到这一点,同时让它们保持在同一类型下吗?

编辑:有效:

makeLensesFor [("_stockSymbol", "symbol"),
               ("_etfSymbol", "symbol"),
               ("_stockFairValue", "fairValue"),
               ("_etfFairValue", "fairValue"),
               ("_stockBuyAt", "buyAt"),
               ("_etfBuyAt", "buyAt"),
               ("_stockCurrentPrice", "currentPrice"),
               ("_etfCurrentPrice", "currentPrice")
               ] ''Stock

不确定是否有内置的方式让我不必写出字段。

不是不同意 bheklilr 的评论,但你可以这样做:

data Stock =
         Stock {
           _symbol :: String,
           _fairValue :: Float,
           _buyAt :: Float,
           _currentPrice :: Float
         } |
         Etf {
           _symbol :: String,
           _fairValue :: Float,
           _buyAt :: Float,
           _currentPrice :: Float
         } deriving (Eq)
$(makeLenses ''Stock)