Type of `grouping teamNumber`
Look carefully at the type of grouping :: Int -> [Student]->[(Team, Student)]
, and the arguments that are being declared for its declaration
grouping :: Int -> [Student]->[(Team, Student)]
grouping teamNumber = ...
What is the return type (the type on the right-hand side of the equals sign) if grouping
is provided with all the arguments listed on the left-hand side of the equals sign?
Answer
The type on the right-hand side of the equals sign is [Student]->[(Team, Student)]
. In Haskell, a function that takes two arguments and returns a result can be equivalently seen or defined as a function that takes the first argument and returns a (function that takes the second argument and returns the result). So we could say, for example, that the expression
grouping 3 :: [Student]->[(Team, Student)]
(grouping 3)
is a function that takes a list of students and returns a list of those students, labeled in 3 groups. Presumably, if (grouping 3)
were applied to the list of students from your example, we would have
(grouping 3) [ 'Mark' , 'Hanna' , 'Robert' , 'Mike' , 'Jimmy' ] =
[(1,'Mark'),(2,'Hanna'),(3,'Robert'),(1,'Mike'),(2,'Jimmy')]
Type of `zip ys`
What does currying have to do with the following type and expression?
zip :: [a] -> [b] -> [(a, b)]
zip ys
What would the type of zip ys
be if, for example, ys :: [Bool]
?
What does this have to do with your question?
When you consider this together with the type of grouping teamNumber
, how does this tell you what the type of ys
needs to be in your exercise?
Putting it all together
From the exercise code (ignoring the types and the where
clause) we have:
grouping teamNumber = zip ys
Two things can only be =
in Haskell if their types will unify. In this case, the type of grouping teamNumber
must unify with the type of zip ys
.
From the first part, we know that the type of grouping teamNumber
is [Student]->[(Team,Student)]
.
From the second part, we know that zip ys
has the type [b] -> [(a, b)]
, where a
is a type such that ys
has the type [a]
.
Therefore, we know that (~
is type equality in Haskell)
[Student]->[(Team,Student)] ~ [b] -> [(a, b)]
These will unify if we substitute the following for the type variables b
and a
b ~ Student
a ~ Team
Now, we know the type of ys
is [a]
, which, if we make the same substitution, is [Team]
.
Therefore, the types will be correct if ys :: [Team]
.
Conclusion
If you can provide a ys :: [Team]
, you can produce a function from students to students tagged with their team ([Student]->[(Team,Student)]
) by passing the ys
as the first argument to zip
. Such a function is exactly what grouping
needs to return when it has been applied to the single argument, teamNumber :: Int
.