@@ -41,8 +41,8 @@ module Network.TypedProtocol.Stateful.Codec
4141 -- * CodecFailure
4242 , CodecFailure (.. )
4343 -- * Testing codec properties
44- , AnyMessage (.. )
45- , pattern AnyMessageAndAgency
44+ , AnyMessage (.. , AnyMessageAndAgency )
45+ , showAnyMessage
4646 , prop_codecM
4747 , prop_codec
4848 , prop_codec_splitsM
@@ -59,7 +59,7 @@ import Network.TypedProtocol.Codec (CodecFailure (..),
5959 DecodeStep (.. ), SomeMessage (.. ), hoistDecodeStep ,
6060 isoDecodeStep , mapFailureDecodeStep , runDecoder ,
6161 runDecoderPure )
62- import qualified Network.TypedProtocol.Codec as TP
62+ import qualified Network.TypedProtocol.Codec as TP hiding ( AnyMessageAndAgency )
6363
6464
6565-- | A stateful codec.
@@ -68,14 +68,23 @@ data Codec ps failure (f :: ps -> Type) m bytes = Codec {
6868 encode :: forall (st :: ps ) (st' :: ps ).
6969 StateTokenI st
7070 => ActiveState st
71- => f st'
71+ => f st
72+ -- local state, which contain extra context for the encoding
73+ -- process.
74+ --
75+ -- TODO: input-output-hk/typed-protocols#57
7276 -> Message ps st st'
77+ -- message to be encoded
7378 -> bytes ,
7479
7580 decode :: forall (st :: ps ).
7681 ActiveState st
7782 => StateToken st
7883 -> f st
84+ -- local state, which can contain extra context from the
85+ -- previous message.
86+ --
87+ -- TODO: input-output-hk/typed-protocols#57
7988 -> m (DecodeStep bytes failure m (SomeMessage st ))
8089 }
8190
@@ -130,22 +139,32 @@ data AnyMessage ps (f :: ps -> Type) where
130139 , ActiveState st
131140 )
132141 => f st
133- -> f st'
142+ -- ^ local state
134143 -> Message ps (st :: ps ) (st' :: ps )
144+ -- ^ protocol messsage
135145 -> AnyMessage ps f
136146
137- instance ( forall (st :: ps ) (st' :: ps ). Show (Message ps st st' )
138- , forall (st :: ps ). Show (f st )
139- )
140- => Show (AnyMessage ps f ) where
141- show (AnyMessage st st' msg) = concat [ " AnyMessage "
142- , show st
143- , " "
144- , show st'
145- , " "
146- , show msg
147- ]
148147
148+ -- | `showAnyMessage` is can be used to provide `Show` instance for
149+ -- `AnyMessage` if showing `Message` is independent of the state or one accepts
150+ -- showing only partial information included in message constructors or accepts
151+ -- message constructors to carry `Show` instances for its arguments. Note that
152+ -- the proper solution is to define a custom `Show (AnyMessage ps f)` instance
153+ -- for a protocol `ps`, which give access to the state functor `f` in scope of
154+ -- `show`.
155+ --
156+ showAnyMessage :: forall ps f .
157+ ( forall st st' . Show (Message ps st st' )
158+ , forall st . Show (f st )
159+ )
160+ => AnyMessage ps f
161+ -> String
162+ showAnyMessage (AnyMessage st msg) =
163+ concat [ " AnyMessage "
164+ , show st
165+ , " "
166+ , show msg
167+ ]
149168
150169
151170-- | A convenient pattern synonym which unwrap 'AnyMessage' giving both the
@@ -156,10 +175,9 @@ pattern AnyMessageAndAgency :: forall ps f. ()
156175 (StateTokenI st, ActiveState st)
157176 => StateToken st
158177 -> f st
159- -> f st'
160178 -> Message ps st st'
161179 -> AnyMessage ps f
162- pattern AnyMessageAndAgency stateToken f f' msg <- AnyMessage f f' (getAgency -> (msg, stateToken))
180+ pattern AnyMessageAndAgency stateToken f msg <- AnyMessage f (getAgency -> (msg, stateToken))
163181 where
164182 AnyMessageAndAgency _ msg = AnyMessage msg
165183{-# COMPLETE AnyMessageAndAgency #-}
@@ -169,28 +187,29 @@ pattern AnyMessageAndAgency stateToken f f' msg <- AnyMessage f f' (getAgency ->
169187getAgency :: StateTokenI st => Message ps st st' -> (Message ps st st' , StateToken st )
170188getAgency msg = (msg, stateToken)
171189
190+
172191-- | The 'Codec' round-trip property: decode after encode gives the same
173192-- message. Every codec must satisfy this property.
174193--
175194prop_codecM
176195 :: forall ps failure f m bytes .
177196 ( Monad m
178- , Eq (TP. AnyMessage ps )
197+ , Eq (AnyMessage ps f )
179198 )
180199 => Codec ps failure f m bytes
181200 -> AnyMessage ps f
182201 -> m Bool
183- prop_codecM Codec {encode, decode} (AnyMessage f f' (msg :: Message ps st st' )) = do
184- r <- decode (stateToken :: StateToken st ) f >>= runDecoder [encode f' msg]
202+ prop_codecM Codec {encode, decode} a @ (AnyMessage f (msg :: Message ps st st' )) = do
203+ r <- decode (stateToken :: StateToken st ) f >>= runDecoder [encode f msg]
185204 case r :: Either failure (SomeMessage st ) of
186- Right (SomeMessage msg') -> return $ TP. AnyMessage msg' == TP. AnyMessage msg
205+ Right (SomeMessage msg') -> return $ AnyMessage f msg' == a
187206 Left _ -> return False
188207
189208-- | The 'Codec' round-trip property in a pure monad.
190209--
191210prop_codec
192211 :: forall ps failure f m bytes .
193- (Monad m , Eq (TP. AnyMessage ps ))
212+ (Monad m , Eq (AnyMessage ps f ))
194213 => (forall a . m a -> a )
195214 -> Codec ps failure f m bytes
196215 -> AnyMessage ps f
@@ -212,28 +231,28 @@ prop_codec runM codec msg =
212231--
213232prop_codec_splitsM
214233 :: forall ps failure f m bytes .
215- (Monad m , Eq (TP. AnyMessage ps ))
234+ (Monad m , Eq (AnyMessage ps f ))
216235 => (bytes -> [[bytes ]]) -- ^ alternative re-chunkings of serialised form
217236 -> Codec ps failure f m bytes
218237 -> AnyMessage ps f
219238 -> m Bool
220239prop_codec_splitsM splits
221- Codec {encode, decode} (AnyMessage f f' (msg :: Message ps st st' )) = do
240+ Codec {encode, decode} a @ (AnyMessage f (msg :: Message ps st st' )) = do
222241 and <$> sequence
223242 [ do r <- decode (stateToken :: StateToken st ) f >>= runDecoder bytes'
224243 case r :: Either failure (SomeMessage st ) of
225- Right (SomeMessage msg') -> return $ TP. AnyMessage msg' == TP. AnyMessage msg
244+ Right (SomeMessage msg') -> return $ AnyMessage f msg' == a
226245 Left _ -> return False
227246
228- | let bytes = encode f' msg
247+ | let bytes = encode f msg
229248 , bytes' <- splits bytes ]
230249
231250
232251-- | Like @'prop_codec_splitsM'@ but run in a pure monad @m@, e.g. @Identity@.
233252--
234253prop_codec_splits
235254 :: forall ps failure f m bytes .
236- (Monad m , Eq (TP. AnyMessage ps ))
255+ (Monad m , Eq (AnyMessage ps f ))
237256 => (bytes -> [[bytes ]])
238257 -> (forall a . m a -> a )
239258 -> Codec ps failure f m bytes
@@ -250,30 +269,30 @@ prop_codec_splits splits runM codec msg =
250269prop_codecs_compatM
251270 :: forall ps failure f m bytes .
252271 ( Monad m
253- , Eq (TP. AnyMessage ps )
272+ , Eq (AnyMessage ps f )
254273 , forall a . Monoid a => Monoid (m a )
255274 )
256275 => Codec ps failure f m bytes
257276 -> Codec ps failure f m bytes
258277 -> AnyMessage ps f
259278 -> m Bool
260279prop_codecs_compatM codecA codecB
261- (AnyMessage f f' (msg :: Message ps st st' )) =
262- getAll <$> do r <- decode codecB (stateToken :: StateToken st ) f >>= runDecoder [encode codecA f' msg]
280+ a @ (AnyMessage f (msg :: Message ps st st' )) =
281+ getAll <$> do r <- decode codecB (stateToken :: StateToken st ) f >>= runDecoder [encode codecA f msg]
263282 case r :: Either failure (SomeMessage st ) of
264- Right (SomeMessage msg') -> return $ All $ TP. AnyMessage msg' == TP. AnyMessage msg
283+ Right (SomeMessage msg') -> return $ All $ AnyMessage f msg' == a
265284 Left _ -> return $ All False
266- <> do r <- decode codecA (stateToken :: StateToken st ) f >>= runDecoder [encode codecB f' msg]
285+ <> do r <- decode codecA (stateToken :: StateToken st ) f >>= runDecoder [encode codecB f msg]
267286 case r :: Either failure (SomeMessage st ) of
268- Right (SomeMessage msg') -> return $ All $ TP. AnyMessage msg' == TP. AnyMessage msg
287+ Right (SomeMessage msg') -> return $ All $ AnyMessage f msg' == a
269288 Left _ -> return $ All False
270289
271290-- | Like @'prop_codecs_compatM'@ but run in a pure monad @m@, e.g. @Identity@.
272291--
273292prop_codecs_compat
274293 :: forall ps failure f m bytes .
275294 ( Monad m
276- , Eq (TP. AnyMessage ps )
295+ , Eq (AnyMessage ps f )
277296 , forall a . Monoid a => Monoid (m a )
278297 )
279298 => (forall a . m a -> a )
0 commit comments