You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为非记录newtype类型生成命名Lens?

两种实现命名Lens的简洁方案

用Lens组合子直接实现

你想的简洁写法思路是对的,只需借助lens库自带的_Wrapped组合子处理newtype的拆包,最终可以写成:

import Control.Lens

bar :: Lens' Foo Int
bar = _Wrapped . _1

_Wrapped是Wrapped类型类提供的Lens,专门用来访问newtype包裹的内部值,和元组的_1组合后,就直接实现了访问Foo内部元组第一个元素的Lens,完全不用手动写lens函数的getter和setter。

如果要访问第二个元素的String,同理可以写:

baz :: Lens' Foo String
baz = _Wrapped . _2

用Template Haskell自动生成

如果想进一步自动化,甚至不用自己写组合代码,可以用lens库的Template Haskell功能:

  1. 先启用Template Haskell扩展,在文件顶部添加:
{-# LANGUAGE TemplateHaskell #-}
  1. 导入TH相关模块:
import Control.Lens.TH
  1. 给你的Foo类型自动生成_Wrapped Lens:
newtype Foo = Foo (Int, String)
makeWrapped ''Foo

执行这行TH代码后,会自动生成_Wrapped :: Lens' Foo (Int, String),之后你还是可以像之前一样用_Wrapped . _1定义bar。

另外,如果你愿意把newtype改成记录语法,还能让TH直接生成对应内部结构的基础Lens:

newtype Foo = Foo { unFoo :: (Int, String) }
makeLenses ''Foo

这样会生成unFoo :: Lens' Foo (Int, String),同样可以和_1组合得到bar,这属于记录式newtype的用法,可根据需求选择。

内容的提问来源于stack exchange,提问作者majkrzak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 14:08:18