如何在纯脚本中使用镜头在 ADT 之间进行转换?
How to convert between ADTs with lenses in purescript?
这是我想要完成的工作但简化的示例代码。我想从一种类型的包装记录映射到另一种类型:
import Prelude
import Data.Lens
import Data.String as String
newtype AsString = AsString { names :: Array String }
newtype AsSize = AsSize { names :: Array Int }
_names = lens _.names (_ { names = _ })
to_sizes :: AsString -> AsSize
to_sizes (AsString s) = AsSize $ over (_names <<< traversed) String.length s
如何在不先打开唱片的情况下仅对镜头执行相同的操作?
当使用 lens (\(AsString s) -> s) (const AsString)
这样的镜头作为原始类型时,我猜它希望结果是原始类型?
我想我通过实验找到了答案:
import Prelude
import Data.Lens
import Data.String as String
newtype AsString = AsString { names :: Array String }
newtype AsSize = AsSize { names :: Array Int }
_ToSize = lens (\(AsString s) -> s) (const AsSize)
_names = lens _.names (_ { names = _ })
to_sizes :: AsString -> AsSize
to_sizes s = over (_ToSize <<< _names <<< traversed) String.length s
(const AsSize)
好像"mirror" 原来的记录变成了新的类型。
我不确定您是否会对这个答案感到满意,因为我还建议在这里进行一些重构...
如果您不满意,请告诉我,我将尝试在不涉及您的类型的情况下提供基于以下镜头的代码示例;-)
您能接受如下更改 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) _
此class提供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)
P.S.
如果我正在修改相同的类型,我也经常写这个来简化类型推断:
_Newtype' ∷ ∀ s a. (Newtype s a) ⇒ Iso' s a
_Newtype' = iso unwrap wrap
这是我想要完成的工作但简化的示例代码。我想从一种类型的包装记录映射到另一种类型:
import Prelude
import Data.Lens
import Data.String as String
newtype AsString = AsString { names :: Array String }
newtype AsSize = AsSize { names :: Array Int }
_names = lens _.names (_ { names = _ })
to_sizes :: AsString -> AsSize
to_sizes (AsString s) = AsSize $ over (_names <<< traversed) String.length s
如何在不先打开唱片的情况下仅对镜头执行相同的操作?
当使用 lens (\(AsString s) -> s) (const AsString)
这样的镜头作为原始类型时,我猜它希望结果是原始类型?
我想我通过实验找到了答案:
import Prelude
import Data.Lens
import Data.String as String
newtype AsString = AsString { names :: Array String }
newtype AsSize = AsSize { names :: Array Int }
_ToSize = lens (\(AsString s) -> s) (const AsSize)
_names = lens _.names (_ { names = _ })
to_sizes :: AsString -> AsSize
to_sizes s = over (_ToSize <<< _names <<< traversed) String.length s
(const AsSize)
好像"mirror" 原来的记录变成了新的类型。
我不确定您是否会对这个答案感到满意,因为我还建议在这里进行一些重构... 如果您不满意,请告诉我,我将尝试在不涉及您的类型的情况下提供基于以下镜头的代码示例;-)
您能接受如下更改 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) _
此class提供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)
P.S.
如果我正在修改相同的类型,我也经常写这个来简化类型推断:
_Newtype' ∷ ∀ s a. (Newtype s a) ⇒ Iso' s a
_Newtype' = iso unwrap wrap