2{-# LANGUAGE DeriveTraversable #-}
3{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4{-# LANGUAGE PatternSynonyms #-}
5{-# LANGUAGE TypeFamilies #-}
6{-# LANGUAGE UndecidableInstances #-} -- XXX
7{-# LANGUAGE ViewPatterns #-}
10-- Module : Streamly.List
11-- Copyright : (c) 2018 Composewell Technologies
14-- Maintainer : harendra.kumar@gmail.com
15-- Stability : experimental
18-- Lists are just a special case of monadic streams. The stream type @SerialT
19-- Identity a@ can be used as a replacement for @[a]@. The 'List' type in this
20-- module is just a newtype wrapper around @SerialT Identity@ for better type
21-- inference when using the 'OverloadedLists' GHC extension. @List a@ provides
22-- better performance compared to @[a]@. Standard list, string and list
23-- comprehension syntax can be used with the 'List' type by enabling
24-- 'OverloadedLists', 'OverloadedStrings' and 'MonadComprehensions' GHC
25-- extensions. There would be a slight difference in the 'Show' and 'Read'
26-- strings of streamly list as compared to regular lists.
28-- Conversion to stream types is free, any stream combinator can be used on
29-- lists by converting them to streams. However, for convenience, this module
30-- provides combinators that work directly on the 'List' type.
34-- List $ S.map (+ 1) $ toSerial (1 \`Cons\` Nil)
37-- To convert a 'List' to regular lists, you can use any of the following:
39-- * @toList . toSerial@ and @toSerial . fromList@
40-- * 'Data.Foldable.toList' from "Data.Foldable"
41-- * 'GHC.Exts.toList' and 'GHC.Exts.fromList' from 'IsList' in "GHC.Exts"
43-- If you have made use of 'Nil' and 'Cons' constructors in the code and you
44-- want to replace streamly lists with standard lists, all you need to do is
45-- import these definitions:
49-- pattern Nil <- [] where Nil = []
50-- pattern Cons x xs = x : xs
52-- {-\# COMPLETE Cons, Nil #-}
55-- See <src/docs/streamly-vs-lists.md> for more details and
56-- <src/test/PureStreams.hs> for comprehensive usage examples.
60#if __GLASGOW_HASKELL__ >= 800
67 -- XXX we may want to use rebindable syntax for variants instead of using
68 -- different types (applicative do and apWith).
75import Control.Arrow (second)
76import Control.DeepSeq (NFData(..), NFData1(..))
77import Data.Functor.Identity (Identity, runIdentity)
78import Data.Semigroup (Semigroup(..))
79import GHC.Exts (IsList(..), IsString(..))
81import Streamly.Streams.Serial (SerialT)
82import Streamly.Streams.Zip (ZipSerialM)
84import qualified Streamly.Streams.Prelude as P
85import qualified Streamly.Streams.StreamK as K
87-- We implement list as a newtype instead of a type synonym to make type
88-- inference easier when using -XOverloadedLists and -XOverloadedStrings. When
89-- using a stream type the programmer needs to specify the Monad otherwise the
90-- type remains ambiguous.
92-- XXX once we separate consM from IsStream or remove the MonadIO and
93-- MonadBaseControlIO dependency from it, then we can make this an instance of
94-- IsStream and use the regular polymorphic functions on Lists as well. Once
95-- that happens we can change the Show and Read instances as well to use "1 >:
96-- 2 >: nil" etc. or should we use a separate constructor indicating the "List"
97-- type ":>" for better inference?
99-- | @List a@ is a replacement for @[a]@.
102newtype List a = List { toSerial :: SerialT Identity a }
103 deriving (Show, Read, Eq, Ord, NFData, NFData1
104 , Semigroup, Monoid, Functor, Foldable
105 , Applicative, Traversable, Monad)
107instance (a ~ Char) => IsString (List a) where
108 {-# INLINE fromString #-}
109 fromString = List . P.fromList
111-- GHC versions 8.0 and below cannot derive IsList
112instance IsList (List a) where
113 type (Item (List a)) = a
114 {-# INLINE fromList #-}
115 fromList = List . P.fromList
116 {-# INLINE toList #-}
117 toList = runIdentity . P.toList . toSerial
119------------------------------------------------------------------------------
121------------------------------------------------------------------------------
123-- Note: When using the OverloadedLists extension we should be able to pattern
124-- match using the regular list contructors. OverloadedLists uses 'toList' to
125-- perform the pattern match, it should not be too bad as it works lazily in
126-- the Identity monad. We need these patterns only when not using that
129-- | An empty list constructor and pattern that matches an empty 'List'.
130-- Corresponds to '[]' for Haskell lists.
134pattern Nil <- (runIdentity . K.null . toSerial -> True) where
139-- | A list constructor and pattern that deconstructs a 'List' into its head
140-- and tail. Corresponds to ':' for Haskell lists.
143pattern Cons :: a -> List a -> List a
145 (fmap (second List) . runIdentity . K.uncons . toSerial
146 -> Just (x, xs)) where
147 Cons x xs = List $ K.cons x (toSerial xs)
149#if __GLASGOW_HASKELL__ >= 802
150{-# COMPLETE Nil, Cons #-}
153------------------------------------------------------------------------------
155------------------------------------------------------------------------------
157-- | Just like 'List' except that it has a zipping 'Applicative' instance
158-- and no 'Monad' instance.
161newtype ZipList a = ZipList { toZipSerial :: ZipSerialM Identity a }
162 deriving (Show, Read, Eq, Ord, NFData, NFData1
163 , Semigroup, Monoid, Functor, Foldable
164 , Applicative, Traversable)
166instance (a ~ Char) => IsString (ZipList a) where
167 {-# INLINE fromString #-}
168 fromString = ZipList . P.fromList
170-- GHC versions 8.0 and below cannot derive IsList
171instance IsList (ZipList a) where
172 type (Item (ZipList a)) = a
173 {-# INLINE fromList #-}
174 fromList = ZipList . P.fromList
175 {-# INLINE toList #-}
176 toList = runIdentity . P.toList . toZipSerial
178-- | Convert a 'ZipList' to a regular 'List'
181fromZipList :: ZipList a -> List a
182fromZipList = List . K.adapt . toZipSerial
184-- | Convert a regular 'List' to a 'ZipList'
187toZipList :: List a -> ZipList a
188toZipList = ZipList . K.adapt . toSerial
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