我使用符号的两种语言是Ruby和Erlang,我总是发现它们非常有用。
Haskell确实有代数数据类型,但我仍然认为符号会非常方便。我想到的一个直接用途是,由于符号与整数同构,因此您可以在使用积分或字符串“主键”的地方使用它们。
原子的语法糖可能很小 - :某事或某事>是一个原子。所有原子都是名为Atom的Type的实例,它派生Show和Eq。然后,您可以将其用于更具描述性的错误代码,例如
type ErrorCode = Atom
type Message = String
data Error = Error ErrorCode Message
loginError = Error :redirect "Please login first"
在这种情况下:重定向比使用字符串(“重定向”)更有效,并且比整数(404)更容易理解。
好处似乎很小,但我说值得添加原子作为语言特征(或至少是GHC扩展)。
那么为什么没有将符号添加到语言中呢?或者我是否以错误的方式思考这个问题?
答案 0 :(得分:17)
我同意camccann的答案,它可能缺失主要是因为它必须在实施中深入研究,并且它对于这种复杂程度的使用太少。在Erlang(和Prolog和Lisp)中,符号(或原子)通常用作特殊标记,并且与构造函数大致相同。在Lisp中,动态环境包括编译器,因此它部分也是一个(有用的)编译器概念泄漏到运行时。
问题如下,符号实习是不纯的(它修改了符号表)。但是,因为我们永远不会修改现有对象,所以它在引用上是透明的,但是如果实现天真可能会导致运行时空间泄漏。实际上,正如目前在Erlang中实现的那样,你实际上可以通过实现太多的符号/原子来实现崩溃(我认为当前限制是2 ^ 20),因为它们永远不会被垃圾收集。如果没有围绕符号表的巨大锁定,在并发设置中实现也很困难。
然而,这两个问题都可以(并且已经解决)。例如,请参阅Erlang EEP 20。我在simple-atom包中使用了这种技术。它在引擎盖下使用unsafePerformIO
,但仅限于(希望)极少数情况。它仍然可以使用GC的一些帮助来执行类似于间接缩短的优化。它在内部也使用了很多IORef
,这对于性能和内存使用来说并不是很好。
总之,它可以完成,但正确实施它并非易事。编译器编写者总是权衡一个功能的功能与其实现和维护工作的关系,看起来这个符号上的一流符号似乎就失去了。
答案 1 :(得分:14)
我认为最简单的答案是,在Lissk风格的符号(这是Ruby和Erlang都有这个想法的地方,我相信)用于,在Haskell中,大多数是:
已经以其他方式完成 - 例如。带有一堆nullary构造函数的数据类型,它也表现为“方便的整数名称”。
难以适应 - 存在于语言语法层面而不是常规数据的事物通常会有更多与之相关的类型信息,但符号必须是彼此不同的类型(几乎无用)没有某种轻量级ad-hoc sum类型)或所有相同的类型(在这种情况下,它们与仅仅使用字符串几乎没有区别)。
另外,请记住,Haskell本身实际上是一种非常非常小的语言。很少被“烘焙”,其中最多的东西只是其他原语的语法糖。如果你包含一堆GHC扩展,那就不那么真了,但是带有-XAndTheKitchenSinkToo的GHC与Haskell本身的语言不同。
此外,Haskell非常适合伪语法和元编程,因此即使没有内置也可以做很多事情。特别是如果你进入TH和可怕的类型元编程以及其他任何事情。
所以它主要归结为符号的大多数实用功能已经可以从其他功能中获得,并且不可用的东西将比它的价值更难添加。
答案 2 :(得分:8)
该语言不提供原子,但可以合理地实现为库:
http://hackage.haskell.org/package/simple-atom
还有其他一些关于hackage的库,但这个库看起来是最新的并且维护得很好。
答案 3 :(得分:3)
Haskell使用类型构造函数*而不是符号,以便函数可以采用的符号集是关闭的,并且可以由类型系统进行推理。您可以在语言中添加符号,但它会将您放在使用字符串的相同位置 - 您必须在运行时检查所有可能的符号以及具有已知含义的少数符号,并在整个地方添加错误处理等。所有编译时检查都是一个很大的解决方法。
字符串和符号之间的主要区别是 interning - 符号是原子的,可以在恒定时间内进行比较。两者都是具有基本上无限数量的不同值的类型,并且反对Haskell指定参数和有限类型的结果。
None
或Just 3
。答案 4 :(得分:1)
立即使用的是,由于符号与整数同构,因此您可以在使用积分或字符串“主键”的地方使用它们。
改为使用Enum
。
data FileType = GZipped | BZipped | Plain
deriving Enum
descr ft = ["compressed with gzip",
"compressed with bzip2",
"uncompressed"] !! fromEnum ft