Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/351.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
Java 我需要了解Haskell如何表示数据才能编写好的Haskell程序吗?_Java_Data Structures_Compiler Construction_Haskell_Heap Memory - Fatal编程技术网

Java 我需要了解Haskell如何表示数据才能编写好的Haskell程序吗?

Java 我需要了解Haskell如何表示数据才能编写好的Haskell程序吗?,java,data-structures,compiler-construction,haskell,heap-memory,Java,Data Structures,Compiler Construction,Haskell,Heap Memory,我在Java背景下学习Haskell。当我编写Java程序时,我感觉自己对对象在内存中的布局及其后果有了深刻的理解。例如,我确切地知道java.lang.String和java.util.LinkedList是如何工作的,因此我知道应该如何使用它们。和哈斯克尔在一起,我有点迷路了。例如,(:)是如何工作的?我应该在乎吗?是否在某个地方指定了它?简短的答案是否定的。在Haskell中编程时,您应该将数据结构视为纯数学对象,而不必担心它们在内存中的表示方式。这样做的原因是,在没有副作用的情况下,除了

我在Java背景下学习Haskell。当我编写Java程序时,我感觉自己对对象在内存中的布局及其后果有了深刻的理解。例如,我确切地知道
java.lang.String
java.util.LinkedList
是如何工作的,因此我知道应该如何使用它们。和哈斯克尔在一起,我有点迷路了。例如,
(:)
是如何工作的?我应该在乎吗?是否在某个地方指定了它?

简短的答案是否定的。在Haskell中编程时,您应该将数据结构视为纯数学对象,而不必担心它们在内存中的表示方式。这样做的原因是,在没有副作用的情况下,除了创建数据的函数和可以用来提取构建数据的更简单部分的函数之外,数据实际上什么都没有

要查看有关数据构造函数(如
(:)
)或任何其他术语)的信息,请使用GHCi中的
:type
(或简称
:t
)命令:

:Prelude> :type (:)
(:) :: a -> [a] -> [a]
这说明
(:)
构造函数(发音为“cons”)接受任何类型的值和相同类型的列表,并返回相同类型的列表。您还可以使用
:info
命令获取更多信息。这将向您显示数据定义的外观:

Prelude> :info (:)
data [] a = ... | a : [a]   -- Defined in GHC.Types
infixr 5 :
这告诉您,
(:)
是将元素前置到现有列表的构造函数

我还强烈建议不仅要按名称查找,而且要进行反向搜索;你知道你正在寻找的函数的签名,并且想知道是否有人已经为你编写了它。Hoogle很好,因为它提供了描述和示例用法

归纳数据的形状 我在上面说过,知道数据在内存中的表示并不重要。。。但是,您应该了解正在处理的数据的形状,以避免糟糕的性能决策。Haskell中的所有数据都是归纳定义的,这意味着它有一个递归向外展开的树状形状。您可以通过查看数据的定义来判断数据的形状;一旦您知道如何阅读以下内容,它的性能特征就不会隐藏任何东西:

data MyList a = Nil | Cons a (MyList a)
从定义中可以看出,获得新的
MyList
的唯一方法是使用
Cons
构造函数。如果多次使用此构造函数,最终将得到大致如下形状的结果:

(Cons a5 (Cons a4 (Cons a3 (Cons a2 (Cons a1 Nil)))))
它只是一棵没有分支的树,这就是列表的定义!获得
a1
的唯一方法是依次弹出每个
Cons
s;因此,对最后一个元素的访问是O(n),而对头部的访问是恒定时间。一旦你能根据数据结构的定义对其进行这种推理,你就万事大吉了。

简单的回答是“不”,你不需要了解数据布局——尽管了解复杂性会很有用

然而,要编写高度优化的Haskell程序,必须具备堆中数据结构形状的良好工作知识。帮助实现这一点的工具是,它可以在Haskell数据结构布局时呈现它们的图表

一些例子:

$ view "hello"


下面是一个关于如何使用该工具的简短视频:

这是一个好问题,因为我看到有人在值的前面加了一个前缀!出于这个原因。一般来说,您也不需要了解Java类的内部结构(解耦、信息隐藏、封装…。@musiKk我同意您不需要阅读源代码,但我确实认为从广义上来说,了解一些东西是如何实现的会有所帮助。例如,LinkedList和ArrayList之间的区别很容易理解,因为名称强烈地暗示了实现,我不必查阅文档来发现方法是O(1)还是O(n)或其他。如果你只是给我一个列表,我不知道在没有阅读文档的情况下操作将如何执行。Haskell中的所有数据都定义为向外展开的树。。。因此,对于如何实现一个简单列表,有一个明显的选择:单链接列表。如果你在各种各样的单子中工作,你可以使用可变数组,但这是一个相当高级的主题。每个Haskell程序员都应该知道并使用它。这是一个很好的工具。可能还值得指出的是,一个只在一个地方使用的值(例如列表)通常(?总是?)实际上并不存在——生产函数和消费函数融合在一起,列表表示被跳过。描述得太棒了。
$ view (IntMap.fromList $ zip [1..10] [1..])