Search code examples
haskellencodinghasql

Hasql: encode a sum-type


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)

Solution

  • 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))