user997112
user997112

Reputation: 30675

Cannot include String in my data constructor?

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

Answers (2)

LeleDumbo
LeleDumbo

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

Jan Christiansen
Jan Christiansen

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

Related Questions