如何为Sum Type中不同位置的Date字段创建统一Lens?
如何为Sum Type中位置不同的字段创建统一Lens?
当然可以创建这样的purchaseDate Lens,核心思路是针对每个构造子分别实现Date的提取(get)和替换(set)逻辑,不管Date在构造子中的位置差异。
手动实现方式
借助Control.Lens中的lens函数,我们可以直接为Fruit类型编写统一的日期操作Lens:
import Control.Lens data Color = Red | Green deriving (Show) data Date = Date Int Int Int deriving (Show) data Fruit = Apple Int Color Date | Banana Color Date deriving (Show) -- 你已经生成的Prism makePrisms ''Fruit purchaseDate :: Lens' Fruit Date purchaseDate = lens getPurchaseDate setPurchaseDate where -- 从不同构造子中提取Date getPurchaseDate (Apple _ _ date) = date getPurchaseDate (Banana _ date) = date -- 为不同构造子替换Date setPurchaseDate (Apple num col _) newDate = Apple num col newDate setPurchaseDate (Banana col _) newDate = Banana col newDate
使用示例
定义好Lens后,就可以像操作普通字段一样统一处理所有水果的购买日期:
-- 示例数据 sampleApple = Apple 10 Red (Date 2024 5 20) sampleBanana = Banana Green (Date 2024 5 21) -- 获取购买日期 view purchaseDate sampleApple -- 返回 Date 2024 5 20 view purchaseDate sampleBanana -- 返回 Date 2024 5 21 -- 修改购买日期(比如将日期加1天) addOneDay (Date y m d) = Date y m (d + 1) over purchaseDate addOneDay sampleApple -- 得到 Apple 10 Red (Date 2024 5 21)
关键说明
只要Sum Type的所有构造子都包含目标字段(这里是Date),就可以通过这种方式创建统一Lens。如果存在不含目标字段的构造子,这类Lens就无法定义(因为get操作会有未覆盖的分支),但你的场景中两个构造子都包含Date,所以完全可行。
内容的提问来源于stack exchange,提问作者Shawn Zhang
相关产品推荐
相关产品推荐

