4
\$\begingroup\$

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 -> IO (Maybe (Int, Int))
getImageSize path = do
 img <- readImage path
 case img of
 Left _ -> return Nothing
 Right img' -> return (go img')
 where
 go :: DynamicImage -> Maybe (Int, Int)
 go (ImageRGB8 (Image w h _)) = Just (w, h)
 go (ImageRGBA8 (Image w h _)) = Just (w, h)
 go _ = Nothing
getImageSizeVec :: FilePath -> IO Vec2D
getImageSizeVec path = do
 res <- getImageSize path
 let dims = fromMaybe (0, 0) res
 return $ Vec2D (fromIntegral (fst dims)) (fromIntegral (snd dims)) 
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Jan 12, 2016 at 18:00
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$
  1. I do not understand what benefit you get from the conversion to float
  2. 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 -> 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 -> 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) -> 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 -> Either String (Int, Int)
 sizeToVec :: (Int,Int) -> Vec2D

the last two you can combine à la

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

and the first two

doStuff = do eitherImg <- readImg mypathtoimg
 return $ do size <- getImageSize
 sizeToVec size

or

doStuff = do eitherImg <- readImg mypathtoimg
 return (getImageSize eitherImg >>= sizeToVec)

or even shorter

(削除) doStuff = readImg mypathtoimg >>= (getImageSize >>= sizeToVec) (削除ここまで)

doStuff = readImg path >>= fmap sizeToVec . getImageSize

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

answered Jan 12, 2016 at 21:59
\$\endgroup\$
1
  • \$\begingroup\$ sizeToVec has the wrong type for >>=. Perhaps you meant readImg path >>= fmap sizeToVec . getImageSize? \$\endgroup\$ Commented Jan 17, 2016 at 15:27

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.