-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathFluentApi.hs
125 lines (92 loc) · 3.17 KB
/
FluentApi.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
{-# LANGUAGE FlexibleInstances, InstanceSigs #-}
module FluentApi where
import Control.Comonad
import Control.Arrow
{--
instance {-# OVERLAPPING #-} Comonad ((->) Options) where
extract :: (Options -> config) -> config
extract builder = builder mempty
extend :: ((Options -> config) -> config') -> (Options -> config) -> (Options -> config')
extend withFun builder opt2 = withFun (\opt1 -> builder (opt1 ++ opt2))
--}
type Options = [String]
newtype Config = Conf Options deriving (Show)
type ConfigBuilder = Options -> Config
configBuilder :: Options -> Config
configBuilder = Conf
withWarnings' :: ConfigBuilder -> Config
withWarnings' builder = builder ["-Wall"]
withProfiling' :: ConfigBuilder -> Config
withProfiling' builder = builder ["-prof", "-auto-all"]
withOptimization' :: ConfigBuilder -> Config
withOptimization' builder = builder ["-O2"]
withLogging' :: ConfigBuilder -> Config
withLogging' builder = builder ["-logall"]
-- ConfigBuilder -> ConfigBuilder versions
withWarnings :: ConfigBuilder -> (Options -> Config)
withWarnings builder opts = builder (opts ++ ["-Wall"])
withProfiling :: ConfigBuilder -> ConfigBuilder
withProfiling builder opts = builder (opts ++ ["-prof", "-auto-all"])
withOptimization :: ConfigBuilder -> ConfigBuilder
withOptimization builder opts = builder (opts ++ ["-O2"])
withLogging :: ConfigBuilder -> ConfigBuilder
withLogging builder opts = builder (opts ++ ["-logall"])
-- factoring out the option concatenation
withLogging'' :: ConfigBuilder -> ConfigBuilder
withLogging'' builder = extend' builder ["-logall"]
extend' :: ConfigBuilder -> Options -> ConfigBuilder
--extend' builder opts2 = \opts1 -> builder (opts1 ++ opts2)
extend' builder opts2 opts1 = builder (opts1 ++ opts2)
extend'' :: (ConfigBuilder -> Config) -> ConfigBuilder -> ConfigBuilder
extend'' withFun builder opt2 = withFun (\opt1 -> builder (opt1 ++ opt2))
build :: ConfigBuilder -> Config
build builder = builder mempty
(#) :: a -> (a -> b) -> b
x # f = f x
infixl 0 #
(#>) :: Comonad w => w a -> (w a -> b) -> w b
x #> f = extend f x
infixl 0 #>
(#>>) :: ConfigBuilder -> (ConfigBuilder -> Config) -> ConfigBuilder
x #>> f = extend'' f x
infixl 0 #>>
data User = User {
userId :: String
, name :: String
, email :: String
} deriving Show
emptyUser = User "" "" ""
setId :: String -> User -> User
setId id user = user {userId = id}
setName :: String -> User -> User
setName name user = user {name = name}
setMail :: String -> User -> User
setMail mail user = user {email = mail}
fluentApiDemo :: IO ()
fluentApiDemo = do
putStrLn "FluentApi -> Comonad"
print $ build $ withOptimization $ withProfiling configBuilder
configBuilder
#>> withProfiling'
#>> withOptimization'
#>> withLogging'
# build
# print
configBuilder
#> withProfiling'
#> withOptimization'
#> withLogging'
# extract
# print
configBuilder
# withProfiling
# withOptimization
# withLogging
# withWarnings
# build
# print
emptyUser
# setId "4610"
# setName "tom"
# setMail "[email protected]"
# print