Reputation: 414
I cannot understand why, although I have declared the data types, the function does not accept the different return. I also tried to create a "Result" type but it was not enough to solve the problem.
Take a look at my code:
type Set a = [a]
type Bag a = [(a, Int)]
type Seq a = [a]
data ComposedType a = Set a | Bag [a] | Seq a deriving(Eq, Show)
data ComposedResult a = Res1 [a] | Res2 [(a, Int)]
-- This function get a list [a] and returns a list of tuples [(a, Int)]
occrs :: (Ord a) => [a] -> [(a, Int)]
occrs [] = []
occrs xs = toList (fromListWith (+) [(x, 1) | x <- xs])
--getElements :: ComposedType a -> ComposedResult a
getElements (Set a) = (Set (nub a))
getElements (Seq a) = (Seq (sort a))
getElements (Bag a) = (Bag (occrs a))
The error:
- Couldn't match type ([a], Int) with '[a]' Expected type: ComposedType [a] Actual type: ComposedType ([a], Int)
- In the expression: (Bag (occrs a)) In an equation for 'getElements': getElements (Bag a) = (Bag (occrs a))
Upvotes: 1
Views: 260
Reputation: 477686
The reason this does not work is because Set (num a)
for example has type ComposedType [a]
, whereas for the Bag (occrs)
, it will require ComposedTYpe (a, Int)
, since the Bag
uses, in contrast to the other data constructors a list of a
s: [a]
.
If you make use of a ComposedResult
, then you will need to use the Res1
and Res2
data constructors:
getElements :: (Eq a, Ord a) => ComposedType [a] -> ComposedResult a
getElements (Set b) = Res1 (nub b)
getElements (Seq b) = Res1 (sort b)
getElements (Bag b) = Res2 (occrs b)
but this will still not work. Indeed Bag a
has a parameter b
, but that b
has as type [[a]]
, and although occrs
can work with a list of lists (since these are also an instance of Ord
if the element is an instance of ord
, this would mean that occrs b
has type [([a], Int)]
whereas the others (nub b
and sort b
), have type [a]
, so that would again raise trouble.
We can fix this by concatenating for example the elements of b
together:
getElements :: (Eq a, Ord a) => ComposedType [a] -> ComposedResult a
getElements (Set b) = Res1 (nub b)
getElements (Seq b) = Res1 (sort b)
getElements (Bag bs) = Res2 (occrs (concat bs))
but likely you made a mistake by specifying [a]
as parameter for bag, you thus can fix the type and use:
data ComposedType a = Set a | Bag a | Seq a deriving (Eq, Show)
getElements :: (Eq a, Ord a) => ComposedType [a] -> ComposedResult a
getElements (Set b) = Res1 (nub b)
getElements (Seq b) = Res1 (sort b)
getElements (Bag b) = Res2 (occrs b)
Upvotes: 1