git.iko.soy/typeable/attoparsec
on master help sign in
Make code future proof by adding MonadFail/Semigroup instances

This patch makes the code future proof under the MonadFail and Semigroup proposals by adding instances in a CPP-avoiding way. Moreover, Monad instance definitions are refactored in a canonical form. With this patch, attoparsec is warning free with GHC 8.0 under -Wall -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances (Compilation of attorparsec with GHCs back till 7.0.4 is warning-free as well)

commit36b2adc4ca869550c4c9feb7427e267126eb78c4 authorHerbert Valerio Riedel <hvr@gnu.org> dateWed 2 Mar 2016, 20:33 (11 years ago) parent812ce4f
5 files changed+83−50
Data/Attoparsec/ByteString/Buffer.hs+10−8 Data/Attoparsec/Internal/Types.hs+32−25 Data/Attoparsec/Text/Buffer.hs+11−9 Data/Attoparsec/Zepto.hs+15−8 attoparsec.cabal+15
Data/Attoparsec/ByteString/Buffer.hs+10−8
@@ -1,4 +1,4 @@
1−{-# LANGUAGE BangPatterns, CPP #-}
1+{-# LANGUAGE BangPatterns #-}
22-- |
33-- Module : Data.Attoparsec.ByteString.Buffer
44-- Copyright : Bryan O'Sullivan 2007-2015
@@ -57,9 +57,8 @@ import Control.Exception (assert)
5757import Data.ByteString.Internal (ByteString(..), memcpy, nullForeignPtr)
5858import Data.Attoparsec.Internal.Fhthagn (inlinePerformIO)
5959import Data.List (foldl1')
60−#if !MIN_VERSION_base(4,8,0)
61−import Data.Monoid (Monoid(..))
62−#endif
60+import Data.Monoid as Mon (Monoid(..))
61+import Data.Semigroup (Semigroup(..))
6362import Data.Word (Word8)
6463import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)
6564import Foreign.Ptr (castPtr, plusPtr)
@@ -88,14 +87,17 @@ buffer (PS fp off len) = Buf fp off len len 0
8887unbuffer :: Buffer -> ByteString
8988unbuffer (Buf fp off len _ _) = PS fp off len
9089
90+instance Semigroup Buffer where
91+ (Buf _ _ _ 0 _) <> b = b
92+ a <> (Buf _ _ _ 0 _) = a
93+ buf <> (Buf fp off len _ _) = append buf fp off len
94+
9195instance Monoid Buffer where
9296 mempty = Buf nullForeignPtr 0 0 0 0
9397
94− mappend (Buf _ _ _ 0 _) b = b
95− mappend a (Buf _ _ _ 0 _) = a
96− mappend buf (Buf fp off len _ _) = append buf fp off len
98+ mappend = (<>)
9799
98− mconcat [] = mempty
100+ mconcat [] = Mon.mempty
99101 mconcat xs = foldl1' mappend xs
100102
101103pappend :: Buffer -> ByteString -> Buffer
Data/Attoparsec/Internal/Types.hs+32−25
@@ -1,4 +1,4 @@
1−{-# LANGUAGE BangPatterns, CPP, GeneralizedNewtypeDeriving, OverloadedStrings,
1+{-# LANGUAGE BangPatterns, GeneralizedNewtypeDeriving, OverloadedStrings,
22 Rank2Types, RecordWildCards, TypeFamilies #-}
33-- |
44-- Module : Data.Attoparsec.Internal.Types
@@ -25,13 +25,13 @@ module Data.Attoparsec.Internal.Types
2525 , Chunk(..)
2626 ) where
2727
28−#if !MIN_VERSION_base(4,8,0)
29−import Control.Applicative (Applicative(..), (<$>))
30−import Data.Monoid (Monoid(..))
31−#endif
28+import Control.Applicative as App (Applicative(..), (<$>))
3229import Control.Applicative (Alternative(..))
3330import Control.DeepSeq (NFData(rnf))
3431import Control.Monad (MonadPlus(..))
32+import qualified Control.Monad.Fail as Fail (MonadFail(..))
33+import Data.Monoid as Mon (Monoid(..))
34+import Data.Semigroup (Semigroup(..))
3535import Data.Word (Word8)
3636import Data.ByteString (ByteString)
3737import qualified Data.ByteString as BS
@@ -127,17 +127,19 @@ type Success i t a r = t -> Pos -> More -> a -> IResult i r
127127data More = Complete | Incomplete
128128 deriving (Eq, Show)
129129
130−instance Monoid More where
131− mappend c@Complete _ = c
132− mappend _ m = m
133− mempty = Incomplete
130+instance Semigroup More where
131+ c@Complete <> _ = c
132+ _ <> m = m
133+
134+instance Mon.Monoid More where
135+ mappend = (<>)
136+ mempty = Incomplete
134137
135138instance Monad (Parser i) where
136− fail err = Parser $ \t pos more lose _succ -> lose t pos more [] msg
137− where msg = "Failed reading: " ++ err
139+ fail = Fail.fail
138140 {-# INLINE fail #-}
139141
140− return v = Parser $ \t pos more _lose succ -> succ t pos more v
142+ return = App.pure
141143 {-# INLINE return #-}
142144
143145 m >>= k = Parser $ \t !pos more lose succ ->
@@ -145,6 +147,15 @@ instance Monad (Parser i) where
145147 in runParser m t pos more lose succ'
146148 {-# INLINE (>>=) #-}
147149
150+ (>>) = (*>)
151+ {-# INLINE (>>) #-}
152+
153+
154+instance Fail.MonadFail (Parser i) where
155+ fail err = Parser $ \t pos more lose _succ -> lose t pos more [] msg
156+ where msg = "Failed reading: " ++ err
157+ {-# INLINE fail #-}
158+
148159plus :: Parser i a -> Parser i a -> Parser i a
149160plus f g = Parser $ \t pos more lose succ ->
150161 let lose' t' _pos' more' _ctx _msg = runParser g t' pos more' lose succ
@@ -169,23 +180,23 @@ apP d e = do
169180{-# INLINE apP #-}
170181
171182instance Applicative (Parser i) where
172− pure = return
183+ pure v = Parser $ \t pos more _lose succ -> succ t pos more v
173184 {-# INLINE pure #-}
174185 (<*>) = apP
175186 {-# INLINE (<*>) #-}
176−
177− -- These definitions are equal to the defaults, but this
178− -- way the optimizer doesn't have to work so hard to figure
179− -- that out.
180− (*>) = (>>)
187+ m *> k = m >>= \_ -> k
181188 {-# INLINE (*>) #-}
182− x <* y = x >>= \a -> y >> return a
189+ x <* y = x >>= \a -> y >> pure a
183190 {-# INLINE (<*) #-}
184191
192+instance Semigroup (Parser i a) where
193+ (<>) = plus
194+ {-# INLINE (<>) #-}
195+
185196instance Monoid (Parser i a) where
186197 mempty = fail "mempty"
187198 {-# INLINE mempty #-}
188− mappend = plus
199+ mappend = (<>)
189200 {-# INLINE mappend #-}
190201
191202instance Alternative (Parser i) where
@@ -197,7 +208,7 @@ instance Alternative (Parser i) where
197208
198209 many v = many_v
199210 where many_v = some_v <|> pure []
200− some_v = (:) <$> v <*> many_v
211+ some_v = (:) App.<$> v <*> many_v
201212 {-# INLINE many #-}
202213
203214 some v = some_v
@@ -206,10 +217,6 @@ instance Alternative (Parser i) where
206217 some_v = (:) <$> v <*> many_v
207218 {-# INLINE some #-}
208219
209−(<>) :: (Monoid m) => m -> m -> m
210−(<>) = mappend
211−{-# INLINE (<>) #-}
212−
213220-- | A common interface for input chunks.
214221class Monoid c => Chunk c where
215222 type ChunkElem c
Data/Attoparsec/Text/Buffer.hs+11−9
@@ -40,9 +40,8 @@ module Data.Attoparsec.Text.Buffer
4040import Control.Exception (assert)
4141import Data.Bits (shiftR)
4242import Data.List (foldl1')
43−#if !MIN_VERSION_base(4,8,0)
44−import Data.Monoid (Monoid(..))
45−#endif
43+import Data.Monoid as Mon (Monoid(..))
44+import Data.Semigroup (Semigroup(..))
4645import Data.Text ()
4746import Data.Text.Internal (Text(..))
4847import Data.Text.Internal.Encoding.Utf16 (chr2)
@@ -80,17 +79,20 @@ unbufferAt s (Buf arr off len _ _) =
8079 assert (s >= 0 && s <= len) $
8180 Text arr (off+s) (len-s)
8281
82+instance Semigroup Buffer where
83+ (Buf _ _ _ 0 _) <> b = b
84+ a <> (Buf _ _ _ 0 _) = a
85+ buf <> (Buf arr off len _ _) = append buf arr off len
86+ {-# INLINE (<>) #-}
87+
8388instance Monoid Buffer where
8489 mempty = Buf A.empty 0 0 0 0
8590 {-# INLINE mempty #-}
8691
87− mappend (Buf _ _ _ 0 _) b = b
88− mappend a (Buf _ _ _ 0 _) = a
89− mappend buf (Buf arr off len _ _) = append buf arr off len
90− {-# INLINE mappend #-}
92+ mappend = (<>)
9193
92− mconcat [] = mempty
93− mconcat xs = foldl1' mappend xs
94+ mconcat [] = Mon.mempty
95+ mconcat xs = foldl1' (<>) xs
9496
9597pappend :: Buffer -> Text -> Buffer
9698pappend (Buf _ _ _ 0 _) t = buffer t
Data/Attoparsec/Zepto.hs+15−8
@@ -38,18 +38,17 @@ module Data.Attoparsec.Zepto
3838
3939import Control.Applicative
4040import Control.Monad (MonadPlus(..), ap)
41+import qualified Control.Monad.Fail as Fail
4142import Control.Monad.IO.Class (MonadIO(..))
4243import Data.ByteString (ByteString)
4344import Data.Functor.Identity (Identity(runIdentity))
45+import Data.Monoid as Mon (Monoid(..))
46+import Data.Semigroup (Semigroup(..))
4447import Data.Word (Word8)
4548import Prelude hiding (take, takeWhile)
4649import qualified Data.ByteString as B
4750import qualified Data.ByteString.Unsafe as B
4851
49−#if !MIN_VERSION_base(4,8,0)
50−import Data.Monoid (Monoid(..))
51−#endif
52−
5352newtype S = S {
5453 input :: ByteString
5554 }
@@ -83,7 +82,7 @@ instance MonadIO m => MonadIO (ZeptoT m) where
8382 {-# INLINE liftIO #-}
8483
8584instance Monad m => Monad (ZeptoT m) where
86− return a = Parser $ \s -> return (OK a s)
85+ return = pure
8786 {-# INLINE return #-}
8887
8988 m >>= k = Parser $ \s -> do
@@ -93,6 +92,10 @@ instance Monad m => Monad (ZeptoT m) where
9392 Fail err -> return (Fail err)
9493 {-# INLINE (>>=) #-}
9594
95+ fail = Fail.fail
96+ {-# INLINE fail #-}
97+
98+instance Monad m => Fail.MonadFail (ZeptoT m) where
9699 fail msg = Parser $ \_ -> return (Fail msg)
97100 {-# INLINE fail #-}
98101
@@ -108,7 +111,7 @@ instance Monad m => MonadPlus (ZeptoT m) where
108111 {-# INLINE mplus #-}
109112
110113instance (Monad m) => Applicative (ZeptoT m) where
111− pure = return
114+ pure a = Parser $ \s -> return (OK a s)
112115 {-# INLINE pure #-}
113116 (<*>) = ap
114117 {-# INLINE (<*>) #-}
@@ -137,10 +140,14 @@ parseT p bs = do
137140 Fail err -> return (Left err)
138141{-# INLINE parseT #-}
139142
140−instance Monad m => Monoid (ZeptoT m a) where
143+instance Monad m => Semigroup (ZeptoT m a) where
144+ (<>) = mplus
145+ {-# INLINE (<>) #-}
146+
147+instance Monad m => Mon.Monoid (ZeptoT m a) where
141148 mempty = fail "mempty"
142149 {-# INLINE mempty #-}
143− mappend = mplus
150+ mappend = (<>)
144151 {-# INLINE mappend #-}
145152
146153instance Monad m => Alternative (ZeptoT m) where
attoparsec.cabal+15
@@ -50,6 +50,11 @@ library
5050 build-depends:
5151 bytestring < 0.10.4.0
5252
53+ if !impl(ghc >= 8.0)
54+ -- Data.Semigroup && Control.Monad.Fail are available in base-4.9+
55+ build-depends: fail == 4.9.*,
56+ semigroups >=0.16.1 && <0.19
57+
5358 exposed-modules: Data.Attoparsec
5459 Data.Attoparsec.ByteString
5560 Data.Attoparsec.ByteString.Char8
@@ -113,6 +118,11 @@ test-suite tests
113118 transformers,
114119 vector
115120
121+ if !impl(ghc >= 8.0)
122+ -- Data.Semigroup && Control.Monad.Fail are available in base-4.9+
123+ build-depends: fail == 4.9.*,
124+ semigroups >=0.16.1 && <0.19
125+
116126benchmark benchmarks
117127 type: exitcode-stdio-1.0
118128 hs-source-dirs: benchmarks benchmarks/warp-3.0.1.1 .
@@ -154,6 +164,11 @@ benchmark benchmarks
154164 unordered-containers,
155165 vector
156166
167+ if !impl(ghc >= 8.0)
168+ -- Data.Semigroup && Control.Monad.Fail are available in base-4.9+
169+ build-depends: fail == 4.9.*,
170+ semigroups >=0.16.1 && <0.19
171+
157172source-repository head
158173 type: git
159174 location: https://github.com/bos/attoparsec