Search code examples
haskellhip

Haskell, HIP library, decode function


Please help me understand how to use the decode function from the HIP library.

class ImageFormat format => Readable img format where
  decode :: format -> B.ByteString -> Either String img

I don't understand the first parameter, what should it be? Example would help.


Solution

  • Type classes are a little bit messy when you have fat arrows. The intention of typeclass Readable is to defined the set of types which can be read from a given ImageFormat, where an ImageFormat is a typeclass too. A little verbose but It'll be clear below; bear with me.

    class ImageFormat format => Readable img format where
      decode :: format -> B.ByteString -> Either String img
    --          |         |               |- returns codification error or the something of type img.
    --          |         |- This is the raw bytestring of the image
    --          |- This is a type which implements the ImageFormat typeclass  (see below)
    

    Now, you can check in the documentation the instances of each type class. For example ImageFormat has these instances.

    enter image description here

    So, your first argument should be one of those. But not only so, you also need to be sure that the pair img format implements the Readable typeclass. For example Readable has these instances (among others):

    • Readable (Image VS RGB Double) PNG
    • Readable [Image VS RGB Double] (Seq GIF)

    You can interpret these as "from a PNG I can read and Image VS RGB Double and from a sequence of GIF I can read [Image VS RGB Double] (list of images)". But more important there is no(!!) instance

    • Readable [Image VS RGB Double] PNG

    Which means that you can't read a list of images from a PNG.

    That being said, how do you use the decode function?. well, we know that the first argument should be one of the instances of ImageFormat, so lets pick PNG

    my_bytestring :: ByteString
    my_bytestring = ... whateve
    
    wrong_my_image = decode PNG some_bytestring
    -- You could think that this read an Image from a PNG but, which image should we pick??
    -- There are many instances for this. For example:
    -- Readable (Image VS RGB Double) PNG  reads a PNG as a Vector of Doubles in the RGB color space
    -- Readable (Image VS RGBA Word8) PNG  reads a PNG as a Vector of 8-bits unsigned integers in the RGB with alpha color space
    -- Readable (Image VS Y Word16) PNG    reads a PNG as a Vector of 16-bits unsigned integers in the YUV color space
    -- etc...
    
    right_my_image_1 :: Either String (Image VS RGB Double) -- For example
    right_my_image_1 = decode PNG my_bytestring
    
    right_my_image_2 = decode PNG my_bytestring :: Either String (Image VS RGB Double)
    -- Notice that you must(!!) specify the type you want to read to with explicit
    -- annotations. Wheter the annotation is in two lines or one line is up to you.