2012-01-05 38 views
22

公式定义的函数我今天注意到,这样的定义用不同数量的参数

是不可能的。我只是好奇这背后的(好)理由是什么。必须有一个很好的(毕竟是Haskell :))。

注意:我不想看看上面代码的其他实现的建议,这是一个简单的例子来证明我的观点。

+4

你称之为“安全”?让它返回一个'Maybe'或其他东西,或者抛出一些已知的异常,或者将它用于'newtype',这个''newtype'专门用于你认为是非退化函数的例子。 L 2希尔伯特空间(即只有定义的模空集);那将是安全的。只为所有的'分数'实例定义'x/0 = x' _ad hoc_是非常奇怪的! - 好吧,这可能只是一个例子。 – leftaroundabout 2012-01-05 18:21:46

+0

+1哇,一直使用Haskell多年,从未注意到这样的定义是不允许的! – is7s 2012-01-05 19:30:47

+0

@leftaroundabout'safeDivide x 0 = Nothing; safeDivide = Just。:(/)'better? :) – 2012-01-06 01:13:11

回答

25

我认为这主要是为了保持一致性,所以所有的子句都可以用同样的方式阅读,可以这么说;即每个RHS在功能类型中处于相同的位置。如果你允许的话,我认为会掩盖一些愚蠢的错误。

还有一个轻微的语义怪癖:说编译器填补了这些子句与其他子句具有相同数量的模式;即你的榜样将成为

safeDivide x 0 = x 
safeDivide x y = (/) x y 

现在考虑如果第二线已经代替了safeDivide = undefined;在没有前面的条款的情况下,safeDivide将是,但是由于在此执行的eta扩展,因此它是\x y -> if y == 0 then x else ⊥ - 因此safeDivide = undefined实际上并没有将safeDivide定义为!这似乎令人困惑,足以证明禁止这些条款,国际海事组织。

+0

那么没有更深的技术原因吗? – aelguindy 2012-01-05 16:14:51

+1

@aelguindy:其实,是的!我已经更新了我的答案:) – ehird 2012-01-05 16:23:43

+0

感谢代码格式编辑:),将从现在开始。我花了一段时间才弄明白为什么它是const(const \ bot),但现在我明白了。 – aelguindy 2012-01-05 16:31:47

11

与多个子句函数的含义由Haskell的标准(section 4.4.3.1)通过翻译定义为一个lambda和case声明:

fn pat1a pat1b = r1 
fn pat2a pat2b = r2 

成为

fn = \a b -> case (a,b) of 
    (pat1a, pat1b) -> r1 
    (pat2a, pat2b) -> r2 

这是这样,函数定义/案例陈述的做事方式是好的和一致的,每一个的含义都没有冗余和混淆。

只有每个子句具有相同数量的参数时,这种翻译才有意义。当然,可能会有额外的规则来解决这个问题,但是它们会使翻译变得复杂并且收益不大,因为为了读者的缘故,您可能不希望定义类似的东西。

4

Haskell这样做是因为它的前身(如LML和Miranda)所做的。没有技术上的理由,它必须是这样的;可以扩展具有较少参数的方程。但是对于不同的方程有不同数量的参数可能是一个错字而不是故意的,所以在这种情况下,我们禁止某些合理的东西,以在常见情况下获得更好的错误报告。

相关问题