Home > Net >  How can I write a ToDhall instance for a ByteString, in Haskell?
How can I write a ToDhall instance for a ByteString, in Haskell?

Time:09-26

So I have a simple data structure that has some ByteStrings. I want to serialize these into Dhall files. However, I apparently can't just automatically derive ToDhall, since there's no instance for ToDhall. How do I write that?

data WordBounds = WordBounds { zipFile :: Prelude.FilePath
                             , start :: BS.ByteString
                             , end :: BS.ByteString
                             } deriving (Show, Generic, ToDhall)

I've tried instance ToDhall BS.ByteString and I think I'm getting closer, but I still don't quite understand what the syntax of instance is trying to do, and/or how to get it to work with Dhall.

CodePudding user response:

From the documentation, it looks like you could do something like this:

instance ToDhall ByteString where
    injectWith = contramap unpack . injectWith

This uses the two existing instances for ToDhall:

instance ToDhall Word8
instance ToDhall a => ToDhall [a]

...so the injectWith on the RHS of the equation is for [Word8], not a recursive call to the one for ByteString. It also uses

instance Contravariant Encoder

to convert an Encoder [Word8] to an Encoder ByteString.

That said, this will be an orphan instance. Most of the community would recommend that you do not do that. Alternatives include creating a newtype, as in

newtype Jonathan'sByteString = Jonathan'sByteString ByteString

and writing instances for that instead, or simply writing

jonathan'sInjectWith :: InputNormalizer -> Encoder ByteString
jonathan'sInjectWith = contramap unpack . injectWith

and then using that in a hand-written instance ToDhall WordBounds.

  • Related