我已经声明了一个具有以下结构的递归数据类型:
data Path = GET | POST | Slash Path String
我真的想将最后一个值构造函数重命名为/
,这样我就可以在GET /"controller"/"action"
之类的可爱表达式中添加它。但是,如果我尝试这样做:
import Prelude hiding ((/))
infixr 5 /
data Path = GET | POST | Path / String
...然后我明白了:
Path.hs:4:30: parse error on input `/'
如果我将/
替换为:/
或以:
开头的任何其他特殊字符序列,那么相同的三行编译就可以了。
那么,有什么方法可以命名我的值构造函数/
吗?我知道我可以将其命名为Slash
,然后声明一个单独的函数:
(/) :: Path -> String -> Path
(/) = Slash
...但这不会让我模式匹配,如:
request :: Path -> String
request path = case path of GET /"hello" -> "Hello!"
GET /"goodbye" -> "Goodbye!"
答案 0 :(得分:12)
简短回答:不。
长答案:类型类,类型名称和数据构造函数必须以大写字母或冒号开头(其中一些需要使用语言扩展名)。其他所有内容必须以小写字母或任何其他允许的符号开头。
请注意,类型变量(通常为小写标识符)遵循相同的规则,不以冒号开头。
另请参阅the GHC user's guide以启用类型运算符。我认为,数据构造函数总是被允许的。
就个人而言,我个人只使用(:/)
。它看起来并不那么糟糕,过了一段时间,你习惯于忽略冒号。有些人也喜欢尾随冒号,特别是如果数据在某种意义上是“对称的”。
答案 1 :(得分:6)
不,你不能这样做。在纯Haskell 98中,用户定义的类型名称和构造函数必须是字母数字,并以大写字母开头;这是in section 4.1.2 of the Haskell 98 Report。在GHC中,正如具有字母数字名称的用户定义构造函数必须以大写字母开头一样,作为运算符的用户定义构造函数必须以:
。 1 开头(对于用户定义的类型名称。)section 7.4.2 of the GHC manual中记录了这一点。我可能会使用:/
,我自己,有或没有/
作为同义词。
1:“用户定义”资格认定的原因是存在一些内置例外:->
,[]
,()
,以及元组类型(,)
,(,,)
等作为类型名称;和()
以及元组类型构造函数(,)
,(,,)
等作为类型构造函数
答案 2 :(得分:2)
我认为所有构造函数运算符都需要以冒号开头(但我可能错了)。
所以你可以这样做:
data Path = GET | POST | Path :/ String