Проблема заключается в том, что, когда вы не укажете явно общий тип параметра ZipList
, когда вы обратитесь к нему, компилятор попытается сделать это для вас - а это не всегда исправить.
Как вы уже внутри ZipList<A>
класса, компилятор будет пытаться вывести ZipList
быть ZipList<A>
когда вы опускаете общий параметр (см this question для получения дополнительной информации о поведении).
Поэтому теперь ожидает ввод [A]
в ZipList(xs:_)
Инициализатором, а это означает, что функция карты выводятся как A -> A
, который вы пытаетесь передать A -> B
к, вызывая несоответствие типов (поэтому f
выделен в качестве проблема в вашей ошибке).
Если вы облегчите вниз ваш пример просто вызывая init()
на вашем ZipList
без предоставления аргументов, вы увидите более полезное сообщение об ошибке:
class ZipList<A> {
init() {}
func map<B>() -> ZipList<B> {
// error: Cannot convert return expression of type 'ZipList<A>' to 'ZipList<B>'
return ZipList()
}
}
Тот факт, что компилятор полностью игнорирует явное тип аннотации возврата для метода map()
является ошибкой и отслеживается SR-1789. Причина, как описано Иордана Rose в комментариях отчета в том, что:
Вроде бы случай мы охотно в предположении, что параметры такие же, как и для self
. (Это, как правило, функция, но не тогда, когда он становится на пути других умозаключений.)
Решение, как вы уже нашли, это явно указать общий тип параметра ZipList
при создании нового пример:
return ZipList<B>(xs: xs.map(f))
Это вынуждает общий параметр, чтобы иметь тип B
, поэтому предотвращение Swift из-за неправильного выводя его, позволяя функции map
решить.
Что касается того, что сообщение об ошибке «Невозможно преобразовать значение типа„A -> B“ожидаемого типа аргумента«_ -> _»означает, _
в данном случае просто относится к универсальному типу, который компилятор не может Разрешить (не полезное сообщение об ошибке, я знаю). Таким образом, весь компилятор говорит вам, что он ожидает, что функция принимает ввод неизвестного типа и возвращает тот же тип.
Это часто помогает при диагностировании подобных сообщений об ошибках, чтобы разделить выражение на несколько подвыражений и проверить типы для каждого из них, чтобы попытаться найти неправильное совпадение. Это также может помочь упростить пример вниз (например, использовать init()
вместо init(xs:[A])
в вашем методе map
), пока вы не столкнетесь с более полезным сообщением об ошибке.
Отличный ответ! Спасибо за помощь; в этом есть смысл. –
@MattFenwick Счастлив помочь :) – Hamish