File tree 6 files changed +187
-0
lines changed
6 files changed +187
-0
lines changed Original file line number Diff line number Diff line change 1
1
node_modules
2
2
* .log
3
3
.DS_Store
4
+ * .hi
5
+ * .o
6
+ * .dyn_hi
7
+ * .dyn_o
Original file line number Diff line number Diff line change
1
+ -- cabal install template-haskell
2
+ --
3
+ -- Lens is implementation of most common of optics.
4
+ --
5
+ -- Real makeLens implementation more complex supporting all of Haskell syntax
6
+ -- cases for creating types.
7
+ --
8
+ {-# LANGUAGE Rank2Types #-}
9
+ {-# LANGUAGE TemplateHaskell #-}
10
+ module Lens where
11
+
12
+ import Language.Haskell.TH
13
+
14
+ type Lens s t a b = forall f . Functor f = > (a -> f b ) -> s -> f t
15
+ type Lens' s a = Lens s s a a
16
+
17
+ lens :: (s -> a ) -> (s -> b -> t ) -> Lens s t a b
18
+ lens getter setter = \ afb s -> setter s <$> afb (getter s)
19
+
20
+ fieldLens :: Name -> (Name , a , Type ) -> Q [Dec ]
21
+ fieldLens s (v, _, a) = do
22
+ sVar <- newName " s"
23
+ bVar <- newName " b"
24
+ let setter = return $ LamE [VarP sVar, VarP bVar] $ RecUpdE (VarE sVar) [(v, VarE bVar)]
25
+ body <- NormalB <$> [| lens $ (return $ VarE v) $ setter | ]
26
+ let fn = mkName $ tail $ nameBase v
27
+ return [ SigD fn (AppT (AppT (ConT $ mkName " Lens'" ) (ConT s)) a)
28
+ , FunD fn [Clause [] body [] ]
29
+ ]
30
+
31
+ makeLens :: Name -> Q [Dec ]
32
+ makeLens s = do
33
+ (TyConI (DataD _ _ _ _ [RecC _ cs] _)) <- reify s
34
+ concat <$> mapM (fieldLens s) cs
Original file line number Diff line number Diff line change
1
+ --
2
+ -- cabal install template-haskell
3
+ -- ghc 1-lens.hs 2-view.hs -o 2-view
4
+ -- ./2-view
5
+ --
6
+ {-# LANGUAGE Rank2Types #-}
7
+ {-# LANGUAGE TemplateHaskell #-}
8
+ import Data.Functor.Const (Const (.. ))
9
+ import Text.Printf (printf )
10
+
11
+ import Lens
12
+
13
+ view :: Lens s t a b -> s -> a
14
+ view l s = getConst $ l Const s
15
+
16
+ data City = City
17
+ { _cityName :: String
18
+ , _country :: String
19
+ , _inEU :: Bool
20
+ } deriving Show
21
+ $ (makeLens ''City)
22
+
23
+ data Person = Person
24
+ { _name :: String
25
+ , _city :: City
26
+ , _born :: Int
27
+ } deriving Show
28
+ $ (makeLens ''Person)
29
+
30
+ person = Person " Marcus Aurelius" (City " Rome" " Italy" True ) 121
31
+
32
+ main = printf " view country of the city person was born in: %v\n "
33
+ $ view (city . country) person
Original file line number Diff line number Diff line change
1
+ --
2
+ -- cabal install template-haskell
3
+ -- ghc 1-lens.hs 3-set.hs -o 3-set
4
+ -- ./3-set
5
+ --
6
+ {-# LANGUAGE Rank2Types #-}
7
+ {-# LANGUAGE TemplateHaskell #-}
8
+ import Data.Functor.Identity (Identity (.. ))
9
+ import Text.Printf (printf )
10
+
11
+ import Lens
12
+
13
+ set :: Lens' s a -> a -> s -> s
14
+ set l a s = runIdentity $ l (Identity . const a) s
15
+
16
+ data City = City
17
+ { _cityName :: String
18
+ , _country :: String
19
+ , _inEU :: Bool
20
+ } deriving Show
21
+ $ (makeLens ''City)
22
+
23
+ data Person = Person
24
+ { _name :: String
25
+ , _city :: City
26
+ , _born :: Int
27
+ } deriving Show
28
+ $ (makeLens ''Person)
29
+
30
+ person = Person " Marcus Aurelius" (City " Rome" " Italy" True ) 121
31
+
32
+ main = printf " set inEU of the city person was born in: %v\n "
33
+ $ show $ set (city . inEU) False person
Original file line number Diff line number Diff line change
1
+ --
2
+ -- cabal install template-haskell
3
+ -- ghc 1-lens.hs 4-over.hs -o 4-over
4
+ -- ./4-over
5
+ --
6
+ {-# LANGUAGE Rank2Types #-}
7
+ {-# LANGUAGE TemplateHaskell #-}
8
+
9
+ import Data.Char (toUpper )
10
+ import Data.Functor.Identity (Identity (.. ))
11
+ import Text.Printf (printf )
12
+
13
+ import Lens
14
+
15
+ over :: Lens' s a -> (a -> a ) -> s -> s
16
+ over l ab s = runIdentity $ l (Identity . ab) s
17
+
18
+ data City = City
19
+ { _cityName :: String
20
+ , _country :: String
21
+ , _inEU :: Bool
22
+ } deriving Show
23
+ $ (makeLens ''City)
24
+
25
+ data Person = Person
26
+ { _name :: String
27
+ , _city :: City
28
+ , _born :: Int
29
+ } deriving Show
30
+ $ (makeLens ''Person)
31
+
32
+ person = Person " Marcus Aurelius" (City " Rome" " Italy" True ) 121
33
+
34
+ main = printf " over name of the city person was born in: %v\n "
35
+ $ show $ over (city . cityName) (map toUpper) person
Original file line number Diff line number Diff line change
1
+ --
2
+ -- cabal install template-haskell
3
+ -- ghc 1-lens.hs 5-together.hs -o 5-together
4
+ -- ./5-together
5
+ --
6
+ {-# LANGUAGE Rank2Types #-}
7
+ {-# LANGUAGE TemplateHaskell #-}
8
+
9
+ import Data.Char (toUpper )
10
+ import Data.Functor.Const (Const (.. ))
11
+ import Data.Functor.Identity (Identity (.. ))
12
+ import Text.Printf (printf )
13
+
14
+ import Lens
15
+
16
+ view :: Lens s t a b -> s -> a
17
+ view l s = getConst $ l Const s
18
+
19
+ set :: Lens' s a -> a -> s -> s
20
+ set l a s = runIdentity $ l (Identity . const a) s
21
+
22
+ over :: Lens' s a -> (a -> a ) -> s -> s
23
+ over l ab s = runIdentity $ l (Identity . ab) s
24
+
25
+ data City = City
26
+ { _cityName :: String
27
+ , _country :: String
28
+ , _inEU :: Bool
29
+ } deriving Show
30
+ $ (makeLens ''City)
31
+
32
+ data Person = Person
33
+ { _name :: String
34
+ , _city :: City
35
+ , _born :: Int
36
+ } deriving Show
37
+ $ (makeLens ''Person)
38
+
39
+ person = Person " Marcus Aurelius" (City " Rome" " Italy" True ) 121
40
+
41
+
42
+ main = do
43
+ printf " view country of the city person was born in: %v\n "
44
+ $ view (city . country) person
45
+ printf " set inEU of the city person was born in: %v\n "
46
+ $ show $ set (city . inEU) False person
47
+ printf " over name of the city person was born in: %v\n "
48
+ $ show $ over (city . cityName) (map toUpper) person
You can’t perform that action at this time.
0 commit comments