[英]Haskell data type function parameter
对于参数的数据类型,Haskell中的函数定义中的括号有什么意义。
例如:
doStuff Name -> Age -> String
doStuff (NameConstr a) (AgeConstr b) = "Nom: " ++ a ++ ", age: " ++ b
预先在某处定义以下内容:
data Name = NameConstr String
data Age = AgeConstr Integer
功能参数a和b是否可以在这里取消对括号的需要?
仅供参考,我正在努力:
我似乎无法掌握这个更精细的细节。
没有括号,该函数将被视为具有四个参数。 我想不出一个反例,即省略括号会导致含糊不清。
如果需要,您可以按如下方式重新定义类型:
data Name = NameConstr { getName :: String }
data Age = AgeConstr { getAge :: Integer }
这样你的功能就可以变成:
doStuff n a = "Nom: " ++ getName n ++ ", age: " ++ show (getAge a)
(修复了最后一部分; a
是一个Integer
,不能连接成一个字符串)
实际上,有可能为(甚至嵌套的)模式解析简单的语法而根本没有parens。 假设这样一个:
<PAT> ::= <WILDCARD> | <VAR> | <CON0> | <CON1> <PAT> | <CON2> <PAT> <PAT> ...
<VAR> ::= <LNAME>
<CON*> ::= <UNAME>
<WILD> ::= "_"
其中LNAME是以小写字母开头的名称,UNAME以大写字母开头。 解析时我们应该查找构造函数名称,以便我们找到它的arity。 然后我们可以使用arity信息解析构造函数字段。 但是这种查找可能会使解析本身变得复杂化并减慢其速度。 Haskell具有更复杂的模式(视图模式,“作为”模式,记录,具有任意固定性的中缀构造函数等)并且省略parens可能导致模糊性。
虽然还有另一个原因不这样做。 请考虑以下代码:
data Bar = Bar Int
data Foo = Foo Int
libFunction Foo a Bar b = a + b
someUse bar foo = libFunction foo bar
接下来想象我们稍微更改数据类型:
data Bar = Bar
data Foo = Foo Int Bar Int
修改后的代码可能仍然存在类似问题,但该功能将不符合我们的预期。 虽然不是现实世界的例子。 而且由于Haskell有类型类,因此很难找到出错的地方。
换句话说:我们可以放松错误消息的质量,而且parens可以防止我们在更改后出现意外行为。
它有点傻,但在这种情况下,实际上有一种方法可以避免使用括号:
doStuff :: Name -> Age -> String
NameConstr a `doStuff` AgeConstr b = "Nom: " ++ a ++ ", age: " ++ b
这与定义中缀运算符的方式完全相同,并且使用反引号作为infix-ify非运算符标识符在将其定义为应用时也同样有效。
不过,我不推荐使用你不希望在backtick-y中缀风格中使用的函数实际执行此操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.