Haskell 如何使这样的函数'shouldBeRight::a b->;IO b`?
为了得到“正确”的值或“公正”的值,我尝试做如下两个函数。但是不能编译,为什么Haskell 如何使这样的函数'shouldBeRight::a b->;IO b`?,haskell,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
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"
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
编译器不知道您试图通过
throwIO
执行的异常类型
从错误消息判断,您可能启用了-XOverloadedStrings
,这意味着字符串文本(例如“abcd”
)没有确定的类型,但可以采用预期的任何类型,只要有IsString
实例。最常用的字符串类型是string
和Text
,但也有其他类型,您也可以自己制作
另一方面,函数::Exception e=>e->IO a
也没有指定任何特定的类型:它接受任何类型e
,只要它有一个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
或者,如果您只是想要一个quick-n-dirty解决方案,您可以使用该函数,该函数生成运行时异常,非常类似于throwIO
,但其类型为纯,因此也可以在IO外部使用:
shouldBeJust Nothing = error "should be Just value but was Nothing"
如果说
throwIO
的参数需要是Exception
类的一个实例,而String
似乎不是,那么这似乎是一种相当混乱的说法。或者至少《代码》中的throwIO建议了这样的解释。我明白了。使用error
替代工作为什么在IO
环境中提到error
,在这里有一个更干净的机制可用?@dfeuer有两个原因:(1)从代码的其余部分判断,OP很可能在寻找一个快速修复方法,(2)评论中已经建议了error
,而OP也选择了这样做。