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