我正在尝试使用以下两个函数来获取"正确"值或"正确"值.但是无法编译,为什么?
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)
编译器不知道您尝试的异常类型throwIO.
从错误消息判断,您可能已-XOverloadedStrings启用,这意味着字符串文字,例如"abcd",没有确定类型,但可以采用任何类型的预期,只要有一个IsString实例.最常用的字符串类型是String和Text,但还有其他类型,您也可以自己创建.
另一方面,该函数也没有指定任何特定类型:只要有一个实例,它就会采用任何类型.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)