2 haskell types function return-value
如何从单个函数返回多个类型的值?
我想做的事情如下:
take x y | x == [] = "error : empty list"
| x == y = True
| otherwise = False
Run Code Online (Sandbox Code Playgroud)
我有必要的语言背景.
有一个类型构造函数Either,可以让您创建一个可以是两种类型之一的类型.它通常用于处理错误,就像在您的示例中一样.你会像这样使用它:
take x y | x == [] = Left "error : empty list"
| x == y = Right True
| otherwise = Right False
Run Code Online (Sandbox Code Playgroud)
那样的类型take会是这样的Eq a => [a] -> [a] -> Either String Bool.Either用于错误处理的约定是Left表示错误并Right表示正常返回类型.
如果您有Either类型,则可以对其进行模式匹配以查看它包含的值:
case take x y of
Left errorMessage -> ... -- handle error here
Right result -> ... -- do what you normally would
Run Code Online (Sandbox Code Playgroud)
您的问题有几种解决方案,具体取决于您的意图:您是否希望在您的类型中制作您的功能可能失败的清单(在这种情况下,您希望返回失败的原因,如果有的话,这可能是不必要的这里只有一种失败模式)或者你估计在这个函数中得到一个空列表根本不应该发生,所以想要立即失败并抛出异常?
因此,如果您想明确表示类型失败的可能性,可以使用Maybe,只是在没有解释的情况下指出失败(最终在您的文档中):
take :: (Eq a) => [a] -> [a] -> Maybe Bool
take [] _ = Nothing
take x y = x == y
Run Code Online (Sandbox Code Playgroud)
或者要么注册失败的原因(注意,一般来说,或者是"从一个函数返回两种类型"的答案,尽管你的代码更具体):
take :: (Eq a) => [a] -> [a] -> Either String Bool
take [] _ = Left "Empty list"
take x y = Right $ x == y
Run Code Online (Sandbox Code Playgroud)
最后,您可以发出信号,表示此故障完全异常且无法在本地处理:
take :: (Eq a) => [a] -> [a] -> Bool
take [] _ = error "Empty list"
take x y = x == y
Run Code Online (Sandbox Code Playgroud)
请注意,使用这种最后一种方式,调用站点不必立即处理失败,实际上它不能,因为异常只能在IO monad中捕获.使用前两种方式,必须修改调用站点以处理失败(并且可以)的情况,如果仅对其自身调用"错误".
有一个最终解决方案允许调用代码选择您想要的失败模式(使用失败包http://hackage.haskell.org/package/failure):
take :: (Failure String m, Eq a) => [a] -> [a] -> m Bool
take [] _ = failure "Empty list"
take x y = return $ x == y
Run Code Online (Sandbox Code Playgroud)
这可以模仿Maybe和Either解决方案,或者你可以使用take作为IO Bool,如果它失败将抛出异常.它甚至可以在[Bool]上下文中工作(如果失败则返回空列表,这有时很有用).