我可以有一个名为"/"的值构造函数吗?

Tom*_*Tom 6 syntax haskell

我已经声明了一个具有以下结构的递归数据类型:

data Path = GET | POST | Slash Path String
Run Code Online (Sandbox Code Playgroud)

我真的想重命名最后一个值构造函数,/以便我可以在可爱的表达式中添加它GET /"controller"/"action".但是,如果我尝试这样做:

import Prelude hiding ((/))
infixr 5 /
data Path = GET | POST | Path / String
Run Code Online (Sandbox Code Playgroud)

...然后我明白了:

Path.hs:4:30: parse error on input `/'
Run Code Online (Sandbox Code Playgroud)

如果我取代那些相同的三条线编译就好/:/或其他特殊字符序列开头:.

那么,有什么方法可以命名我的值构造函数/吗?我知道我可以命名它Slash然后声明一个单独的函数:

(/) :: Path -> String -> Path 
(/) = Slash
Run Code Online (Sandbox Code Playgroud)

......但这不会让我模式匹配,如:

request :: Path -> String
request path = case path of GET /"hello" -> "Hello!"
                            GET /"goodbye" -> "Goodbye!"
Run Code Online (Sandbox Code Playgroud)

C. *_*ann 12

简答:不.

答案很长:类型类,类型名称和数据构造函数必须以大写字母或冒号开头(其中一些需要使用语言扩展名).其他所有内容必须以小写字母或任何其他允许的符号开头.

请注意,类型变量(通常是小写标识符)遵循相同的规则,不以冒号开头.

另请参阅GHC用户指南以启用类型操作符.我想,总是允许数据构造函数.

就个人而言,在我的情况下,我只是使用(:/).它看起来并不那么糟糕,过了一段时间,你习惯于忽略冒号.有些人也喜欢尾随冒号,特别是如果数据在某种意义上是"对称的".

  • 在我的代码中看到`:/`会让我想知道为什么它如此失望. (18认同)
  • 此外,关于Haskell的一个好处是,你永远不必*为什么你的代码对你感到失望,GHC会告诉你所有关于它的事情. (6认同)

Ant*_*sky 6

不,你不能这样做.在纯Haskell 98中,用户定义的类型名称和构造函数必须是字母数字,并以大写字母开头; 这是在Haskell 98报告的4.1.2节中.在GHC中,正如具有字母数字名称的用户定义构造函数必须以大写字母开头一样,作为运算符的用户定义构造函数必须以a开头:.1 (对于用户定义的类型名称也是如此.)这在GHC手册的第7.4.2节中有记录.我可能会使用:/或不/使用同义词.


1:的原因"用户定义的"限定的是,有一些内置的例外:->,[],(),和的元组类型(,),(,,)等,如类型名; 和()与所述元组类型构造(,),(,,)等,如类型构造