From f900dc37b70cc388683667be86af8ae7b92a4ed1 Mon Sep 17 00:00:00 2001 From: Nick Ivanych Date: Tue, 7 Jul 2026 02:20:54 +0200 Subject: [PATCH] Derive PgMsgParser's Applicative and Alternative via ReaderT The hand-written instances were the pointwise lifting of Maybe through two readers, which is exactly what ReaderT Char (ReaderT LBS.ByteString Maybe) provides. Deriving via that type makes the instances lawful by construction and removes the TODO questioning the Applicative laws. --- hpgsql/src/Hpgsql/Msgs.hs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/hpgsql/src/Hpgsql/Msgs.hs b/hpgsql/src/Hpgsql/Msgs.hs index c1f432e..afcef5d 100644 --- a/hpgsql/src/Hpgsql/Msgs.hs +++ b/hpgsql/src/Hpgsql/Msgs.hs @@ -2,6 +2,7 @@ module Hpgsql.Msgs (AuthenticationResponse (..), AuthenticationMethod (..), Back import Control.Applicative (Alternative (..)) import Control.Monad (replicateM) +import Control.Monad.Trans.Reader (ReaderT (..)) import qualified Crypto.Hash as Crypto import qualified Data.Attoparsec.ByteString as Parsec import qualified Data.Attoparsec.ByteString.Lazy as LazyParsec @@ -38,16 +39,7 @@ newtype PgMsgParser a Maybe a ) deriving stock (Functor) - -instance Applicative PgMsgParser where - pure a = PgMsgParser $ \_ _ -> Just a - - -- TODO: Is this Applicative correct? Double-check laws - PgMsgParser f <*> PgMsgParser p = PgMsgParser $ \c r -> f c r <*> p c r - -instance Alternative PgMsgParser where - empty = PgMsgParser $ \_ _ -> Nothing - PgMsgParser p1 <|> PgMsgParser p2 = PgMsgParser $ \c restOfMsg -> p1 c restOfMsg <|> p2 c restOfMsg + deriving (Applicative, Alternative) via (ReaderT Char (ReaderT LBS.ByteString Maybe)) class FromPgMessage a where msgParser :: PgMsgParser a