Hasql: encode a sum-type

132 views Asked by At

How to encode the following sum-type using Hasql? I tried to create an encoder sumValue :: Value SumValue, but I can't pattern match. E.g. I would like to encode SumBool with Hasql.Encoders.bool and SumChar with Hasql.Encoders.char.

data SumValue
  = SumBool !(Maybe Bool)
  | SumChar !(Maybe Char)
  | SumDate !(Maybe Day)
  | ...
  | SumUuid !(Maybe UUID)
  deriving (Eq, Show)
1

There are 1 answers

0
Nikita Volkov On BEST ANSWER

While this seems highly likely to be a mistake in your design, in the current version of Hasql (0.19.*) it is possible to implement such an encoder at least on the level of Params. However I must notice that, unless provided with a use-case, which proves it useful, the support for this will be removed completely in the next major release in the sake of type-level security.

Either way, here's how you can do that now:

import qualified Hasql.Encoders as A

data SumValue
  = SumBool !(Maybe Bool)
  | SumChar !(Maybe Char)
  | SumDate !(Maybe Day)
  | SumUuid !(Maybe UUID)
  deriving (Eq, Show)

sumValue :: A.Params SumValue
sumValue =
  contramap match $
  chosen (A.nullableValue A.bool) $
  chosen (A.nullableValue A.char) $
  chosen (A.nullableValue A.date) $
  A.nullableValue A.uuid
  where
    match =
      \case
        SumBool x -> Left x
        SumChar x -> Right (Left x)
        SumDate x -> Right (Right (Left x))
        SumUuid x -> Right (Right (Right x))