2013-04-14 174 views
4

对于参数的数据类型,Haskell函数定义中括号的含义是什么。Haskell数据类型函数参数

例如:

doStuff Name -> Age -> String 
doStuff (NameConstr a) (AgeConstr b) = "Nom: " ++ a ++ ", age: " ++ b 

与下面定义的某事先:

data Name = NameConstr String 
data Age = AgeConstr Integer 

能函数的参数a和b在否定了括号这里需要一种方法来捕捉?

通知你,我努力通过:

,我似乎把握只是没有这种更精细的细节呢。

回答

7

没有括号,函数将被视为有四个参数。尽管如此,我想不出一个反括省略括号会导致含糊不清的反例。

如果你愿意,你可以重新定义你的类型如下:

data Name = NameConstr { getName :: String } 
data Age = AgeConstr { getAge :: Integer } 

让你的函数可以成为:

doStuff n a = "Nom: " ++ getName n ++ ", age: " ++ show (getAge a) 

(固定的最后一部分; aInteger,不能连接到一个字符串)

4

事实上,可以根据(甚至是嵌套的)模式解析简单的语法,而不需要parens。假设这样一个:

<PAT> ::= <WILDCARD> | <VAR> | <CON0> | <CON1> <PAT> | <CON2> <PAT> <PAT> ... 
<VAR> ::= <LNAME> 
<CON*> ::= <UNAME> 
<WILD> ::= "_" 

其中LNAME是用小写字母和UNAME启动名称以大写字母开头。在解析时,我们应该查看构造函数的名称,以便我们可以找出其构造。然后我们可以使用arity信息解析构造函数字段。但是这种查找可能会使解析本身复杂化并减慢速度。 Haskell具有更复杂的模式(视图模式,“模式,记录,具有任意固定的中缀构造函数,e.t.c.)并省略了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可以防止我们发生意外的行为。

+1

再加上它很难阅读没有parens,恕我直言 –

1

这是略带傻气,但在这种情况下,实际上有一种方法来避免括号:

doStuff :: Name -> Age -> String 
NameConstr a `doStuff` AgeConstr b = "Nom: " ++ a ++ ", age: " ++ b 

这正是你定义一个管道符同样的方式,并使用反引号来缀IFY非运营商标识符在将其定义为应用时也同样适用。

我不推荐实际做到这一点,但你不希望在反向插入式中使用函数。