我怀疑可能和两种类型,以及他们与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
已被检查。
我的问题:
答案 0 :(得分:8)
带有Maybe
和Either
的Haskell样式会强制您检查某点处的错误,但不一定要马上。如果您现在不想处理错误,可以通过其余计算将其传播。
采用您假设的安全除以0的示例,您可以在没有明确检查的情况下在更广泛的计算中使用它:
do result <- func a b
let x = result * 10
return x
在这里,您不必匹配Maybe
返回的func
:您只需使用do-notation将其提取到result
变量中,这会自动传播失败始终。结果是你不需要立即处理潜在的错误,但计算的最终结果包含在Maybe
本身。
这意味着您可以轻松组合(撰写)导致错误的功能,而无需在每一步检查错误。
从某种意义上说,这可以为您提供两全其美的体验。您仍然只需要在最后一个地方检查错误,但是您已经明确。你必须使用do-notation这样的东西来处理实际的传播,你不能偶然忽略最后的错误:如果你不想处理它,你必须把它变成运行时明确错误。
明显比隐含更好吗?
现在,Haskell还有一个处理运行时错误的异常系统,您根本不需要检查它们。这偶尔会有用,但不常见。在Haskell中,我们只将它用于我们不期望永远捕获的错误 - 真正的异常情况。经验法则是运行时异常表示程序中的错误,而不正确的输入或仅仅是不常见的情况应该用Maybe
或Either
表示。