Reputation: 159
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)]
Upvotes: 2
Views: 757
Reputation: 48631
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
.
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.
Upvotes: 1
Reputation: 78
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
Upvotes: 1
Reputation: 39400
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).
Upvotes: 9