Skip to content

Commit fa85383

Browse files
committed
Add pattern synonyms for sequences
Allow `Seq` to be matched with `Empty`, `:<|`, and `:|>`. Unfortunately, there's quite a lot of CPP noise resulting from various developments in pattern synonyms in different versions. Also unfortunately, there's not yet any way to let GHC know that matching on `Empty` and `:<|`, or on `Empty` and `:|>`, will be exhaustive.
1 parent d0105d2 commit fa85383

File tree

3 files changed

+68
-7
lines changed

3 files changed

+68
-7
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@
88
GNUmakefile
99
dist-install
1010
ghc.mk
11+
.stack-work

Data/Sequence.hs

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
{-# LANGUAGE CPP #-}
2+
#if __GLASGOW_HASKELL__ >= 708
3+
#define DEFINE_PATTERN_SYNONYMS 1
4+
#endif
25
#if __GLASGOW_HASKELL__
36
{-# LANGUAGE DeriveDataTypeable #-}
47
{-# LANGUAGE StandaloneDeriving #-}
@@ -10,6 +13,10 @@
1013
#if __GLASGOW_HASKELL__ >= 708
1114
{-# LANGUAGE TypeFamilies #-}
1215
#endif
16+
#ifdef DEFINE_PATTERN_SYNONYMS
17+
{-# LANGUAGE PatternSynonyms #-}
18+
{-# LANGUAGE ViewPatterns #-}
19+
#endif
1320

1421
#include "containers.h"
1522

@@ -56,10 +63,24 @@
5663
-----------------------------------------------------------------------------
5764

5865
module Data.Sequence (
59-
#if !defined(TESTING)
60-
Seq,
66+
#if defined(TESTING)
67+
Elem(..), FingerTree(..), Node(..), Digit(..),
68+
#if __GLASGOW_HASKELL__ >= 800
69+
Seq (.., Empty, (:<|), (:|>)),
70+
#else
71+
Seq (..),
72+
#endif
73+
74+
#elif __GLASGOW_HASKELL__ >= 800
75+
Seq (Empty, (:<|), (:|>)),
6176
#else
62-
Seq(..), Elem(..), FingerTree(..), Node(..), Digit(..),
77+
Seq,
78+
#if defined(DEFINE_PATTERN_SYNONYMS)
79+
-- * Pattern synonyms
80+
pattern Empty, -- :: Seq a
81+
pattern (:<|), -- :: a -> Seq a -> Seq a
82+
pattern (:|>), -- :: Seq a -> a -> Seq a
83+
#endif
6384
#endif
6485
-- * Construction
6586
empty, -- :: Seq a
@@ -220,6 +241,45 @@ infixr 5 ><
220241
infixr 5 <|, :<
221242
infixl 5 |>, :>
222243

244+
#ifdef DEFINE_PATTERN_SYNONYMS
245+
infixr 5 :<|
246+
infixl 5 :|>
247+
248+
-- TODO: Once GHC implements some way to prevent non-exhaustive
249+
-- pattern match warnings for pattern synonyms, we should be
250+
-- sure to take advantage of that.
251+
252+
-- Unfortunately, there's some extra noise here because
253+
-- pattern synonyms could not have signatures until 7.10,
254+
-- but 8.0 at least will warn if they're missing.
255+
#if __GLASGOW_HASKELL__ >= 710
256+
pattern Empty :: Seq a
257+
#endif
258+
pattern Empty = Seq EmptyT
259+
260+
-- Non-trivial bidirectional pattern synonyms are only
261+
-- available in GHC >= 7.10. In earlier versions, these
262+
-- can be used to match, but not to construct.
263+
264+
#if __GLASGOW_HASKELL__ >= 710
265+
pattern (:<|) :: a -> Seq a -> Seq a
266+
#endif
267+
pattern x :<| xs <- (viewl -> x :< xs)
268+
#if __GLASGOW_HASKELL__ >= 710
269+
where
270+
x :<| xs = x <| xs
271+
#endif
272+
273+
#if __GLASGOW_HASKELL__ >= 710
274+
pattern (:|>) :: Seq a -> a -> Seq a
275+
#endif
276+
pattern xs :|> x <- (viewr -> xs :> x)
277+
#if __GLASGOW_HASKELL__ >= 710
278+
where
279+
xs :|> x = xs |> x
280+
#endif
281+
#endif
282+
223283
class Sized a where
224284
size :: a -> Int
225285

tests/seq-properties.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ instance (Arbitrary a, Sized a) => Arbitrary (FingerTree a) where
116116
arbitrary = sized arb
117117
where
118118
arb :: (Arbitrary b, Sized b) => Int -> Gen (FingerTree b)
119-
arb 0 = return Empty
119+
arb 0 = return EmptyT
120120
arb 1 = Single <$> arbitrary
121121
arb n = do
122122
pr <- arbitrary
@@ -128,13 +128,13 @@ instance (Arbitrary a, Sized a) => Arbitrary (FingerTree a) where
128128
m <- arb n_m
129129
return $ deep pr m sf
130130

131-
shrink (Deep _ (One a) Empty (One b)) = [Single a, Single b]
131+
shrink (Deep _ (One a) EmptyT (One b)) = [Single a, Single b]
132132
shrink (Deep _ pr m sf) =
133133
[deep pr' m sf | pr' <- shrink pr] ++
134134
[deep pr m' sf | m' <- shrink m] ++
135135
[deep pr m sf' | sf' <- shrink sf]
136136
shrink (Single x) = map Single (shrink x)
137-
shrink Empty = []
137+
shrink EmptyT = []
138138

139139
instance (Arbitrary a, Sized a) => Arbitrary (Node a) where
140140
arbitrary = oneof [
@@ -176,7 +176,7 @@ instance Valid (Seq a) where
176176
valid (Seq xs) = valid xs
177177

178178
instance (Sized a, Valid a) => Valid (FingerTree a) where
179-
valid Empty = True
179+
valid EmptyT = True
180180
valid (Single x) = valid x
181181
valid (Deep s pr m sf) =
182182
s == size pr + size m + size sf && valid pr && valid m && valid sf

0 commit comments

Comments
 (0)