1{-# LANGUAGE BangPatterns #-}
3{-# LANGUAGE ExistentialQuantification #-}
4{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE PatternSynonyms #-}
6{-# LANGUAGE RankNTypes #-}
7{-# LANGUAGE RecordWildCards #-}
8{-# LANGUAGE ScopedTypeVariables #-}
13-- Module : Streamly.Unfold
14-- Copyright : (c) 2019 Composewell Technologies
16-- Maintainer : harendra.kumar@gmail.com
17-- Stability : experimental
20-- Streams forcing a closed control flow loop can be categorized under
21-- two types, unfolds and folds, both of these are duals of each other.
23-- Unfold streams are really generators of a sequence of elements, we can also
24-- call them pull style streams. These are lazy producers of streams. On each
25-- evaluation the producer generates the next element. A consumer can
26-- therefore pull elements from the stream whenever it wants to. A stream
27-- consumer can multiplex pull streams by pulling elements from the chosen
28-- streams, therefore, pull streams allow merging or multiplexing. On the
29-- other hand, with this representation we cannot split or demultiplex a
30-- stream. So really these are stream sources that can be generated from a
31-- seed and can be merged or zipped into a single stream.
33-- The dual of Unfolds are Folds. Folds can also be called as push style
34-- streams or reducers. These are strict consumers of streams. We keep pushing
35-- elements to a fold and we can extract the result at any point. A driver can
36-- choose which fold to push to and can also push the same element to multiple
37-- folds. Therefore, folds allow splitting or demultiplexing a stream. On the
38-- other hand, we cannot merge streams using this representation. So really
39-- these are stream consumers that reduce the stream to a single value, these
40-- consumers can be composed such that a stream can be split over multiple
43-- Open control flow style streams can also have two representations. StreamK
44-- is a producer style representation. We can also have a consumer style
45-- representation. We can use that for composable folds in StreamK
52 -- A 'Fold' can be run over a seed using the 'unfold' combinator.
54 -- >>> unfold UF.replicateM (putStrLn "hello") 10
66import Streamly.Streams.StreamD.Type (Stream(..), Step(..))
67#if __GLASGOW_HASKELL__ < 800
68import Streamly.Streams.StreamD.Type (pattern Stream)
70import Streamly.Unfold.Types (Unfold(..))
72-------------------------------------------------------------------------------
74-------------------------------------------------------------------------------
76-- | Convert an 'Unfold' into a 'Stream' by supplying it a seed.
78{-# INLINE_NORMAL unfold #-}
79unfold :: Monad m => a -> Unfold m a b -> Stream m b
80unfold seed (Unfold ustep inject) = Stream step Nothing
82 {-# INLINE_LATE step #-}
83 step _ Nothing = inject seed >>= return . Skip . Just
87 Yield x s -> Yield x (Just s)
88 Skip s -> Skip (Just s)
91-------------------------------------------------------------------------------
93-------------------------------------------------------------------------------
95-- | Identity unfold. Generates a singleton stream with the seed as the only
96-- element in the stream.
98-- > singleton = replicateM 1
100{-# INLINE singleton #-}
101singleton :: Monad m => Unfold m a a
102singleton = Unfold step inject
104 inject x = return $ Just x
105 {-# INLINE_LATE step #-}
106 step (Just x) = return $ Yield x Nothing
107 step Nothing = return Stop
109-- | Generates a stream replicating the seed @n@ times.
111{-# INLINE replicateM #-}
112replicateM :: Monad m => Int -> Unfold m a a
113replicateM n = Unfold step inject
115 inject x = return (x, n)
116 {-# INLINE_LATE step #-}
117 step (x, i) = return $
120 else Yield x (x, (i - 1))
122-- | Convert a list of pure values to a 'Stream'
123{-# INLINE_LATE fromList #-}
124fromList :: Monad m => Unfold m [a] a
125fromList = Unfold step inject
128 {-# INLINE_LATE step #-}
129 step (x:xs) = return $ Yield x xs
130 step [] = return Stop
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list