为了获得“ Right”值或“ Just”值,我正在尝试实现以下两个功能。但是不能编译,为什么呢?
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
以下是错误:
• 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"
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
答案 0 :(得分:8)
编译器不知道您要尝试throwIO
的异常类型。
从错误消息来看,您可能已启用-XOverloadedStrings
,这意味着字符串文字,例如"abcd"
,没有确定的类型,但是可以采用任何期望的类型,只要有一个IsString
实例即可。最常用的字符串类型是String
和Text
,但是还有其他类型,您也可以自己创建。
另一方面,函数throwIO
:: Exception e => e -> IO a
也没有指定任何特定类型:只要有e
,它就可以使用任何类型Exception
。实例。
因此,编译器类型不知道选择哪种类型。没有任何选择的依据。
应该解决的“正常”方法是创建自己的异常类型并为其提供一个Exception
实例,如下所示:
data MyConversionException = NotJust | NotRight String deriving (Typeable, Show)
instance Exception MyConversionException
然后将其抛出:
shouldBeRight (Left a) = throwIO $ NotRight (show a)
...
shouldBeJust Nothing = throwIO NotJust
如果您确实希望异常在发生时显示该特定文本,则可以始终为其提供自定义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
或者,如果您只想要快速解决问题的方法,可以使用error
函数,该函数会生成运行时异常,类似于throwIO
,但其类型是纯净的,因此也可以在IO外部使用:
shouldBeJust Nothing = error "should be Just value but was Nothing"