'Array <Element>' не может быть преобразован в 'Array <Int>'

Я могу создать итератор для создания префиксов:

extension Array where Element == Int {
  func prefixesInt() -> AnyIterator<[Element]> {
    var length = 0
    return AnyIterator {
      guard length < self.count else { return nil }
      length += 1
      return Array(self.prefix(length))
    }
  }
}

for prefix in [1,10,5].prefixesInt() {
  print(prefix)  // Prints: [1]  then  [1, 10]  then [1, 10, 5]
}

Теперь я хочу добиться того же с другими типами:

1) Кодирование типов в Ints

2) Использование той же префиксной функции

3) Возвращение к исходному типу

[Я знаю, что могут быть другие способы добиться этого, но я хочу следовать этой линии по разным причинам, а также хочу понять больше.]

Итак, мне нужно:

extension Array where Element: Equatable {
  func encode() -> [Int] {
    return map { self.firstIndex(of: $0)! }
  }
}
print(["A", "B", "A", "C"].encode())  // Prints: [0, 1, 0, 3]

extension Array where Element == Int {
  func decode<Output>(_ original: [Output]) -> [Output] {
    return map { original[$0] }
  }
}
print([2,3,0].decode(["P", "Q", "R", "S"]))  // Prints: ["R", "S", "P"]

Теперь я могу делать то, что хочу:

extension Array where Element: Equatable {
  func prefixes() -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
    return encode().prefixesInt().lazy.map { $0.decode(self) }
  }
}

for prefix in ["H","A","T"].prefixes() {
  print(prefix)
}

Теперь я хочу пойти еще дальше, сделав преобразование (в данном случае префиксы) параметром, и моя попытка такова:

extension Array where Element: Equatable {
  func encodeTransformDecode(transform: ([Int]) -> AnyIterator<[Int]> ) -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
    return transform(encode()).lazy.map { $0.decode(self) }
  }
}

который компилируется нормально, но когда я пытаюсь:

extension Array where Element: Equatable {
  func prefixes2() -> LazyMapSequence<AnyIterator<[Element]>, [Element]> {
    return encodeTransformDecode(transform: prefixesInt) //ERROR: 'Array<Element>' is not convertible to 'Array<Int>'
  }
}

for prefix in ["A","B","C"].prefixes2() {
  print(prefix)
}

Затем я получаю указанную ошибку

Я застрял. Любая помощь приветствуется.

Весь код:

print("========== prefixesInt")
extension Array where Element == Int {
  func prefixesInt() -> AnyIterator<[Element]> {
    var length = 0
    return AnyIterator {
      guard length < self.count else { return nil }
      length += 1
      return Array(self.prefix(length))
    }
  }
}

for prefix in [1,10,5].prefixesInt() {
  print(prefix)  // Prints: [1]  then  [1, 10]  then [1, 10, 5]
}

print("============ encode")
extension Array where Element: Equatable {
  func encode() -> [Int] {
    return map { self.firstIndex(of: $0)! }
  }
}
print(["A", "B", "A", "C"].encode())  // Prints: [0, 1, 0, 3]

print("============ decode")
extension Array where Element == Int {
  func decode<Output>(_ original: [Output]) -> [Output] {
    return map { original[$0] }
  }
}
print([2,3,0].decode(["P", "Q", "R", "S"]))  // Prints: ["R", "S", "P"]

print("============ prefixes")
extension Array where Element: Equatable {
  func prefixes() -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
    return encode().prefixesInt().lazy.map { $0.decode(self) }
  }
}

for prefix in ["H","A","T"].prefixes() {
  print(prefix)
}

extension Array where Element: Equatable {
  func encodeTransformDecode(transform: ([Int]) -> AnyIterator<[Int]> ) -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
    return transform(encode()).lazy.map { $0.decode(self) }
  }
}

print("============ prefixes2")
extension Array where Element: Equatable {
  func prefixes2() -> LazyMapSequence<AnyIterator<[Element]>, [Element]> {
    return encodeTransformDecode(transform: prefixesInt)
  }
}

for prefix in ["A","B","C"].prefixes2() {
  print(prefix)
}
prefixesInt определяется только на Array where Element == Int, а не в массивах вообще
ielyamani 16.11.2018 11:26

Но подпись encodeTransformDecode спрашивает, имеет ли преобразование тип: ([Int]) -> AnyIterator <[Int]>, так что не ясно в сообщении?

Cortado-J 16.11.2018 11:54

Вы не можете вызвать prefixesInt из массива, в котором единственное ограничение на элемент должно быть равнозначным. Плюс подпись prefixesInt не ([Int]) -> AnyIterator<[Int]>

ielyamani 16.11.2018 11:58

Какую версию Xcode / Swift вы используете? Комментирование вашей ошибки в конце и запуск дает результат с ожидаемым плюсом SWIFT RUNTIME BUG: unable to demangle type of field '_transform'. mangled type name is 'q_7ElementSTQzc' в игровой площадке Xcode 10.0 / Swift 4.2

CRD 16.11.2018 12:08

Привет @CRD, версия - Xcode 10.1 (10B61)

Cortado-J 16.11.2018 12:18

Спасибо @ Carpsen90 за помощь в этом. Ваш вопрос заставляет меня понять, что я не понимаю тип prefixesInt. Я предположил, что, поскольку это метод на [Int] и возвращает AnyIterator<[Int]>, его типом будет ([Int]) -> AnyIterator<[Int]>, но я полагаю, что я не прав?

Cortado-J 16.11.2018 12:22

Его тип - () -> AnyIterator<[Int]>.

