Haskell 中的 EAFP

EAFP in Haskell

我怀疑 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 范式或 "prefers" LBYL 尽管承认半奇怪的 EAFP 近似?

PD:我打电话给 "semi-bizarre" 是因为,即使它直观可读,它看起来(至少对我而言)就像它会破坏 EAFP。

带有 MaybeEither 的 Haskell 样式强制您在 某个点 检查错误,但它没有马上。如果您现在不想处理错误,您可以将其传播到其余的计算中。

以您假设的安全除以 0 为例,您可以在更广泛的计算中使用它而无需显式检查:

do result <- func a b
   let x = result * 10
   return x

在这里,您不必匹配 func 返回的 Maybe:您只需使用 do-notation 将其提取到 result 变量中,它会自动传播失败始终。结果是您不需要立即处理潜在的错误,但计算的最终结果包含在 Maybe 本身中。

这意味着您可以轻松组合(组合)可能导致错误的函数,而无需在每一步检查错误。

从某种意义上说,这可以让您两全其美。你仍然只需要在最后检查一个地方的错误,但你明确。您必须使用诸如 do-notation 之类的东西来处理实际的传播,并且您不能意外地忽略最终错误:如果您不想处理它,则必须明确地将其转换为运行时错误。

显式不是比隐式好吗?

现在,Haskell 也有一个异常系统,用于处理您根本不必检查的运行时错误。这偶尔有用,但不会太频繁。在 Haskell 中,我们仅将其用于我们 不希望 捕获的错误——真正的异常情况。经验法则是,运行时异常表示 程序中的错误 ,而不正确的输入或仅仅是不常见的情况应表示为 MaybeEither .