我正在尝试在Haskell中使用'Either'来获取正确的值。这通常很容易,但我收到了一个错误,我不知道我做错了什么。
我想做的是:
cropImage image = do
resized <- resizeImage copy
newImage <- getImageFromEither resized
...
其中resized
定义为:
resized :: Either CV.CvException (M.Mat ('CV.S '['CV.D, 'CV.D]) channels depth)
我希望得到M.Mat ('CV.S '['CV.D, 'CV.D]) channels depth
要做到这一点,我使用这个功能:
getImageFromEither eitherImage = fromRight eitherImage
和:
fromRight :: Either a b -> b
fromRight (Left _) = error "fromRight: Argument takes form 'Left _'"
fromRight (Right x) = x
我认为它应该有效。但是我得到了这个错误:
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
我不知道出了什么问题。我看到代码正确,但我对错误视而不见。
答案 0 :(得分:5)
你可能想要
cropImage image = do
resized <- resizeImage copy
let newImage = getImageFromEither resized
...
请记住,<-
用于运行monadic操作,let .. = ..
用于定义纯值。这里,getImageFromEither
没有monadic返回类型 - 它不会在monad中执行任何操作,它是一个普通的常规函数。
还要考虑明确处理这两种情况的可能性:
cropImage image = do
resized <- resizeImage copy
case resized of
Left err -> error ("resize failed: " ++ show err)
Right newImage -> do
...
这也允许您更优雅地处理错误,例如通过向用户报告。使用error
或部分函数(例如getImageFromEither
)通常不会被认为是好的风格。通过崩溃处理错误在短期内很方便,但最终你可能希望正确处理错误。