简体   繁体   English

在 Haskell 中使用自定义数据类型

[英]using custom data types in haskell

I made these custom data types:我制作了这些自定义数据类型:

data BakedGoods = Muffin
                | Croissant
                | Cookie
                deriving (Eq, Show)

data Muffin = Blueberry
            | SaltedCaramel
            | Cheesecake

then I tried to use them in a function that returns the price of the BakedGoods:然后我尝试在返回 BakedGoods 价格的函数中使用它们:

price :: BakedGoods -> Int
price a 
  | a == Blueberry = 2

[...]

and I keep getting this error:我不断收到此错误:

 Couldn't match expected type ‘BakedGoods’ with actual type ‘Muffin’

I get the point but unfortunately I have no idea how to fix it, do you have any ideas?我明白了,但不幸的是我不知道如何解决它,你有什么想法吗? :) :)

This is a bit confusing for beginners.这对初学者来说有点混乱。

An algebraic datatype is of the form: data typename = constructor1 |代数数据类型的形式如下: data typename = constructor1 | constructor2 etc.构造函数2

A type can have the same name as a constructor, even of a different type.类型可以与构造函数同名,即使是不同的类型。 So your code has two different Muffin s - a type called Muffin (with constructors Blueberry , SaltedCaramel and Cheescake ), and a constructor Muffin for the type BakedGoods .所以你的代码有两个不同的Muffin s - 一个叫做Muffin类型(带有构造函数BlueberrySaltedCaramelCheescake ),以及一个用于类型BakedGoods构造函数Muffin As far as the compiler is concerned, they are completely unconnected.就编译器而言,它们是完全没有联系的。

The code you want looks like this:您想要的代码如下所示:

data BakedGoods = Muffin Muffin
    | ...

This means: The type BakedGoods has a constructor called Muffin , which contains one field of type Muffin .这意味着: BakedGoods类型有一个名为Muffin构造函数,其中包含一个Muffin类型的字段

You would then pattern-match it like so:然后你可以像这样模式匹配它:

price :: BakedGoods -> Int
price (Muffin Blueberry) = 2
...

Which means: when the argument (which must be a BakedGoods ) has a top-level constructor matching Muffin , whose field (of type Muffin ) matches Blueberry , then return 2.这意味着:当参数(必须是BakedGoods )具有匹配Muffin的顶级构造函数,其字段(类型Muffin )匹配Blueberry ,则返回 2。

Happy Haskelling!哈斯克林快乐!

If you write如果你写

data BakedGoods = Muffin | …
then this is not a union of the data constructors of the Muffin type with other data constructors. 那么这不是Muffin类型的数据构造函数与其他数据构造函数的联合。 You here simply say that BakedGood s has a data constructor named Muffin , the fact that there is a type named Muffin does not matter. 你在这里只是说BakedGood s 有一个名为Muffin的数据构造函数,事实上有一个名为Muffin的类型并不重要。

You can wrap a Muffin object in the Muffin data constructor, like:您可以在Muffin数据构造函数中包装一个Muffin对象,例如:

data BakedGoods
  = Muffin Muffin  -- ← parameter for the Muffin data type
  | Croissant
  | Cookie
  deriving (Eq, Show)

Then you thus can perform pattern matching on the value wrapped in the Muffin data constructor:然后,您可以对包裹在Muffin数据构造函数中的值执行模式匹配:

price :: BakedGoods -> Int
price (Muffin Blueberry) = 2

When you do当你做

data BakedGoods = Muffin -- ...
data Muffin = Blueberry -- ...

You are not saying that BakedGoods 's data constructors should include all of Muffin 's.并不是BakedGoods的数据构造函数应该包括所有Muffin的数据构造函数。 You are actually saying that you should create a new Muffin data constructor, completely unrelated to the Muffin type, and that Muffin data constructor is a BakedGood .实际上是说您应该创建一个新的Muffin数据构造函数,与Muffin类型完全无关,并且Muffin数据构造函数是BakedGood If you want to merge the two, then declare them merged:如果要合并两者,则声明它们合并:

data BakedGoods = Blueberry
                | SaltedCaramel
                | Cheesecake
                | Croissant
                | Cookie

Then Blueberry would be a BakedGoods .那么Blueberry将成为BakedGoods But, if you want to retain the fact that they are muffins, then you can make a MuffinFlavor type and have your Muffin contain a MuffinFlavor :但是,如果你想保留它们是松饼的事实,那么你可以制作一个MuffinFlavor类型并让你的Muffin包含一个MuffinFlavor

data BakedGoods = Muffin MuffinFlavor
                | Croissant
                | Cookie

data MuffinFlavor = Blueberry | SaltedCaramel | Cheesecake

And now you can create muffins with Muffin Blueberry .现在您可以使用Muffin Blueberry制作松饼。

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

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