Haskell語言學習筆記(64)Lens(4)

Prisms

{-# LANGUAGE TemplateHaskell, RankNTypes #-}

import Control.Lens

data NewTask =
  SimpleTask String |
  HarderTask String Int |
  CompoundTask String [NewTask]
  deriving (Show)

makePrisms ''NewTask

a = SimpleTask "Clean"
b = HarderTask "Clean Kitchen" 15
c = CompoundTask "Clean House" [a,b]

自定義 prisms 的幾個步驟

  1. {-# LANGUAGE TemplateHaskell, RankNTypes #-}
    使用語言擴展
  2. import Control.Lens
    使用Lens庫
  3. data NewTask = SimpleTask | HarderTask | CompoundTask
    使用 data 關鍵字定義聯合類型。
  4. makePrisms ”NewTask
    使用 makePrisms ”TypeName 來定義 prisms。
  5. 注意這裏的情況和 makeLenses 正相反,字段名沒有帶下劃線,屬性名帶下劃線。
*Main> a ^? _SimpleTask
Just "Clean"
*Main> b ^? _HarderTask
Just ("Clean Kitchen",15)
*Main> b ^? _HarderTask._2
Just 15
*Main> b & _SimpleTask .~ "Clean Garage"
HarderTask "Clean Kitchen" 15
*Main> b & _HarderTask._2 .~ 30
HarderTask "Clean Kitchen" 30

手動計算 preview _Left (Left 5)

Prelude Control.Lens> preview _Left (Left 5)
Just 5
_Left = prism Left $ either Right (Left . Right)

prism bt seta = dimap seta (either pure (fmap bt)) . right'

instance Choice (->) where
  right' = fmap

preview l = getFirst . foldMapOf l (First . Just)

foldMapOf l f = getConst . l (Const . f)

instance Profunctor (->) where
  dimap ab cd bc = cd . bc . ab

instance Functor (Const m) where
    fmap _ (Const v) = Const v
preview _Left (Left 5)
= getFirst . foldMapOf _Left (First . Just) $ Left 5
= getFirst $ foldMapOf _Left (First . Just) $ Left 5
= getFirst $ getConst . _Left (Const . (First . Just)) $ Left 5
= getFirst $ getConst $ _Left (Const . (First . Just)) $ Left 5
= getFirst $ getConst $ prism Left (either Right (Left . Right)) (Const . First . Just) (Left 5)
= getFirst $ getConst $ (dimap (either Right (Left . Right)) (either pure (fmap Left)) . right') (Const . First . Just) (Left 5)
= ①

(dimap f g . h) x y
= (dimap f g $ h x) y
= g . (h x) . f $ y
= g . (h x) $ f y= getFirst $ getConst $ (either pure (fmap Left)) . (right' (Const . First . Just)) $ (either Right (Left . Right)) (Left 5)
= getFirst $ getConst $ (either pure (fmap Left)) . (right' (Const . First . Just)) $ (Right 5)
= getFirst $ getConst $ (either pure (fmap Left)) $ right' (Const . First . Just) (Right 5)
= getFirst $ getConst $ (either pure (fmap Left)) $ fmap (Const . First . Just) (Right 5)
= getFirst $ getConst $ (either pure (fmap Left)) $ Right (Const . First $ Just 5)
= getFirst $ getConst $ fmap Left (Const . First $ Just 5)
= getFirst $ getConst $ fmap Left (Const . First $ Just 5)
= getFirst $ getConst $ Const . First $ Just 5
= Just 5

參考鏈接

Haskell語言學習筆記(38)Lens(1)
Haskell語言學習筆記(44)Lens(2)
Haskell語言學習筆記(56)Lens(3)
Taking a Close look at Lenses

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章