如何使用镜头在嵌套地图中设置值
How to set value in a nested Map using Lens
我有以下程序:
{-# LANGUAGE TemplateHaskell #-}
import qualified Data.Map.Strict as Map
import Control.Lens
data MyLabel = MyLabel { _label :: String } deriving (Show, Eq, Ord)
data MyMap = MyMap { _vals :: Map.Map String MyLabel } deriving (Show, Eq, Ord)
makeLenses ''MyLabel
makeLenses ''MyMap
sample :: MyMap
sample = MyMap { _vals = Map.fromList [("foo", MyLabel "bar")] }
现在我想知道如何使用镜头进行变换 f
,这样:
f sample "quux" == MyMap { _vals = Map.fromList [("foo", MyLabel "quux")] }
我了解到 Lens 库中的函数 at
应该用于修改地图,所以我尝试这样做:
sample ^. vals & at "foo" . label .~ Just "quux"
但这会产生一条我不太能理解的错误消息。正确的做法是什么?
试穿尺码:
{-# LANGUAGE TemplateHaskell #-}
module Main where
import qualified Data.Map.Strict as Map
import Control.Lens
data MyLabel =
MyLabel { _label :: String } deriving (Show, Eq, Ord)
data MyMap =
MyMap { _vals :: Map.Map String MyLabel } deriving (Show, Eq, Ord)
makeLenses ''MyLabel
makeLenses ''MyMap
sample :: MyMap
sample =
MyMap (Map.fromList [("foo", MyLabel "bar")])
main :: IO ()
main =
print (sample & (vals . at "foo" . _Just . label .~ "quux"))
请记住,在设置时,您正在尝试构建 MyMap -> MyMap
类型的函数。这样做的方法是将一堆光学器件链接在一起 (vals . at "foo" . _Just . label
),然后选择 setter 操作 (.~
)。您不能将 ^.
之类的 getter 操作与 .~
之类的 setter 操作混合搭配!所以每个 setter 或多或少看起来像这样:
foo' = (optic1 . optic2 . optic3 . optic4) .~ value $ foo
-- _________this has type Foo -> Foo___________
为了提高可读性,我们使用 &
,$
的翻转版本:
foo' = foo & (optic1 . optic2 . optic3 . optic4) .~ value
问题实际上是由 cabal hell 引起的,需要清理 ~/.ghc
目录才能使其正常工作。
我有以下程序:
{-# LANGUAGE TemplateHaskell #-}
import qualified Data.Map.Strict as Map
import Control.Lens
data MyLabel = MyLabel { _label :: String } deriving (Show, Eq, Ord)
data MyMap = MyMap { _vals :: Map.Map String MyLabel } deriving (Show, Eq, Ord)
makeLenses ''MyLabel
makeLenses ''MyMap
sample :: MyMap
sample = MyMap { _vals = Map.fromList [("foo", MyLabel "bar")] }
现在我想知道如何使用镜头进行变换 f
,这样:
f sample "quux" == MyMap { _vals = Map.fromList [("foo", MyLabel "quux")] }
我了解到 Lens 库中的函数 at
应该用于修改地图,所以我尝试这样做:
sample ^. vals & at "foo" . label .~ Just "quux"
但这会产生一条我不太能理解的错误消息。正确的做法是什么?
试穿尺码:
{-# LANGUAGE TemplateHaskell #-}
module Main where
import qualified Data.Map.Strict as Map
import Control.Lens
data MyLabel =
MyLabel { _label :: String } deriving (Show, Eq, Ord)
data MyMap =
MyMap { _vals :: Map.Map String MyLabel } deriving (Show, Eq, Ord)
makeLenses ''MyLabel
makeLenses ''MyMap
sample :: MyMap
sample =
MyMap (Map.fromList [("foo", MyLabel "bar")])
main :: IO ()
main =
print (sample & (vals . at "foo" . _Just . label .~ "quux"))
请记住,在设置时,您正在尝试构建 MyMap -> MyMap
类型的函数。这样做的方法是将一堆光学器件链接在一起 (vals . at "foo" . _Just . label
),然后选择 setter 操作 (.~
)。您不能将 ^.
之类的 getter 操作与 .~
之类的 setter 操作混合搭配!所以每个 setter 或多或少看起来像这样:
foo' = (optic1 . optic2 . optic3 . optic4) .~ value $ foo
-- _________this has type Foo -> Foo___________
为了提高可读性,我们使用 &
,$
的翻转版本:
foo' = foo & (optic1 . optic2 . optic3 . optic4) .~ value
问题实际上是由 cabal hell 引起的,需要清理 ~/.ghc
目录才能使其正常工作。