haskell – 我应该用什么镜头来建立一个只读的getter getter?

我有一个隐藏内部细节的类型.我想提供某种镜头,可以在特定索引处读取所述类型的元素,但不能修改它们.我的类型的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
点赞