-
Notifications
You must be signed in to change notification settings - Fork 39
/
Pipeline.hs
59 lines (46 loc) · 2 KB
/
Pipeline.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
-- The DeriveFunctor Language Pragma provides automatic derivation of Functor instances
{-# LANGUAGE DeriveFunctor #-}
module Pipeline where
-- The Stream type is a wrapper around an arbitrary payload type 'a'
newtype Stream a = Stream a deriving (Show)
-- echo injects an item of type 'a' into the Stream context
echo :: a -> Stream a
echo = Stream
-- the 'andThen' operator used for chaining commands
infixl 7 |>
(|>) :: Stream a -> (a -> Stream b) -> Stream b
Stream x |> f = f x
-- echo and |> are used to create the actual pipeline
pipeline :: String -> Stream Int
pipeline str =
echo str |> echo . length . words |> echo . (3 *)
-- a log is just a list of Strings
type Log = [String]
-- the Stream type is extended by a Log, that keeps track of any logged messages
newtype LoggerStream a = LoggerStream (a, Log) deriving (Show, Functor)
instance Applicative LoggerStream where
pure = return
LoggerStream (f, _) <*> r = fmap f r
-- our definition of the Logging Stream Monad
instance Monad LoggerStream where
-- returns a Stream wrapping a tuple of the actual payload and an empty Log
return a = LoggerStream (a, [])
-- we define (>>=) to return a tuple (composed functions, concatenated logs)
m1 >>= m2 = let LoggerStream(f1, l1) = m1
LoggerStream(f2, l2) = m2 f1
in LoggerStream(f2, l1 ++ l2)
-- compute length of a String and provide a log message
logLength :: String -> LoggerStream Int
logLength str = let l = length(words str)
in LoggerStream (l, ["length(" ++ str ++ ") = " ++ show l])
logMultiply :: Int -> LoggerStream Int
logMultiply x = let z = x * 3
in LoggerStream (z, ["multiply(" ++ show x ++ ", 3" ++") = " ++ show z])
logPipeline :: String -> LoggerStream Int
logPipeline str =
return str >>= logLength >>= logMultiply
pipelineDemo = do
putStrLn "Pipeline -> Monad"
print $ pipeline "hello world"
print $ logPipeline "hello logging world"
putStrLn ""