Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 函数语言如何表示内存中的代数数据类型?_Haskell_Memory_Functional Programming_Sml_Algebraic Data Types - Fatal编程技术网

Haskell 函数语言如何表示内存中的代数数据类型?

Haskell 函数语言如何表示内存中的代数数据类型?,haskell,memory,functional-programming,sml,algebraic-data-types,Haskell,Memory,Functional Programming,Sml,Algebraic Data Types,如果您正在用Haskell编写生物信息学算法,您可能会使用代数数据类型来表示核苷酸: data Nucleotide = A | T | C | G 我想,在标准ML或OCaml中也会这样做(我从未真正使用过) 核苷酸类型的值可以清楚地包含在两位中。但是,这样做会导致访问时间比使用每个核苷酸值一个字节慢,因为需要使用二进制运算符来选择感兴趣的两位 因此,在决定如何表示代数数据类型时,编译器必须在内存效率和计算效率之间进行权衡。此外,内存中代数数据类型的表示因值大小可变而变得更加复杂: data

如果您正在用Haskell编写生物信息学算法,您可能会使用代数数据类型来表示核苷酸:

data Nucleotide = A | T | C | G
我想,在标准ML或OCaml中也会这样做(我从未真正使用过)

核苷酸类型的值可以清楚地包含在两位中。但是,这样做会导致访问时间比使用每个
核苷酸
值一个字节慢,因为需要使用二进制运算符来选择感兴趣的两位

因此,在决定如何表示代数数据类型时,编译器必须在内存效率和计算效率之间进行权衡。此外,内存中代数数据类型的表示因值大小可变而变得更加复杂:

data Maybe a = Just a | Nothing
显然,一个
可能是一个
形式的值,仅仅是一个
在逻辑上大于一个
形式的值。在这样一个极端的例子中:

data Hulk a b c d e = Big a b c d e | Little
您肯定不希望必须存储
值空指针或
值中包含的五个值的零值。我假设您只使用大小可变的堆分配内存,在开始时使用构造函数ID(例如,
0
表示
Big
,而
1
表示
Little
)。但是,如果您想在堆栈上存储<代码> Hulk <代码>值(一种更快的表示),您必须将空白内存与<代码>小值一起存储,以便类型<代码> Hulk < /C> >的所有值都是相同的大小。另一个权衡

Simon Marlow在一份报告中回答了我关于GHC的一般性问题。然而,我有三个相关问题尚未回答:

  • 标准ML(SML/NJ和MLton)和OCaml是否使用相同的技术
  • 如果是这样的话,这些语言(或它们的兄弟)的编译器有没有用其他技术进行实验
  • 在这些语言中,是否有一种相当简单的方法(理想情况下是pragma或option标志)来使用更高效的内存表示法,比如
    核苷酸的两位表示法
    ?这种记忆效率对于许多生物信息学应用是必要的;如果每个
    核苷酸都必须是一个字节,那么高性能的生物信息学算法将不得不求助于手动位篡改

    • 没有单一的答案:数据类型是抽象结构,可以由实现者自行决定以多种方式实现。在实践中,诸如单独编译之类的考虑往往会在某种程度上限制事情

      对于将仅包含空构造函数的数据类型打包为尽可能少的位的特定情况,可以通过定义从数据类型到小整数再到小整数的函数来继续。由抽象类型隐藏的整数类型(或在Haskell中,
      newtype
      )也是一个合理的选择。将小整数打包并解包成您正在使用的任何聚合形式将是您的工作


      顺便说一句,现实世界中的OCaml对OCaml值的表示有很大的影响(粗略总结:就这个问题而言,与GHC没有太大的区别)。

      对于haskell,您可以使用GHC like或
      -ddump siml
      选项查看它在较低级别的存储方式。基本上,对于您的简单示例,每个标记似乎都表示为一个
      long
      ,但其中有一些元数据,我也不确定它在做什么。基本要点是,每个构造函数都被转换成一个闭包,然后将它们组合起来形成数据类型的闭包。关于GHC,你肯定不会得到比Simon Marlow在链接问题中更明确的答案(或答案)。由于这是事实上的标准Haskell实现,也许您应该将您的问题特定于另一种语言——或者我们可以将此问题作为该语言的副本关闭。你觉得怎么样?@DanielWagner:我想我现在的问题并没有完全回答这个问题,因为我也问了SML和OCaml。我将改写它来询问一般技术和内存效率实现。数据表示不太可能是你可以轻易概括的东西,因为高级函数语言的规范为实现留下了很大的变化空间。有人可以肯定地谈论OCaml,但SML有多种实现。然而,我的猜测是,这些语言中没有一种会自动为您提供所需的紧凑表示,只需一个pragma或标志,因为由于参数多态性,它们倾向于堆分配和统一表示。@LeviPearson:这一点很好。我指定了我想使用的SML编译器:SML/NJ和MLton。我不知道还有其他常用的。当您停留在公共子集中时,OCaml值没有太大的不同,但不在公共子集中的所谓“多态变体”本身值得注意。事实上,还有对象。我认为这些结构与老年退休金计划的问题没有多大关系,因此我将改写,以表明这一主题还有更多内容。