Two questions:
Why does this code fail to compile? I believe (but am not 100% sure, I may have made a mistake) that it's type-correct.
What does the error message mean? I'm confused why the expected argument type is _ -> _
(or maybe I just don't know what it means by _ -> _
in this case). The goal of this question is to learn how to correctly diagnosis this error message, should I run into it again in the future.
The code:
This code fails to compile with the error message "Cannot convert value of type 'A -> B' to expected argument type '_ -> _':
class ZipList<A> {
let xs: [A]
init(xs: [A]) {
self.xs = xs
}
func map<B>(f: A -> B) -> ZipList<B> {
return ZipList(xs: self.xs.map(f))
}
}
Additional information:
At first, I assumed the problem was with type inference, so I tried writing out the types explicitly, but that also failed:
However, this compiles just fine (the only difference from my original map
version is the <B>
passed to the ZipList
initializer):
func map4<B>(f: A -> B) -> ZipList<B> {
return ZipList<B>(xs: self.xs.map(f))
}
Type 1 error, in statistical hypothesis testing, is the error caused by rejecting a null hypothesis when it is true. Type 1 error is caused when the hypothesis that should have been accepted is rejected. Type I error is denoted by α (alpha) known as an error, also called the level of significance of the test.
A type I error (false-positive) occurs if an investigator rejects a null hypothesis that is actually true in the population; a type II error (false-negative) occurs if the investigator fails to reject a null hypothesis that is actually false in the population.
Type II error is mainly caused by the statistical power of a test being low. A Type II error will occur if the statistical test is not powerful enough. The size of the sample can also lead to a Type I error because the outcome of the test will be affected.
Type I error (false positive): the test result says you have coronavirus, but you actually don't. Type II error (false negative): the test result says you don't have coronavirus, but you actually do.
The problem is that when you don't explicitly supply the generic parameter type of ZipList
when you refer to it, the compiler will try and infer it for you – which it doesn't always get correct.
As you're already inside a ZipList<A>
class, the compiler will try and infer ZipList
to be ZipList<A>
when you omit the generic parameter (see this question for more info about this behaviour).
Therefore it's now expecting an input of [A]
in the ZipList(xs:_)
initialiser, meaning that the map function is inferred to be A -> A
, which you're trying to pass A -> B
to, causing the type mismatch (this is why f
is highlighted as the problem in your error).
If you simplify down your example to just calling init()
on your ZipList
without providing an argument, you'll see a more helpful error message:
class ZipList<A> {
init() {}
func map<B>() -> ZipList<B> {
// error: Cannot convert return expression of type 'ZipList<A>' to 'ZipList<B>'
return ZipList()
}
}
The fact that the compiler completely ignores the explicit type annotation of the return for the map()
method is a bug and is tracked by SR-1789. The cause, as described by Jordan Rose in the comments of the report is that:
It seems to be a case of us eagerly assuming the parameters are the same as for
self
. (That's usually a feature, but not when it gets in the way of other inference.)
The solution, as you've already found, is to explicitly state the generic parameter type of ZipList
when you create a new instance:
return ZipList<B>(xs: xs.map(f))
This forces the generic parameter to be of type B
, therefore preventing Swift from incorrectly inferring it, allowing the map
function to resolve.
As for what the error message "Cannot convert value of type 'A -> B' to expected argument type '_ -> _" means, _
in this case simply refers to a generic type which the compiler cannot resolve (not a helpful error message, I know). So all the compiler is telling you is that it was expecting a function that takes an input of an unknown type, and returns that same type.
It often helps when diagnosing these kind of error messages to split the expression up into multiple sub-expressions and inspect the types for each those to try and find the mis-match. It can also help to begin simplifying the example down (like using init()
instead of init(xs:[A])
in your map
method), until you run into a more helpful error message.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With