我不确定您是否会对这个答案感到满意,因为我还建议在这里进行一些重构......
如果您不满意,请告诉我,我将尝试根据以下镜头提供代码示例,而不涉及您的类型;-)
您是否可以接受如下更改AsString 和AsSize?
newtype Names a = Names { names :: Array a }
type AsString = Names String
type AsSize = Names Int
这种重构将稍微简化操作并使您的类型更具可重用性。我真的很推荐这个关于类型参数的力量的演讲:https://www.youtube.com/watch?v=BHjIl81HgfE)。
对于names 字段,我们可以使用通用prop 函数创建镜头。
关于Name 类型,我们首先应该派生Newtype 实例(请注意这个派生的非常具体的语法 - 我认为_ 类型编译器自己推断):
newtype Names a = Names { names :: Array a }
derive instance newtypeNames ∷ Newtype (Names a) _
这个类提供wrap 和unwrap 方法,供_Newtype 镜头使用。所以我们现在可以使用_Newtype 镜头。
最后你应该能够组合这两个。我们开始:
module Main where
import Prelude
import Data.Lens (over, traversed)
import Data.Lens.Iso.Newtype (_Newtype)
import Data.Lens.Record (prop)
import Data.Newtype (class Newtype)
import Data.String as String
import Type.Prelude (SProxy(..))
newtype Names a = Names { names :: Array a }
derive instance newtypeNames ∷ Newtype (Names a) _
type AsString = Names String
type AsSize = Names Int
_names = prop (SProxy ∷ SProxy "names")
toSizes :: AsString -> AsSize
toSizes = over (_Newtype <<< _names <<< traversed) (String.length)
附言
如果我修改相同的类型,我也经常写这个来简化类型推断:
_Newtype' ∷ ∀ s a. (Newtype s a) ⇒ Iso' s a
_Newtype' = iso unwrap wrap