2
votes

I'm new to Haskell and I need to define this data type:

data Restaurant = Restaurant [(String, String, Int)] deriving (Eq,Show)

that is a list of the employees of the restaurant: (name , address, wage) for each employee.

Now, I'm trying to define this numberOfEmployees function:

numberOfEmployees :: Restaurant -> Int
numberOfEmployees rest = length rest

But I get this compile error: Couldn't match expected type ‘t2 a0’ with actual type ‘Restaurant'

Why is it working if I use type instead of data? (I can't use the 'type' declaration in my code because it's part of an exercise about 'data')

type Restaurant = [(String, String, Int)]
3
Side note: every time you say "I can't do that", you should state a reason here.Bartek Banachewicz
You are right, sorry. I've just corrected it.Fossa

3 Answers

9
votes

Why is it working if I use type instead of data?

Because type is a weak alias. In code, it is equivalent to the type on RHS.

data (and newtype, perhaps even more so), on the other hand, creates a "strong" alias, which means you need to unpack it first:

numberOfEmployees :: Restaurant -> Int
numberOfEmployees (Restaurant rest) = length rest

This is especially important if you want to restrict the operations on your data. If your inner module doesn't export the constructor, the user can only use your smart constructors and other operators, and is unable to access or modify the wrapped data directly (effectively making it opaque).

1
votes

The function length has type [a] -> Int. That is it expects a list as an argument. But you are trying to pass a Restaurant to it.

You should use pattern matching to get the list and pass that to length instead.

numberOfEmployees :: Restaurant -> Int
numberOfEmployees (Restaurant a) = length a
1
votes

The type of length is

length :: Foldable t => t a -> Int

But there are no types t and a such that the Restaurant type equals t a. As others have explained, you'll need to pull out the list and find the length of the list—a Restaurant can never have a length.

Nitpick

You could write

type Foo a = Restaurant

So that

Foo a ~ Restaurant

for each a. However, Foo will only be a type synonym/family and not a proper first-class type. Only bona fide types declared with data or newtype, the built-in (), list, and tuple types, the oddball ->, and applications of these, really count.