2017-08-24 100 views
1

我能以恆定的指標,像這樣創建列表的IndexedTraversal混淆組成索引鏡頭

constIndex :: i -> Lens.AnIndexedLens i a b a b 
constIndex index f = Lens.indexed f index 

constIndexedList :: i -> Lens.AnIndexedTraversal i [a] [b] a b 
constIndexedList index = Lens.cloneLens (constIndex index) <. traverse 

然而這樣的:

constIndexedList :: i -> Lens.AnIndexedTraversal i [a] [b] a b 
constIndexedList _ _ [] = pure [] 
constIndexedList index f (x:xs) = (:) <$> Lens.indexed f index x <*> constListIndex index f xs 

我寧願通過組合2簡單的鏡頭創建無法類型檢查,並從lens類型錯誤不是我很容易明白的:

• Couldn't match type ‘Lens.Indexed 
         i (t0 a) (Lens.Bazaar (Lens.Indexed i) a b (t0 b))’ 
       with ‘[a] -> Lens.Bazaar (Lens.Indexed i) a b [b]’ 
    Expected type: Lens.Indexed 
        i (t0 a) (Lens.Bazaar (Lens.Indexed i) a b (t0 b)) 
       -> [a] -> Lens.Bazaar (Lens.Indexed i) a b [b] 
    Actual type: ([a] -> Lens.Bazaar (Lens.Indexed i) a b [b]) 
       -> [a] -> Lens.Bazaar (Lens.Indexed i) a b [b] 
• In the first argument of ‘(<.)’, namely 
    ‘Lens.cloneLens (constIndex index)’ 
    In the expression: Lens.cloneLens (constIndex index) <. traverse 

爲什麼我不能像這樣組成索引鏡頭?

我最終找到一個不同的模塊化的方式來做到這一點(Lens.reindexed (const index) Lens.traversed,但我仍然不知道爲什麼上面提到的方法不起作用..

回答

2

(<.)預計其索引視神經離開,但cloneLens給它未編制索引的透鏡。

一個部分解決辦法是使用Lens.cloneIndexedLens代替cloneLens

但是,光學器件的A_/An_變體(AnIndexedLens)意味着是參數類型,而不是結果類型,它們可以使用常規光學器件(IndexedLens)。因此,cloneIndexedLens變得不必要。

constIndex :: i -> Lens.IndexedLens i a b a b 
constIndex i f = Lens.indexed f i 

constIndexedList :: i -> Lens.IndexedTraversal i [a] [b] a b 
constIndexedList i = constIndex i <. traverse 

單形的輸入和輸出的多態提高可組合。

IndexedLens是一個多態類型(請注意類型定義中的forall關鍵字)。

type IndexedLens i s t a b = forall f p. (Indexable i p, Functor f) => p a (f b) -> s -> f t 

AnIndexedLens是單形的。

type AnIndexedLens i s t a b = Optical (Indexed i) (->) (Pretext (Indexed i) a b) s t a b 

IndexedLensAnIndexedLens,但轉換的其他方式必須經過明確cloneIndexedLens