If you want to define a read-only lens, you must use a type Getter. Let's look at a simple example first. You can access an item by index using the ^?and functions 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
So, this was an example of how you can use standard lenses to access indexed data structures. This knowledge should be enough to define your own indexed read-only, but I will give an extended example.
{-# 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)
Now in ghci you can use this 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
source
share