Swift 4. Использование PAT.Разрешены ли протоколы, которые ссылаются друг на друга?Я получаю сообщение об ошибке, я не понимаю - PullRequest
0 голосов
/ 27 августа 2018

В приведенном ниже коде я настроил протоколы для вершин и ребер в простом графическом проекте.Вершины ссылаются на ребра, а ребра ссылаются на вершины.В функции neighbours() я вызываю map() в массиве edges и получаю эту ошибку:

'map' создает '[T]', а не ожидаемый контекстный тип результата '[Self.VertexType] '.

import Foundation

protocol EdgeProtocol {
    associatedtype VertexType: VertexProtocol
    var from : VertexType { get set }
    var to : VertexType { get set }
    init(from: VertexType, to:VertexType)
}

protocol VertexProtocol  {
    associatedtype EdgeType: EdgeProtocol
    associatedtype VertexType: VertexProtocol
    var id: String { get set }
    var edges: [EdgeType] { get set }
    func neighbours() -> [VertexType]
}

extension VertexProtocol {
    func neighbours() -> [VertexType] {
        return edges.map { $0.to }  // 'map' produces '[T]', not the expected
                                    //  contextual result type '[Self.VertexType]'
    }
}

struct Edge: EdgeProtocol {
    typealias VertexType = Vertex   // leave out -> no compile error
    var from: Vertex
    var to: Vertex
    init(from: Vertex, to:Vertex) {
        self.from = from
        self.to = to
    }
}

class Vertex: VertexProtocol {
    typealias VertexType = Vertex   // leave out -> compile error
    typealias EdgeType = Edge       // leave out -> no compile error

    var id: String
    var edges = [Edge]()
    init(name: String) { id = name }
}

Мой код "знает", что edges имеет тип [Vertex:VertexProtocol], но тем не менее map() интерпретирует его как [T].Это потому, что Swift 4 не допускает перекрестные ссылки между протоколами или что-то еще?Должен признаться, я не совсем понимаю PAT (протоколы со связанными типами), как показывают мои строки комментариев.Любое руководство ценится

1 Ответ

0 голосов
/ 27 августа 2018

Проблема в том, что хотя edges соответствует EdgeProtocol, а EdgeProtocol содержит VertexType связанный тип, компилятор не может знать, что это будет тот же тип, что и VertexProtocol 's VertexType связанный тип.Оба протокола VertexType будут соответствовать VertexProtocol, но они не обязательно должны быть одного типа.Поэтому edges.map { $0.to } возвращает [EdgeType.VertexType], но ваша функция объявлена ​​как возвращающая [Self.VertexType], так что это несоответствие типов.

Это можно исправить, явно указав, что оба VertexType одинаковы.Вы можете сделать это либо в определении:

protocol VertexProtocol  {
    associatedtype VertexType
    associatedtype EdgeType: EdgeProtocol where EdgeType.VertexType == VertexType
    // ...
}

Или, если это нецелесообразно, вы можете ограничить расширение:

extension VertexProtocol where EdgeType.VertexType == VertexType {
    func neighbours() -> [VertexType] {
        return edges.map { $0.to }
    }
}

Любой из этих подходов должен привести к компиляции кода.

...