2
votes

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))
1
Note that set uses a, so that means that the first line needs a ComposeType [a], not a ComposeType a., the same with seq. But now the Bag needs b ~ (a, Int), hence the error.Willem Van Onsem
You use Set both as a type alias and as a constructor name. These two uses are unrelated: the type definition data ComposedType a = Set a | Bag [a] | Seq a does not use the type Set a at all. Ditto for Bag and Seq. This is probably not what you wanted.chi
Do you believe the Set in type Set a = [a] and the Set in data ComposedType a = Set a | ... are related to each other? If so, that may be the core part of your confusion -- they are the same name, but in two distinct namespaces (the type namespace for the former and the computation namespace for the latter) -- and it might be worth adding an answer that discusses this.Daniel Wagner

1 Answers

1
votes

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 as: [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)