How do I define a data type consisting of other da

2020-03-27 11:37发布

问题:

I want to define the data type Currency, which consists of three other data types. I have the problem that Haskell doesn't recognize the data types as a part of currency, which breaks everything.

My idea was to define the different currencies as their own data types and then add them to the Currency type, which I tried with:

data Euro = MkEuro Integer Integer
data Dollar = MkDollar Integer Integer
data Yen = MkYen Integer
data Currency = Euro | Dollar | Yen

If I want to use the type Currency in any function I get a variation of the following error message:

Couldn't match expected type `Currency' with actual type `Dollar'

Sadly I have to use the type Currency and can't create different functions for all three currencies.

回答1:

Currently your Currency is constructed as three values, that take no parameters. So Euro is a value, Dollar is a value, and Yen is a value, but not MkYen 15.

You can add parameters to your data constructors like:

data Currency = Euro Euro | Dollar Dollar | Yen Yen

Then you thus can construct a Currency with:

Euro (MkEuro 14 25) :: Currency

The :: Currency is not necessary. The MkEuro will thus construct an object of the Euro type, and then we use the Euro data constructor with type Euro -> Currency to construct a Currency.

Sadly I have to use the type Currency and can't create different functions for all three currencies.

You might want to make a Currency typeclass however, that provides an interface that says what functions a currency should implement, and then make Euro, Dollar, and Yen instances of that typeclass.



回答2:

The issue with what you attempted is that the Euro, Dollar and Yen defined on the first 3 lines (on the left-hand-side of the = signs) are types, whereas those in the last line, on the right-hand-side, are data constructors. These are different things, which is why you're allowed to give them the same names - but also means that the value Dollar has the type Currency, not the type Dollar.

You had the right idea to create a union type combining the other three - but you are confusing the data constructors (which are just "tags") with the types of the values they hold. You can fix it like this:

data Currency = Euro Euro | Dollar Dollar | Yen Yen

That might look confusing to have the same name twice (three times, too) - but the two occurrences of the name have different meanings. In Euro Euro, for example, the first Euro is a data constructor (a function which "tags" the value), while the second is the type on which the constructor function operates.