Reputation: 15882
Suppose I have a type like this:
data Stock = Stock {
_stockSymbol :: String,
_stockFairValue :: Float,
_stockBuyAt :: Float,
_stockCurrentPrice :: Float
} |
Etf {
_etfSymbol :: String,
_etfFairValue :: Float,
_etfBuyAt :: Float,
_etfCurrentPrice :: Float
} deriving (Eq)
Stock
and Etf
both have the same fields. Now I want to access the symbol for one of them:
item ^. symbol -- don't care if stock or etf
I can do this with a typeclass, but I'm wondering if the lens package can build this lens for my automatically? I have looked at the makeFields
function, but it seems that works if I have the constructors defined separately:
data Stock = Stock { ... }
data Etf = Etf { ... }
Is there any way to do this while keeping them under the same type?
Edit: This works:
makeLensesFor [("_stockSymbol", "symbol"),
("_etfSymbol", "symbol"),
("_stockFairValue", "fairValue"),
("_etfFairValue", "fairValue"),
("_stockBuyAt", "buyAt"),
("_etfBuyAt", "buyAt"),
("_stockCurrentPrice", "currentPrice"),
("_etfCurrentPrice", "currentPrice")
] ''Stock
Not sure if there's a built-in way where I don't have to write the fields out.
Upvotes: 3
Views: 462
Reputation: 15029
Not to disagree with bheklilr's comment, but you could just do this:
data Stock =
Stock {
_symbol :: String,
_fairValue :: Float,
_buyAt :: Float,
_currentPrice :: Float
} |
Etf {
_symbol :: String,
_fairValue :: Float,
_buyAt :: Float,
_currentPrice :: Float
} deriving (Eq)
$(makeLenses ''Stock)
Upvotes: 2