我应该使用什么 in lens 来按索引构建只读 getter?
What in lens should I use to build a read-only getter by index?
我有一个内部细节被隐藏的类型。我想提供某种镜头,可以在特定索引处从所述类型读取元素,但 不会 修改它们。我的类型的 Ixed
实例似乎没有做我想做的事,因为它明确允许修改(尽管不允许插入或删除)。如果我想允许只读索引,我不确定我使用什么。
如果你想定义只读镜头你应该使用Getter
类型。让我们首先考虑简单的例子。您可以使用 ^?
和 ix
函数按索引访问元素。
λ: [1..] ^? ix 10
Just 11
λ: import qualified Data.Map as M
λ: M.empty ^? ix 'a'
Nothing
λ: M.singleton 'a' 3 ^? ix 'a'
Just 3
所以这是一个如何使用标准镜头访问索引数据结构的示例。这些知识应该足以定义您自己的只读索引 getter 但我将给出扩展示例。
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data MyData = MkData
{ _innerList :: [Int]
, _dummyField :: Double
}
makeLenses ''MyData
indexedGetter :: Int -> Getter MyData (Maybe Int)
indexedGetter i = innerList . to (^? ix i)
现在在 ghci 中你可以使用这个 getter。
λ: let exampleData = MkData [2, 1, 3] 0.3
λ: exampleData ^. indexedGetter 0
Just 2
λ: exampleData & indexedGetter 0 .~ Just 100
<interactive>:7:15:
No instance for (Contravariant Identity)
arising from a use of ‘indexedGetter’
In the first argument of ‘(.~)’, namely ‘indexedGetter 0’
In the second argument of ‘(&)’, namely
‘indexedGetter 0 .~ Just 100’
In the expression: exampleData & indexedGetter 0 .~ Just 100
我有一个内部细节被隐藏的类型。我想提供某种镜头,可以在特定索引处从所述类型读取元素,但 不会 修改它们。我的类型的 Ixed
实例似乎没有做我想做的事,因为它明确允许修改(尽管不允许插入或删除)。如果我想允许只读索引,我不确定我使用什么。
如果你想定义只读镜头你应该使用Getter
类型。让我们首先考虑简单的例子。您可以使用 ^?
和 ix
函数按索引访问元素。
λ: [1..] ^? ix 10
Just 11
λ: import qualified Data.Map as M
λ: M.empty ^? ix 'a'
Nothing
λ: M.singleton 'a' 3 ^? ix 'a'
Just 3
所以这是一个如何使用标准镜头访问索引数据结构的示例。这些知识应该足以定义您自己的只读索引 getter 但我将给出扩展示例。
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data MyData = MkData
{ _innerList :: [Int]
, _dummyField :: Double
}
makeLenses ''MyData
indexedGetter :: Int -> Getter MyData (Maybe Int)
indexedGetter i = innerList . to (^? ix i)
现在在 ghci 中你可以使用这个 getter。
λ: let exampleData = MkData [2, 1, 3] 0.3
λ: exampleData ^. indexedGetter 0
Just 2
λ: exampleData & indexedGetter 0 .~ Just 100
<interactive>:7:15:
No instance for (Contravariant Identity)
arising from a use of ‘indexedGetter’
In the first argument of ‘(.~)’, namely ‘indexedGetter 0’
In the second argument of ‘(&)’, namely
‘indexedGetter 0 .~ Just 100’
In the expression: exampleData & indexedGetter 0 .~ Just 100