简体   繁体   English

了解Haskell中的数据结构

[英]understanding data structure in Haskell

I have a problem with a homework (the topic is : "functional data structures"). 我的作业有问题(主题是:“功能数据结构”)。 Please understand that I don't want anyone to solve my homework. 请理解我不希望任何人解决我的作业。 I just have a problem with understanding the structure of this : 我只是理解这个结构的问题:

data Heap e t = Heap {
 empty :: t e,
 insert :: e -> t e -> t e,
 findMin :: t e -> Maybe e,
 deleteMin :: t e -> Maybe (t e),
 merge :: t e -> t e -> t e,
 contains :: e -> t e -> Maybe Int
}

In my understanding "empty" "insert" and so on are functions which can applied to "Heap"-type data. 在我的理解中,“空”“插入”等是可以应用于“堆”类型数据的函数。 Now I just want to understand how that "Heap"thing looks like. 现在我只想了解“Heap”的样子。 So I was typing things like : 所以我输入的内容如下:

  a = Heap 42 42

But I get errors I can't really work with. 但我得到的错误我无法真正使用。

Maybe it is a dumb question and I'm just stuck at this point for no reason, but it is killing me at the moment. 也许这是一个愚蠢的问题,我只是无缘无故地停留在这一点上,但此刻它正在杀死我。 Thankful to any help 感谢任何帮助

If you truly wish to understand that type, you need to understand a few requisites first. 如果您真的希望了解该类型,则需要首先了解一些必要条件。

types and values (and functions) 类型和值(和函数)

Firstly, you need to understand what types and values are. 首先,您需要了解哪些类型和值。 I'm going to assume you understand this. 我假设你明白这一点。 You understand, for example, the separation between "hello" as a value and its type, String and you understand clearly what it means when I say a = "hello" :: String and: 例如,你理解"hello"作为一个值与它的类型之间的分离, String和你清楚地理解当我说a = "hello" :: String时它意味着什么:

a :: String
a = "hello"

If you don't understand that, then you need to research values and types in Haskell. 如果您不理解,那么您需要研究Haskell中的值和类型。 There are a myriad of books that can help here, such as this one, which I helped to author: http://happylearnhaskelltutorial.com 这里有无数的书可以提供帮助,例如我帮助创作的这本书: http//happylearnhaskelltutorial.com

I'm also going to assume you understand what functions and currying are, and how to use both of them. 我也会假设您了解功能currying是什么,以及如何使用它们。

polymorphic types 多态类型

Secondly, as your example contains type variables, you'll need to understand what they are. 其次,由于您的示例包含类型变量,您需要了解它们是什么。 That is, you need to understand what polymoprhic types are. 也就是说,您需要了解多态类型是什么。 So, for example, Maybe a , or Either ab , and you'll need to understand how Maybe String is different to Maybe Int and what Num a => [a] and even things like what Num a => [Maybe a] is. 所以,例如, Maybe a或者Either ab ,你需要理解Maybe StringMaybe Int不同之处以及Num a => [a]甚至是什么,比如Num a => [Maybe a]是。

Again, there are many free or paid books that can help, the example above covers this, too. 同样,有许多免费或付费书籍可以提供帮助,上面的例子也涵盖了这一点。

algebraic data types 代数数据类型

Next up is algebraic data types. 接下来是代数数据类型。 This is a pretty amazingly cool feature that Haskell has. 这是Haskell的一个非常酷的功能。 Haskell-like languages such as Elm and Idris have it as well as others like Rust, too. 类似Haskell的语言,比如Elm和Idris,以及像Rust这样的其他语言。 It lets you define your own data types. 它允许您定义自己的数据类型。 These aren't just things like Structs in other languages, and yeah, they can even contain functions. 这些不仅仅是像其他语言中的Structs这样的东西,是的,它们甚至可以包含函数。

Maybe is actually an example of an algebraic data types. Maybe实际上是代数数据类型的一个例子。 If you understand these, you'll know that: 如果您了解这些,您就会知道:

