哈斯克尔的EAFP

时间:2015-04-16 17:56:47

标签: haskell exception-handling maybe

我怀疑可能和两种类型,以及他们与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近似值?
  2. PD:我称之为“半离奇”,因为即使它具有直观可读性,它看起来(至少对我而言)就像它会使EAFP漏洞一样。

1 个答案:

答案 0 :(得分:8)

带有MaybeEither的Haskell样式会强制您检查某点处的错误,但不一定要马上。如果您现在不想处理错误,可以通过其余计算将其传播。

采用您假设的安全除以0的示例,您可以在没有明确检查的情况下在更广泛的计算中使用它:

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

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

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

从某种意义上说,这可以为您提供两全其美的体验。您仍然只需要在最后一个地方检查错误,但是您已经明确。你必须使用do-notation这样的东西来处理实际的传播,你不能偶然忽略最后的错误:如果你不想处理它,你必须把它变成运行时明确错误。

明显比隐含更好吗?

现在,Haskell还有一个处理运行时错误的异常系统,您根本不需要检查它们。这偶尔会有用,但不常见。在Haskell中,我们只将它用于我们期望永远捕获的错误 - 真正的异常情况。经验法则是运行时异常表示程序中的错误,而不正确的输入或仅仅是不常见的情况应该用MaybeEither表示。