Reputation: 2048
I'm trying to use 'Either' in Haskell to get the right value. It is usually easy to do, but I'm getting an error, and I don't know what I'm doing wrong.
What I want to do is this:
cropImage image = do
resized <- resizeImage copy
newImage <- getImageFromEither resized
...
where resized
is defined as:
resized :: Either CV.CvException (M.Mat ('CV.S '['CV.D, 'CV.D]) channels depth)
And I want to get M.Mat ('CV.S '['CV.D, 'CV.D]) channels depth
to do it, I use this function:
getImageFromEither eitherImage = fromRight eitherImage
and:
fromRight :: Either a b -> b
fromRight (Left _) = error "fromRight: Argument takes form 'Left _'"
fromRight (Right x) = x
And I thought it should work. But I get this error:
Couldn't match kind ‘*’ with ‘CV.DS *'
When matching types
m :: * -> *
M.Mat ('CV.S '['CV.D, 'CV.D]) channels :: CV.DS * -> *
Expected type: Either CV.CvException (m t0)
Actual type: Either
CV.CvException (M.Mat ('CV.S '['CV.D, 'CV.D]) channels depth)
Relevant bindings include
resized :: Either
CV.CvException (M.Mat ('CV.S '['CV.D, 'CV.D]) channels depth)
(bound at src/CropImage.hs:25:9)
copy :: M.Mat ('CV.S '[height, width]) channels depth
(bound at src/CropImage.hs:32:17)
image :: M.Mat ('CV.S '[height, width]) channels depth
(bound at src/CropImage.hs:24:11)
cropImage :: M.Mat ('CV.S '[height, width]) channels depth
-> m (Either
CV.CvException (M.Mat ('CV.S '['CV.D, 'CV.D]) channels depth))
(bound at src/CropImage.hs:24:1)
In the first argument of ‘getImageFromEither’, namely ‘resized’
In a stmt of a 'do' block: newImage <- getImageFromEither resized
I don't have an idea what's wrong. I see the code right, but I'm blind with the error.
Upvotes: 0
Views: 357
Reputation: 116139
You likely want
cropImage image = do
resized <- resizeImage copy
let newImage = getImageFromEither resized
...
Remember that <-
is used to run monadic actions, and let .. = ..
is used to define pure values. Here, getImageFromEither
has not a monadic return type -- it does not perform any action in the monad, it is a plain, regular function.
Also consider the possibility of handling both cases explicitly:
cropImage image = do
resized <- resizeImage copy
case resized of
Left err -> error ("resize failed: " ++ show err)
Right newImage -> do
...
This also allows you to handle the error more gracefully, e.g. by reporting it to the user. Using error
or a partial function like your getImageFromEither
is not generally considered good style. Handling errors by crashing is convenient in the short term, but eventually you'll likely want that error to be handled properly.
Upvotes: 5