Haskell中的参数命名规则

5

为什么不允许在同一等式中出现相同名称的参数?

示例:

f a a = show a

d && d = d
_ && _ = False

从技术上讲,形式参数(报告称之为变量)也是模式,只不过它们永远不会匹配失败。作为成功匹配的“副作用”,形式参数被绑定到它正在匹配的值上。因此,在任何一个方程中,模式不允许有多个相同形式参数的出现(这被称为线性特性 §3.17、§3.3、§4.4.3)。


1
那会是什么意思呢?例如,如果你像这样调用 ff 1 2,结果应该是什么? - Pedro Rodrigues
@fjh- 如果 xy 没有 Eq 实例,或者它们是不同的类型,则意味着与 f x y | x == y = .... 完全相同的含义- 编译器错误。 - jamshidh
但是为什么要专门为“==”添加特定的语法表达式呢?守卫是通用的,可以接受任何谓词。 - Impredicative
@Impredicative 它使模式匹配更加强大。我喜欢 Prolog 和 Erlang 中的这一点。 - kqr
@Impredicative- 因为无论我们多么希望否认它,(==) 是特殊的... - jamshidh
显示剩余3条评论
2个回答

13
根据这篇邮件列表帖子,在Miranda中允许这样做并且这是常见的错误源头:人们会无意中给两个变量取相同的名称,而很难发现这种微妙的错误。因此,Haskell禁止这样做,而是明确添加保护条件。
我个人认为,这对于代码阅读者也更友好,因为遵循这条规则后,在模式匹配的现场不需要记住所有不同作用域中的变量,以查看该模式是否实际上匹配了所有内容。

好的回答-我也想补充一些内容.... Perl正则表达式基本上允许类似于反向引用的东西(即在RE中跟随一个单个数字的反斜杠,例如/(\w+) \1/,它匹配由空格分隔的相同单词)。也许如果Haskell本身有一个反向引用字符,就像f x \x = ....,那么它可能会更少出错。 - jamshidh
嗨@Daniel,谢谢。然而我不能说我理解你在个人意见中的意思。你能用不同的措辞写出来或者甚至尝试用例子说明吗? - t0ma5
@tomas 嗯,我想归根结底,我只是在重申第一段。但我试图表达的观点是,如果您有一个带有许多参数的函数,每个参数都是一个模式,例如 foo (Person name age id) (Person name' age' id') (Company name location ceo) 或类似的东西,那么阅读此代码的人会感到疲劳,以便解密哪些变量匹配所有值,哪些是“特殊”的 - 例如,您是否注意到此模式仅在您恰好传递具有相同名称的人和公司时才匹配? - Daniel Wagner
@tomas 另外,我想到有人可能会说,“如果能够扩展这个功能,当全局变量mySuperDuperConstant在作用域内时,我也可以使用隐含的等式来匹配它。比如,mySuperDuperConstant = 42; foo mySuperDuperConstant = 0; foo _ = 1 应该将 42 映射为 0,将其他所有内容映射为 1。” 突然间,问题变得十倍复杂:你不仅需要检查同一模式中的其他变量,还需要检查每个作用域内的变量。我认为,长参数列表与长全局常量列表并没有太大的区别。 - Daniel Wagner
@Daniel,非常好。非常感谢! - t0ma5

1
您无法定义


d && d = d
_ && _ = False

因为你试图在一个变量上使用模式匹配。
模式匹配只能用于数据构造函数,所以。
True && True = True

是可以的,但

d && d = d

意思是“取第一个参数(我们称之为d)和第二个参数(我们称之为d)然后……”,但编译器打断你说:“不,等一下,不要都叫d,我不知道你指的是哪个!”然后你说:“但如果它们相同,我只想让你这样做” ,编译器说:“那不是名称的作用 - 用a == b进行测试。请不要在没有使用==的情况下检查相等性,除非通过将数据实例化为Eq类型类来定义==,在这种情况下,我希望你在类型签名中警告我,以便我可以获得正确的==编译定义。”
当你说f a a = show a,然后要求它show 3 4,编译器会说“你想让我显示哪一个?”

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接