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.
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.
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.