@@ -1,4 +1,5 @@
1{-# LANGUAGE FlexibleInstances #-}
1{-# LANGUAGE FlexibleInstances #-}
2+{-# LANGUAGE MonadComprehensions #-}
2{-# LANGUAGE TypeFamilies #-}
3{-# LANGUAGE TypeFamilies #-}
3{-# LANGUAGE OverloadedStrings #-}
4{-# LANGUAGE OverloadedStrings #-}
4{-# LANGUAGE OverloadedLists #-}
5{-# LANGUAGE OverloadedLists #-}
@@ -9,79 +10,91 @@
9module Main (main) where
10module Main (main) where
11import Test.Hspec
12import Test.Hspec
12−import Data.Functor.Identity
13import qualified GHC.Exts as GHC
13import qualified GHC.Exts as GHC
14−import Prelude hiding (String)
15+import Data.Functor.Identity
16import Streamly
16import Streamly
17+import Streamly.List (pattern Cons, pattern Nil)
17import qualified Streamly.Prelude as S
18import qualified Streamly.Prelude as S
18−
19+import qualified Streamly.List as S
19−type List = SerialT Identity
20−type String = List Char
22−------------------------------------------------------------------------------
24−------------------------------------------------------------------------------
26−-- | A pattern that matches an empty pure stream.
27−pattern Nil :: SerialT Identity a
28−pattern Nil <- (runIdentity . S.null -> True) where
31−-- | A pattern that deconstructs a pure stream into its head and tail.
32−pattern Cons :: a -> SerialT Identity a -> SerialT Identity a
33−pattern Cons x xs <- (runIdentity . S.uncons -> Just (x, xs)) where
34− Cons x xs = S.cons x xs
36main :: IO ()
21main :: IO ()
37main = hspec $ do
22main = hspec $ do
38− -- Need type annotation to resolve the monad ambiguity
23+ describe "OverloadedLists for 'SerialT Identity' type" $ do
39− -- Use toList or runIdentity . S.toList to convert to Haskell lists
24+ it "overloaded lists" $ do
40−
25+ ([1..3] :: SerialT Identity Int) `shouldBe` S.fromList [1..3]
41− it "overloaded lists" $ do
26+ GHC.toList ([1..3] :: SerialT Identity Int) `shouldBe` [1..3]
28+ it "Show instance" $ do
29+ show (S.fromList [1..3] :: SerialT Identity Int)
42− ([1..3] :: Main.List Int) `shouldBe` S.fromList [1..3]
30+ `shouldBe` "fromList [1,2,3]"
31+ it "Read instance" $ do
43− GHC.toList ([1..3] :: Main.List Int) `shouldBe` [1..3]
32+ (read "fromList [1,2,3]" :: SerialT Identity Int) `shouldBe` [1..3]
45− it "overloaded strings" $ do
34+ it "Eq instance" $ do
35+ ([1,2,3] :: SerialT Identity Int) == [1,2,3] `shouldBe` True
37+ it "Ord instance" $ do
38+ ([1,2,3] :: SerialT Identity Int) > [1,2,1] `shouldBe` True
40+ it "Monad comprehension" $ do
41+ [(x,y) | x <- [1..2], y <- [1..2]] `shouldBe`
42+ ([(1,1), (1,2), (2,1), (2,2)] :: SerialT Identity (Int, Int))
44+ describe "OverloadedLists for List type" $ do
45+ it "overloaded lists" $ do
46− ("hello" :: Main.String) `shouldBe` S.fromList "hello"
46+ [1..3 :: Int] `shouldBe` S.fromSerial (S.fromList [1..3])
47−
47+ GHC.toList ([1..3] :: S.List Int) `shouldBe` [1..3]
48− it "pattern match constructs a list" $ do
49+ it "pattern constructor constructs a list" $ do
49− ('x' `Cons` Nil) `shouldBe` ('x' `S.cons` S.nil :: Main.String)
50+ ('x' `Cons` Nil) `shouldBe` ['x']
51+ (1 `Cons` [2 :: Int]) `shouldBe` [1,2]
53+ it "pattern match on non-empty list" $
54+ case [1..10 :: Int] of
57+ xs `shouldBe` [2..10]
58+ _ -> expectationFailure "not reached"
60+ it "Show instance" $ do
61+ show ([1..3] :: S.List Int) `shouldBe` "fromList [1,2,3]"
63+ it "Read instance" $ do
64+ (read "fromList [1,2,3]" :: S.List Int) `shouldBe` [1..3]
66+ it "Eq instance" $ do
67+ ([1,2,3] :: S.List Int) == [1,2,3] `shouldBe` True
69+ it "Ord instance" $ do
50− (1 `Cons` [2] :: Main.List Int) `shouldBe` S.fromList [1,2]
70+ ([1,2,3] :: S.List Int) > [1,2,1] `shouldBe` True
72+ it "Monad comprehension" $ do
73+ [(x,y) | x <- [1..2], y <- [1..2]] `shouldBe`
74+ ([(1,1), (1,2), (2,1), (2,2)] :: S.List (Int, Int))
76+ describe "OverloadedStrings for 'SerialT Identity' type" $ do
77+ it "overloaded strings" $ do
78+ ("hello" :: SerialT Identity Char) `shouldBe` S.fromList "hello"
80+ describe "OverloadedStrings for List type" $ do
81+ it "overloaded strings" $ do
82+ "hello" `shouldBe` S.fromSerial (S.fromList "hello")
52− it "pattern match on empty string" $
84+ it "pattern match on empty string" $
53− case "" :: Main.String of
85+ case "" of
54− Nil -> return ()
86+ Nil -> return ()
55− _ -> expectationFailure "not reached"
87+ _ -> expectationFailure "not reached"
57− it "pattern matches on singleton string" $
89+ it "pattern matches on singleton string" $
58− case "a" :: Main.String of
90+ case "a" of
59− Cons x Nil -> x `shouldBe` 'a'
91+ Cons x Nil -> x `shouldBe` 'a'
60− _ -> expectationFailure "not reached"
92+ _ -> expectationFailure "not reached"
62− it "pattern matches on non-empty string" $
94+ it "pattern matches on non-empty string" $
63− case "hello" <> "world" :: Main.String of
95+ case "hello" <> "world" of
64− Cons x1 (Cons x2 xs) -> do
96+ Cons x1 (Cons x2 xs) -> do
65− x1 `shouldBe` 'h'
97+ x1 `shouldBe` 'h'
66− x2 `shouldBe` 'e'
98+ x2 `shouldBe` 'e'
67− xs `shouldBe` "lloworld"
99+ xs `shouldBe` "lloworld"
68− _ -> expectationFailure "not reached"
70− it "pattern match on non-empty list" $
71− case S.map (+1) [1..10] :: Main.List Int of
74− xs `shouldBe` [3..11]
75− _ -> expectationFailure "not reached"
100+ _ -> expectationFailure "not reached"
77− it "Shows as string" $ do
78− show (S.fromList [1..3] :: Main.List Int) `shouldBe` "fromList [1,2,3]"
80− it "Reads from a string" $ do
81− (read "fromList [1,2,3]" :: Main.List Int) `shouldBe` S.fromList [1..3]
83− it "Eq instance" $ do
84− (S.fromList [1,2,3] :: Main.List Int) == S.fromList [1,2,3] `shouldBe` True
86− it "Ord instance" $ do
87− (S.fromList [1,2,3] :: Main.List Int) > S.fromList [1,2,1] `shouldBe` True