访问 sum 类型字段的镜头

问题描述 投票:0回答:2

例如,这里是 sum 类型

 data Fruit = Apple Int Color Date
            | Banana Color Date

Date
是购买日期,但它位于
different location
中,代表
Apple
Banana
。我可以通过
makePrisms ''Fruit

制作 Prism

是否可以创建一个像这样的镜头:

purchaseDate :: Lens Fruit Date

然后我可以轻松地

get/set/modify
在购买日期购买所有水果(苹果和香蕉)?

我认为这与如何为总和类型编写镜头不同,因为字段位置不同“日期”位于值构造函数的不同位置

haskell haskell-lens
2个回答
2
投票

如果您为字段提供通用名称,则

makeLenses
将生成适当的镜头。 也就是说,之后:

data Color = Red | Yellow deriving (Show)
newtype Date = Date Int deriving (Show)

data Fruit = Apple { _tree :: Int
                   , _color :: Color
                   , _date :: Date }
           | Banana { _color :: Color
                    , _date :: Date }
           deriving (Show)

makeLenses ''Fruit

会有

color
date
镜片:

λ> :t date
date :: Lens' Fruit Date
λ> Apple 1 Red (Date 20241217) ^. date
Date 20241217
λ> Banana Yellow (Date 20250101) ^. date
Date 20250101

对于不常见的字段,例如

tree
,它们将被进行遍历:

λ> :t tree
tree :: Traversal' Fruit Int

0
投票

写镜头非常机械;这就是

makeLenses
存在的原因。但如果
makeLenses
不能完全实现您想要的效果,那么您当然可以自由地手写您最喜欢的变体!

purchaseDate :: Lens' Fruit Date
purchaseDate f = \case
    Apple i c d -> Apple i c <$> f d
    Banana c d -> Banana c <$> f d

用于提取颜色的镜头非常相似,尽管由于相当无趣的原因在语法上略有噪音。

fruitColor :: Lens' Fruit Color
fruitColor f = \case
    Apple i c d -> f c <&> \c' -> Apple i c' d
    Banana c d -> f c <&> \c' -> Banana c' d
© www.soinside.com 2019 - 2024. All rights reserved.