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

问题描述 投票:0回答:2

我正在从 Java 背景学习 Haskell。 当我编写 Java 程序时,我觉得我对对象在内存中的布局及其后果有深入的了解。 例如,我确切地知道

java.lang.String
java.util.LinkedList
是如何工作的,因此我知道应该如何使用它们。 对于 Haskell,我有点迷失了。 例如,
(:)
是如何工作的? 我应该关心吗? 有指定的地方吗?

haskell data-structures heap-memory
2个回答
11
投票

简短的回答是否定的。在 Haskell 中编程时,您应该将数据结构视为纯数学对象,而不用担心它们在内存中的表示方式。原因是,在没有副作用的情况下,除了创建数据的函数以及可用于提取构造数据的更简单部分的函数之外,实际上没有任何数据。 要查看有关数据构造函数(如

(:)

)或任何其他术语的信息,请在 GHCi 中使用

:type
(或简称
:t
)命令:
:Prelude> :type (:)
(:) :: a -> [a] -> [a]

这告诉您 
(:)

构造函数(发音为“cons”)接受任何类型的值和相同类型的列表,并返回相同类型的列表。您还可以使用

:info
命令获取更多信息。这将向您展示数据定义的样子:
Prelude> :info (:)
data [] a = ... | a : [a]   -- Defined in GHC.Types
infixr 5 :

这告诉您 
(:)

是将元素添加到现有列表的构造函数。

我还强烈推荐

Hoogle

,不仅可以通过名称查找事物,还可以进行相反的搜索;您知道您正在寻找的函数的签名,并且想要查找是否有人已经为您编写了该函数。 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

;因此,访问最后一个元素的时间为

O(n)
,而访问头部的时间为常数。一旦您可以根据数据结构的定义对数据结构进行此类推理,您就一切就绪了。
    
简短的回答是“不”,您不需要了解数据布局——但了解复杂性会很有用。


2
投票
“vacuum”

,它可以呈现 Haskell 数据结构的布局图。

一些例子: $ view "hello"


$ view (IntMap.fromList $ zip [1..10] [1..])

linked lists


以下是如何使用该工具的简短视频:

http://www.youtube.com/watch?v=X4-212uMgy8Data.IntMap

© www.soinside.com 2019 - 2024. All rights reserved.