如何使这个函数`shouldBeRight :: ab ab - > IO b`?

Leo*_*ang 0 haskell

我正在尝试使用以下两个函数来获取"正确"值或"正确"值.但是无法编译,为什么?

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
Run Code Online (Sandbox Code Playgroud)

以下是错误:

    • 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"
   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Run Code Online (Sandbox Code Playgroud)

Fyo*_*kin 8

编译器不知道您尝试的异常类型throwIO.

从错误消息判断,您可能已-XOverloadedStrings启用,这意味着字符串文字,例如"abcd",没有确定类型,但可以采用任何类型的预期,只要有一个IsString实例.最常用的字符串类型是StringText,但还有其他类型,您也可以自己创建.

另一方面,该函数也没有指定任何特定类型:只要有一个实例,它就会采用任何类型.throwIO:: Exception e => e -> IO aeException

所以编译器类型不知道要选择哪种类型.选择任何东西都没有根据.

应该解决的"正常"方式是创建自己的异常类型并为其提供一个Exception实例,如下所示:

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

instance Exception MyConversionException
Run Code Online (Sandbox Code Playgroud)

然后抛出:

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

...

shouldBeJust Nothing = throwIO NotJust
Run Code Online (Sandbox Code Playgroud)

如果您确实希望异常在发生时显示该特定文本,您始终可以为其提供自定义Show实例:

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
Run Code Online (Sandbox Code Playgroud)

或者,如果你只想要一个快速解决方案,你可以使用该error函数,它产生一个运行时异常,就像throwIO它的类型是纯的一样,所以它也可以在IO之外使用:

shouldBeJust Nothing = error "should be Just value but was Nothing"
Run Code Online (Sandbox Code Playgroud)