Haskell中的EAFP

4
我有一个关于Maybe和Either类型的疑问,以及它们与EAFP(易于请求宽恕而不是许可)的假设关系。我曾经使用Python并习惯于在异常世界中使用EAFP范例。
经典例子:除零操作。
def func(x,y):
    if not y:
        print "ERROR."
    else: return (x/y)

并且Python的风格:

def func(x,y):
    try:
        return (x/y)
    except: return None

在 Haskell 中,第一个函数应该是:
func :: (Eq a, Fractional a) => a -> a -> a
func x y = if y==0 then error "ERROR." else x/y

而且,使用Maybe:
func :: (Eq a, Fractional a) => a -> a -> Maybe a
func x y = if y==0 then Nothing else Just (x/y)

在Python版本中,您运行func而不检查y。在Haskell中,情况相反:y已经被检查。
我的问题是:

1. 正式来说,Haskell是否支持EAFP范例或“更偏爱”LBYL,即使它承认EAFP的半古怪的近似?

PD:我称之为“半古怪”,因为即使它在直觉上可读,但对我来说,它看起来像是违反了EAFP。


6
我从未见过正式描述“EAFP”或“LBYL”范例,因此我不知道如何回答Haskell是否“正式”支持它们。 Haskell确实支持异常。就个人而言,我认为“EAFP”是一种反模式。 - Rein Henrichs
我认为你在这里是在征询意见-问题是如果 y = 0,你期望的行为是什么?因为这两个版本的行为非常不同-对于 Python 也是如此(我猜的-我实际上不太了解 Python)。 - Random Dev
1
@CarlosAlonsoGómez 你应该阅读一下最近发布的电子书Maybe Haskell,它以Maybe类型作为一个重要例子来解释Haskell中一些核心概念,包括如何在程序的“边界”处传播和处理失败(值的缺失)。这是一本很好的读物。 - jub0bs
@CarstenKönig 这不是一个观点问题。如果看起来是这样,我很抱歉。 - Carlos Alonso Gómez
@Jubobs 或许我会看一下。我想知道它是否解释了关于“Applicative”类的内容,因为我无法理解它。 - Carlos Alonso Gómez
显示剩余3条评论
1个回答

9
使用Haskell风格的MaybeEither,你需要在某个时刻检查错误,但不一定要立即检查。如果你现在不想处理错误,可以将其传递到计算的其余部分。
以安全除零为例,你可以在不进行显式检查的情况下将其用于更广泛的计算中。
do result <- func a b
   let x = result * 10
   return x

在这里,您不必匹配由func返回的Maybe:您只需使用do-notation将其提取到result变量中,它会自动传播失败。结果是,您不需要立即处理潜在的错误,而计算的最终结果本身被包装在Maybe中。
这意味着您可以轻松地组合(合成)可能导致错误的函数,而无需在每个步骤上检查错误。
从某种意义上说,这为您提供了最好的两个世界。您仍然只需要在最后一个位置检查错误,但您对此有明确的了解。您必须使用类似于do-notation的东西来处理实际的传播,而且您不能无意中忽略最终错误:如果您不想处理它,则必须明确将其转换为运行时错误。
显式比隐式更好,不是吗?
现在,Haskell还具有异常系统,可用于处理根本不需要检查的运行时错误。这偶尔很有用,但并不经常。在Haskell中,我们仅将其用于我们不希望捕获的错误——真正的异常情况。经验法则是,运行时异常表示程序中的错误,而不当的输入或仅仅是不常见的情况应该用MaybeEither表示。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接