ielyamani 16.11.2018 12:26

Я думаю, вам не хватает одной вещи, так это то, что в encodeTransformDecode(transform: prefixesInt) есть ссылка скрытыйself, поскольку prefixesInt является методом экземпляра - и в этом случае этот self не относится к типу [Int]. Это дает вам две проблемы: неправильный тип, и даже если это был правильный тип, вы неявно связали self. Если вы определите метод staticprefixesInt, который принимает [Int] и просто вызывает версию экземпляра в своем аргументе, передайте его в encodeTransformDecode, и вы продвинетесь дальше. (У меня ваш код "работает" в 10.0, но он извергает ОШИБКИ РАБОТЫ, поэтому публиковать не буду!)

CRD 16.11.2018 12:49

Спасибо @CRD. Я задавался вопросом, но не очень ясно об этом, поэтому ваш комментарий подтолкнул меня к исследованию ... Я очень хотел не идти по статическому маршруту - это делает другие части кода менее элегантными. У меня были довольно смутные воспоминания о некоторых методах каррирования из превосходного "obj Functional Swift". Я поискал его, и это помогло мне уточнить, что тип prefixesInt на самом деле: (Array<Int>) -> () -> AnyIterator<[Int]>. Осознание этого дает мне решение. Я отправлю свои выводы в качестве ответа.

Cortado-J 16.11.2018 20:50
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
9
352
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

С помощью полезных советов от @ Carpsen90 и @CRD (спасибо обоим!) И некоторого погружения в отличную книгу "obj Functional Swift" (без личного контакта) я нашел решение.

Тип метода экземпляра отличается от статического метода, как показано:

extension Int {
  static func doubleStatic(_ x: Int) -> Int { return x * 2 }
  func doubleInstance() -> Int { return self * 2 }
}
print( type(of: Int.doubleStatic) )    // Prints: (Int) -> Int
print( type(of: Int.doubleInstance) )  // Prints: (Int) -> () -> Int

В вопросе тип prefixesInt на самом деле: (Array<Int>) -> () -> AnyIterator<[Int]>.
Имея это в виду, мы можем переписать encodeTransformDecode следующим образом:

extension Array where Element: Equatable {
  func encodeTransformDecode(transform: (Array<Int>) -> () -> AnyIterator<[Int]> ) -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
    return transform(encode())().lazy.map { $0.decode(self) }
  }
}

Во-вторых, нам нужно сообщить компилятору немного больше о типе prefixesInt, когда мы будем использовать его в prefixes2, поэтому:

extension Array where Element: Equatable {
  func prefixes2() -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
    return encodeTransformDecode(transform: Array<Int>.prefixesInt)
  }
}

а теперь по мере необходимости:

for prefix in ["A","B","C"].prefixes2() {
  print(prefix)
}

дает нам:

["A"]
["A", "B"]
["A", "B", "C"]

и теперь мы можем очень легко расширить с помощью другой функции очень кратко:

extension Array where Element == Int {
  func suffixesInt() -> AnyIterator<[Element]> {
    var length = 0
    return AnyIterator {
      guard length < self.count else { return nil }
      length += 1
      return Array(self.suffix(length))
    }
  }
}

extension Array where Element: Equatable {
  func suffixes2() -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
    return encodeTransformDecode(transform: Array<Int>.suffixesInt)
  }
}

for suffix in ["A","B","C"].suffixes2() {
  print(suffix)
}

Возможно, фраза: transform(encode())().lazy.map { $0.decode(self) } загадочна и может быть лучше: let encoded = encode()let transformFunction = transform(encoded)let transformIterator = transformFunction()let lazyTransformIterator = transformIterator.lazyreturn lazyTransformIterator.map { $0.decode(self) }

Cortado-J 16.11.2018 21:07
Ответ принят как подходящий

Как указано в моем комментарии, и вы исследовали в своем собственном ответе, основная проблема в вашем коде заключается в том, что у вас неправильный тип prefixesInt. Метод экземпляра имеет тип формы:

(<object type>) -> (<argument types>) -> <return type>

значение, переданное для <object type>, - это то, что связано с self в функции. Итак, тип prefixesInt:

([Int]) -> () -> AnyIterator<[Int]>

Чтобы исправить ваш код, вам нужно только изменить prefixes2:

func prefixes2() -> LazyMapSequence<AnyIterator<[Int]>, [Element]>
{
   return encodeTransformDecode(transform: { $0.prefixesInt() } )
}

Тип был изменен и теперь включает AnyIterator<[Int]>, а не AnyIterator<[Element]>, и передается закрытие { $0.prefixesInt() }, а не просто prefixesInt (первый принимает массив в качестве аргумента, а компилятор передает последний, что является сокращением для self.prefixesInt, в качестве закрытия с текущим значением Предварительно связанный self - этот self, являющийся Array<Equatable>, был вызван prefixes2).

HTH


Чтобы увидеть связь с созданным вами кодом, учтите, что:

<value>.method(<args>)

это просто сокращение для:

<type of value>.method(<value>)(<args>)

Что в данном случае означает, что:

$0.prefixesInt()

это сокращение для:

Array<Int>.prefixesInt($0)()

это то, что вы создали, но распространяли между prefixes() (Array<Int>.prefixesInt) и encodeTransformDecode (transform(encode())()). При использовании сокращения и закрытии никаких изменений в encodeTransformDecode не требуется.

Спасибо, CRD. Ваш ответ действительно проясняет мое понимание. Очень признателен.

Cortado-J 17.11.2018 00:20

Другие вопросы по теме