Haskell语言学习笔记(64)Lens

Posted zwvista

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Haskell语言学习笔记(64)Lens相关的知识,希望对你有一定的参考价值。

安装 lens-tutorial

Control.Lens.Tutorial

$ cabal install lens-tutorial
Installed lens-tutorial-1.0.3
Prelude> :m +Control.Lens.Tutorial
Prelude Control.Lens.Tutorial> 
{-# LANGUAGE TemplateHaskell   #-}
{-# LANGUAGE DeriveFoldable    #-}
{-# LANGUAGE DeriveFunctor     #-}
{-# LANGUAGE DeriveTraversable #-}
 
import Control.Applicative (Applicative)
import Control.Lens hiding (element)
import Data.Foldable (Foldable)
import Data.Monoid (Monoid)
 
data Atom = Atom { _element :: String, _point :: Point } deriving (Show)
data Point = Point { _x :: Double, _y :: Double } deriving (Show)
data Molecule = Molecule { _atoms :: [Atom] } deriving (Show)
data Pair a = Pair a a deriving (Functor, Foldable, Traversable)
makeLenses \'\'Atom
makeLenses \'\'Point
makeLenses \'\'Molecule

shiftAtomX :: Atom -> Atom
shiftAtomX = over (point . x) (+ 1)

shiftMoleculeX :: Molecule -> Molecule
shiftMoleculeX = over (atoms . traverse . point . x) (+ 1)

shift :: ASetter\' a Double -> a -> a
shift lens = over lens (+ 1)

Lens 的类型

type Lens\' a b = forall f . Functor f => (b -> f b) -> (a -> f a)
type ASetter\' a b   = (b -> Identity b) -> (a -> Identity a)
-- ... equivalent to: (b ->          b) -> (a ->          a)
type Getting b a b  = (b -> Const b b) -> (a -> Const b a)
-- ... equivalent to: (b ->       b  ) -> (a ->       b  )
--                                        (a ->       b  )

--    +-- Bigger type
--    |
--    v
Lens\' bigger smaller
--           ^
--           |
--           +--  Smaller type within the bigger type
element :: Lens\' Atom String
point   :: Lens\' Atom Point
x       :: Lens\' Point Double
y       :: Lens\' Point Double

-- lens :: (a -> b) -> (a -> b -> a) -> Lens\' a b
point2 :: Lens\' Atom Point
point2 = lens _point (\\atom newPoint -> atom { _point = newPoint })

-- point3 :: Lens\' Atom Point
point3 :: Functor f => (Point -> f Point) -> Atom -> f Atom
point3 k atom = fmap (\\newPoint -> atom { _point = newPoint }) (k (_point atom))
(.) :: Lens\' a b -> Lens\' b c -> Lens\' a c
type Lens\' a b = forall f . Functor f => (b -> f b) -> (a -> f a)
(.) :: Functor f
    => ((b -> f b) -> (a -> f a))
    -> ((c -> f c) -> (b -> f b))
    -> ((c -> f c) -> (a -> f a))
point     :: Lens\' Atom Point
x         :: Lens\' Point Double
point . x :: Lens\' Atom Double

view (point . x) :: Atom -> Double
over (point . x) :: (Double -> Double) -> (Atom -> Atom)
view :: Lens\' a b -> a -> b
over :: Lens\' a b -> (b -> b) -> a -> a
set  :: Lens\' a b ->       b  -> a -> a
set lens b = over lens (\\_ -> b)

view (lens1 . lens2) = (view lens2) . (view lens1)
view id = id
over (lens1 . lens2) = (over lens1) . (over lens2)
over id = id
type Traversal\' a b = forall f . Applicative f => (b -> f b) -> (a -> f a)
type Lens\'      a b = forall f . Functor     f => (b -> f b) -> (a -> f a)

atoms   :: Traversal\' Molecule [Atom]
element :: Traversal\' Atom     String
point   :: Traversal\' Atom     Point
x       :: Traversal\' Point    Double
y       :: Traversal\' Point    Double

traverse :: Traversable t => Traversal\' (t a) a
traverse :: (Applicative f, Traversable t) => (a -> f a) -> t a -> f (t a)
traverse :: Traversal\' [a] a

traverse :: Traversal\' (Pair a) a
over traverse :: (a -> a) -> (Pair a -> Pair a)
over traverse (+ 1) (Pair 3 4) = Pair 4 5

(.) :: Traversal\' a b -> Traversal\' b c -> Traversal\' a c
(.) :: Applicative f
    => ((b -> f b) -> (a -> f a))
    -> ((c -> f c) -> (b -> f b))
    -> ((c -> f c) -> (a -> f a))

-- Remember that `atoms`, `point`, and `x` are also `Traversal\'`s
atoms                        :: Traversal\' Molecule [Atom]
traverse                     :: Traversal\' [Atom]   Atom
point                        :: Traversal\' Atom     Point
x                            :: Traversal\' Point    Double

-- Now compose them
atoms                        :: Traversal\' Molecule [Atom]
atoms . traverse             :: Traversal\' Molecule Atom
atoms . traverse . point     :: Traversal\' Molecule Point
atoms . traverse . point . x :: Traversal\' Molecule Double

over (atoms . traverse . point . x)
    :: (Double -> Double) -> (Molecule -> Molecule)
toListOf (atoms . traverse . point . x)
    :: Molecule -> [Double]

toListOf :: Traversal\' a b -> a -> [b]
over :: Traversal\' a b -> (b -> b) -> a -> a
set  :: Traversal\' a b ->       b  -> a -> a
set traversal b = over traversal (\\_ -> b)

toListOf (traversal1 . traversal2) = (toListOf traversal1) >=> (toListOf traversal2)
toListOf id = return

参考链接

Taking a Close look at Lenses

以上是关于Haskell语言学习笔记(64)Lens的主要内容,如果未能解决你的问题,请参考以下文章

Haskell语言学习笔记(65)Lens

Haskell语言学习笔记(49)ByteString Text

如何在 Haskell 中比较镜头

Control.Lens 是不是有性能开销?

Haskell 光学库——Optics

Haskell语言学习笔记(69)Yesod