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

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