Reputation: 30675
I want to include String as part of my constructor:
> data Car = Wheel | Trunk | String deriving (Show)
> test::Car->Car->Car
> test Wheel Wheel = "Wheel"
> test _ _ = ""
it says: Couldn't match Car with [Char]
if I change the constructor to
> data Car = Wheel | Trunk | [Char] deriving (Show)
it says: error in constructor in data/newtype declaration: [Char]
So how do I create a data type where one of the constructors is also a string?
Upvotes: 1
Views: 547
Reputation: 9340
data Car = Wheel | Trunk | String deriving (Show)
here you are declaring Car
with constructors Wheel
, Trunk
and String
. Your String
differs from the standard String type, therefore they're not the same. So you can't simply match that with a String such as ""
. If you want to give it a string value, make the constructor accepts a string, e.g.:
data Car = Wheel | Trunk | CarName String deriving (Show)
and you can then use it like:
test::Car->Car->Car
test Wheel Wheel = CarName "Wheel"
test _ _ = CarName ""
the result of this function must be matched against the constructors, e.g.:
let x = test Wheel Wheel
in case x of
Wheel -> ... -- do something if it's wheel
Trunk -> ... -- do something if it's trunk
CarName x -> ... -- do something if it's carname, you can use the returned x
Upvotes: 1
Reputation: 3173
Haskell does not provide unnamed unions as you have used in your Car
data type. Each element in the definition of a data type must have a constructor. For example, you could define the following data type.
data Car = Wheel | Trunk | Constr String
In this definition Constr
denotes a constructor and String
is the type of its argument. For example, you can construct a value of type Car
by using Constr "Wheel"
. If you omit the String
in the example above, it is a constructor called Constr
without an argument. Similarly, in your example, String
is a constructor, even if there exists a type with the same name.
With the definition of Car
above, you can define test
as follows.
test :: Car -> Car -> Car
test Wheel Wheel = Constr "Wheel"
test _ _ = Constr ""
By adding the constructor String
on the right hand side of the definitions, the string is lifted into the Car
data type. However, as mentioned in the comments, a definition like this seems a little odd as test
always yields a value of type String
. Therefore, another possible definition would be the following.
test :: Car -> Car -> String
test Wheel Wheel = "Wheel"
test _ _ = ""
Upvotes: 7