在haskell中遇到'Either'的麻烦

Chu*_*lar 0 haskell

我正在尝试在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)

我不知道什么是错的.我看到代码正确,但我对错误视而不见.

chi*_*chi 5

你可能想要

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通常不被认为是好的风格.通过崩溃处理错误在短期内很方便,但最终您可能希望正确处理该错误.