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