Converting image size from Maybe (Int, Int) to (Float, Float) I have a function that returns size of an image IO (Maybe (Int, Int))
It would be nice to convert it to float tuple beautifully.

I am sure there must be a better way than what I currently have:

data Vec2D = Vec2D Float Float

getImageSize :: FilePath -&gt; IO (Maybe (Int, Int))
getImageSize path = do
    img &lt;- readImage path
    case img of
        Left _ -&gt; return Nothing
        Right img' -&gt; return (go img')
    where
        go :: DynamicImage -&gt; Maybe (Int, Int)
        go (ImageRGB8 (Image w h _)) = Just (w, h)
        go (ImageRGBA8 (Image w h _)) = Just (w, h)
        go _ = Nothing

getImageSizeVec :: FilePath -&gt; IO Vec2D
getImageSizeVec path = do
    res &lt;- getImageSize path
    let dims = fromMaybe (0, 0) res
    return $ Vec2D (fromIntegral (fst dims)) (fromIntegral (snd dims))
I do not understand what benefit you get from the conversion to float
I would advise you to not mix - IO with the mostly pure calculation you have


so let us look at your code (minus the IO)

getImageSize :: DynamicImage -&gt; Maybe (Int, Int)
getImageSize (ImageRGB8  (Image w h _)) = Just (w, h)
getImageSize (ImageRGBA8 (Image w h _)) = Just (w, h)
getImageSize _ = Nothing


but readImage already has a more useful return type than Maybe it has an Either String which is giving you error messages instead of Nothing so we can adjust.

getImageSize :: DynamicImage -&gt; Either String (Int, Int)
getImageSize (ImageRGB8  (Image w h _)) = Right (w, h)
getImageSize (ImageRGBA8 (Image w h _)) = Right (w, h)
getImageSize _ = Left "Image type neither ImageRGB8 or ImageRGBA8"


this section could be improved a bit - also working on pure data

sizeToVec :: (Int,Int) -&gt; Vec2D
sizeToVec (x,y) = Vec2D (fromIntegral x) (fromIntegral y)


you can then use those with the many mechanisms haskell provides you:

 readImage path :: IO (Either String DynamicImage)
 getImageSize :: DynamicImage -&gt; Either String (Int, Int)
 sizeToVec :: (Int,Int) -&gt; Vec2D


the last two you can combine à la

fmap sizeToVec (getImageSize img) -- or fmap sizeToVec . getImageSize


and the first two

doStuff = do eitherImg &lt;- readImg mypathtoimg
             return $ do size &lt;- getImageSize
                         sizeToVec size


or

doStuff = do eitherImg &lt;- readImg mypathtoimg
             return (getImageSize eitherImg &gt;&gt;= sizeToVec)


or even shorter

doStuff = readImg mypathtoimg &gt;&gt;= (getImageSize &gt;&gt;= sizeToVec)

doStuff = readImg path &gt;&gt;= fmap sizeToVec . getImageSize

if I am not mistaken (I have no haskell env on this machine, therefore this code is untested - sorry)