gpt4 book ai didi

haskell - 有没有直接的方法将多个记录字段的 setter 组合到一个 setter ?

转载 作者:行者123 更新时间:2023-12-03 14:41:39 27 4
gpt4 key购买 nike

import Control.Lens
import Control.Lens.TH

data Foo = Foo {
_bar, _baz :: Int
}
makeLenses ''Foo

现在,如果我想修改两个 int 字段,我可以这样做
barbaz :: Setter' Foo Int
barbaz = sets $ \foo f -> foo & bar %~ f
& baz %~ f

但这似乎是一种非常丑陋的手动方式。

可以直接使用镜头/箭头组合器实现相同的效果吗?

最佳答案

lens 不是现成的组合器,大概是因为如果组件的焦点重叠,您可以获得非法 setter (或镜头)。

data Trio a = Trio a a a
deriving (Show)

oneTwo :: Setter' (Trio a) (a, a)
oneTwo = sets $ \f (Trio x y z) -> let (x', y') = f (x, y) in Trio x' y' z

twoThree :: Setter' (Trio a) (a, a)
twoThree = sets $ \f (Trio x y z) -> let (y', z') = f (y, z) in Trio x y' z'

cheating :: Setter' (Trio a) (a, a)
cheating = sets $ \f x -> x & oneTwo %~ f & twoThree %~ f
GHCi> Trio 1 1 1 & cheating %~ bimap (2*) (2*) & cheating %~ bimap (3+) (3+)
Trio 5 10 5
GHCi> Trio 1 1 1 & cheating %~ (bimap (2*) (2*) <&> bimap (3+) (3+))
Trio 5 13 5

在您的情况下,手动build设置器/遍历的最佳替代方法(正如您 and Cristoph Hegemann 正在做的那样)似乎是 liftA2 (>=>) :: ASetter' s a -> ASetter' s a -> ASetter' s a ,正如 bennofs 在别处所建议的那样(感谢 Shersh 的链接)。如果你碰巧有一个同质对(或其他一些 Bitraversable )的镜头,你可以使用 both 进行遍历。 :
data Foo = Foo
{ _bar, _baz :: Int
} deriving (Show)
makeLenses ''Foo

barBaz :: Iso' Foo (Int, Int)
barBaz = iso ((,) <$> view bar <*> view baz) (Foo <$> fst <*> snd)
GHCi> Foo 1 2 & barBaz . both %~ (2*)
Foo {_bar = 2, _baz = 4}

还有一种可能性是利用 Data.Data.Lens 获取某种类型的所有字段的遍历:
{-# LANGUAGE DeriveDataTypeable #-}

import Control.Lens
import Data.Data.Lens
import Data.Data

data Foo = Foo
{ _bar, _baz :: Int
} deriving (Show, Data, Typeable)
makeLenses ''Foo

barBaz :: Traversal' Foo Int
barBaz = template
GHCi> Foo 1 2 & barBaz %~ (2*)
Foo {_bar = 2, _baz = 4}

关于haskell - 有没有直接的方法将多个记录字段的 setter 组合到一个 setter ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42784819/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com