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 的幾個步驟
- {-# LANGUAGE TemplateHaskell, RankNTypes #-}
使用語言擴展 - import Control.Lens
使用Lens庫 - data NewTask = SimpleTask | HarderTask | CompoundTask
使用 data 關鍵字定義聯合類型。 - makePrisms ”NewTask
使用 makePrisms ”TypeName 來定義 prisms。 - 注意這裏的情況和 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