【问题标题】:EAFP in HaskellHaskell 中的 EAFP
【发布时间】:2015-04-16 17:56:47
【问题描述】:

我对 Maybe 和 Either 类型以及它们与 EAFP(Easier Ask Forgiveness to Permission)的假设关系持怀疑态度。我使用过 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

还有可能:

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 漏洞。

【问题讨论】:

  • 我从未见过正式描述过“EAFP”或“LBYL”范式,所以我不知道如何回答 Haskell 是否“正式”支持它们。 Haskell 确实支持异常。就个人而言,我认为“EAFP”是一种反模式。
  • 你的意思是error函数?
  • error 函数就是一个例子,是的。
  • 我认为您在这里征求意见-问题是如果y = 0,您的预期行为是什么?因为这两个版本的行为非常不同 - 与 Python 相同(我猜 - 我真的不知道任何 Python)
  • @CarlosAlonsoGómez 您应该阅读一下最近发布的电子书Maybe Haskell。它以Maybe 类型作为一个反复出现的例子来解释Haskell 的一些核心概念,包括如何仅在程序的“边界”处传播和处理失败(缺少值)。这是一本好书。

标签: haskell exception-handling maybe


【解决方案1】:

带有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 表示。

【讨论】:

    猜你喜欢
    • 2010-09-29
    • 2012-07-06
    • 1970-01-01
    • 1970-01-01
    • 2017-10-21
    • 1970-01-01
    • 2011-03-06
    • 1970-01-01
    相关资源
    最近更新 更多