data Direction = North | South | East | West

defines a data type called Direction whose values can only be one of North , South , East or West , and you'll know that you can also use the polymorhpic type variables above to parameterise your types like so: 定义一个名为Direction的数据类型,其值只能是NorthSouthEastWest ,并且您将知道您还可以使用上面的polymorhpic类型变量来参数化您的类型,如下所示:

data Tree a = EmptyNode | Node (Tree a) (Tree a)

which uses both optionality (as in the sum type of Direction above) as well as parameterization. 它使用两个选项(如上面的Direction 类型 )以及参数化。

In addition to this, you can also have multiple types in each value. 除此之外,您还可以在每个值中包含多种类型 These are called product types , and Haskell's algebraic datatypes can be expressed as a combination of Sum types that can contain Product types. 这些被称为产品类型 ,Haskell的代数数据类型可以表示为可以包含产品类型的Sum类型的组合。 For example: 例如:

type Location = (Float, Float)
data ShapeNode = StringNode Location String | CircleNode Location Float | SquareNode Location Float Float

That is, each value can be one of StringNode , CircleNode or SquareNode , and in each case there are a different set of fields given to each value. 也就是说,每个值可以是StringNodeCircleNodeSquareNode ,并且在每种情况下,给每个值赋予不同的字段集。 To create a StringNode , for example, you'd need to pass the values of it constructor like this: StringNode (10.0, 5.3) "A String" . 例如,要创建StringNode ,您需要传递构造函数的值,如下所示: StringNode (10.0, 5.3) "A String"

Again, the freely available books will go into much more detail about these things, but we're moving in the direction of getting more than a basic understanding of Haskell now. 同样,免费提供的书籍将更详细地介绍这些内容,但我们现在正朝着不仅仅是对Haskell的基本理解的方向前进。

Finally, in order to fully understand your example, you'll need to know about... 最后,为了充分理解您的示例,您需要了解...

record types 记录类型

Record types are the same as product types above, except that the fields are labelled rather than being anonymous. 记录类型与上面的产品类型相同,只是字段是标记的而不是匿名的。 So, you could define the shape node data type like this, instead: 因此,您可以像这样定义形状节点数据类型,而不是:

type Location = (Float, Float)

data ShapeNode
  = StringNode { stringLocation :: Location, stringData :: String }
  | CircleNode { circleLocation :: Location, radius :: Float }
  | SquareNode { squareLocation :: Location, length :: Float, height :: Float }

Each field is named, and you can't repeat the same name inside data values. 每个字段都被命名,您不能在数据值中重复相同的名称。

All that you need in addition to this to understand the above example is to realise your example contains all of these things together, along with the fact that you have functions as your record field values in the data type you have. 除此之外,您需要的所有内容都是为了理解上面的示例,即实现您的示例包含所有这些内容,以及您在所拥有的数据类型中具有作为记录字段值的函数的事实。

It's a good idea to thoroughly flesh out your understanding and not skip any steps, then you'll be able to follow these kinds of things much more easily in the future. 彻底充实你的理解而不是跳过任何步骤是一个好主意,那么你将来可以更容易地遵循这些事情。 :) I wish you luck! :) 祝你好运!

Heap is a record with six elements. Heap是六个元素的记录。 In order to create a value of that type, you must supply all six elements. 要创建该类型的值,您必须提供所有六个元素。 Assuming that you have appropriate values and functions, you can create a value like this: 假设您有适当的值和函数,您可以创建如下值:

myHeap = Heap myEmpty myInsert myFindMin myDeleteMin myMerge myContains

The doesn't seem like idiomatic Haskell design, however. 然而,这似乎不是惯用的Haskell设计。 Why not define generic functions independent of the data, or, if they must be bundled together, a typeclass? 为什么不定义与数据无关的泛型函数,或者,如果必须将它们捆绑在一起,则为类型类?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM