简体   繁体   中英

How to make such function `shouldBeRight :: Either a b -> IO b`?

I'm trying to make such two functions as below in order to get the "Right" value or the "Just" value. But can't compile, why?

shouldBeRight :: (Show a) => Either a b -> IO b
shouldBeRight (Left a) =
  throwIO $ concat ["should be Right value but wasn't, because:", show a]
shouldBeRight (Right b) = return b

shouldBeJust :: Maybe a -> IO a
shouldBeJust Nothing = throwIO "should be Just value but was Nothing"
shouldBeJust (Just a) = return a

Here are the errors:

    • Ambiguous type variable ‘e0’ arising from a use of ‘throwIO’
      prevents the constraint ‘(GHC.Exception.Exception
                                  e0)’ from being solved.
      Probable fix: use a type annotation to specify what ‘e0’ should be.
      These potential instances exist:
        30 instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the expression: throwIO "should be Just value but is nothing"
      In an equation for ‘shouldBeJust’:
          shouldBeJust Nothing
            = throwIO "should be Just value but is nothing"
   |
23 | shouldBeJust Nothing = throwIO "should be Just value but is nothing"
   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...

    • Ambiguous type variable ‘e0’ arising from the literal ‘"should be Just value but is nothing"’
      prevents the constraint ‘(Data.String.IsString
                                  e0)’ from being solved.
      Probable fix: use a type annotation to specify what ‘e0’ should be.
      These potential instances exist:
        instance a ~ Char => Data.String.IsString [a]
          -- Defined in ‘Data.String’
        ...plus 13 instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the first argument of ‘throwIO’, namely
        ‘"should be Just value but is nothing"’
      In the expression: throwIO "should be Just value but is nothing"
      In an equation for ‘shouldBeJust’:
          shouldBeJust Nothing
            = throwIO "should be Just value but is nothing"
   |
23 | shouldBeJust Nothing = throwIO "should be Just value but is nothing"
   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The compiler doesn't know the type of exception that you're trying to throwIO .

Judging from the error messages, you probably have -XOverloadedStrings enabled, which means that string literals, eg "abcd" , don't have a definitive type, but can take on whatever type is expected, provided that there is an IsString instance for it. The most frequently used string types are String and Text , but there are others, and you can also make your own.

On the other hand, the function throwIO :: Exception e => e -> IO a also doesn't specify any specific type: it takes any type e , as long as there is an Exception instance for it.

So the compiler kind of doesn't know which types to pick. There is no basis for picking anything.

The "normal" way this should be solved is to create your own exception type and give it an Exception instance, like this:

data MyConversionException = NotJust | NotRight String deriving (Typeable, Show)

instance Exception MyConversionException

And then throw that:

shouldBeRight (Left a) = throwIO $ NotRight (show a)

...

shouldBeJust Nothing = throwIO NotJust

If you really want your exception to display that specific text when it happens, you can always give it a custom Show instance:

instance Show MyConversionException where
    show NotJust = "should be Just value but was Nothing"
    show (NotRight leftValue) = "should be Right value but wasn't, because:" ++ leftValue

Alternatively, if you just want a quick-n-dirty solution, you can use the error function, which generates a runtime exception, much like throwIO , except its type is pure, so it can be used outside IO as well:

shouldBeJust Nothing = error "should be Just value but was Nothing"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM