如何构建指向BaseketA及带名称Fruit的Prism透镜路径?
解决方案
要实现只修改BaseketA中Apple或Banana的名称,同时忽略Orange或BaseketB的需求,我们可以通过自定义Traversal并组合自动生成的棱镜来完成。
1. 自定义Traversal匹配带名称的Fruit
首先定义一个Traversal',专门针对Apple和Banana提取名称字段,对其他Fruit构造器直接返回原对象:
import Control.Lens _HasName :: Traversal' Fruit String _HasName f (Apple name num) = Apple <$> f name <*> pure num _HasName f (Banana name) = Banana <$> f name _HasName _ fruit = pure fruit
2. 组合路径并执行修改
将自动生成的_BaseketA棱镜与自定义的_HasName Traversal组合,使用over函数完成名称修改:
over (_BaseketA . _HasName) (\name -> name ++ " 's fruit ")
原理说明
_BaseketA是makePrism自动生成的棱镜,仅匹配Baseket类型的BaseketA构造器,提取其中的Fruit实例。_HasNameTraversal会识别Apple和Banana,提取它们的名称字段供修改;遇到Orange时直接返回原对象,不执行任何操作。- 两者组合后,只有
BaseketA包裹的Apple或Banana会被修改名称,其他场景(如BaseketB、BaseketA里的Orange)完全不受影响。
另一种方式:组合现有棱镜
如果你更倾向于使用自动生成的棱镜组合,可以用choice将_Apple和_Banana的名称路径合并:
over (_BaseketA . (_Apple . _1 `choice` _Banana)) (\name -> name ++ " 's fruit ")
这里_Apple . _1提取Apple的名称字段,_Banana直接提取Banana的名称,choice将两者合并为一个针对带名称Fruit的路径。
内容的提问来源于stack exchange,提问作者Shawn Zhang
相关产品推荐
相关产品推荐

