Swift 中是否可以要求关联类型符合关联类型的关联协议?

dea*_*.dg 5 associated-types swift swift-protocols

我正在尝试(基本上没有任何理由)制定一个协议来描述类别理论中的类别。我试图想出这样的东西。

protocol Category {
    associatedtype Object: Protocol
}
protocol Hom {
    associatedtype C: Category
    associatedtype Source: C.Object
    associatedtype Target: C.Object
}
Run Code Online (Sandbox Code Playgroud)

特别是,我希望每个 Hom 类型都有一个关联的类别 C 以及关联的源和目标类型,它们都是该类别中的对象。因此,我将一个对象协议与每个类别相关联,并尝试使 Hom 的源和目标符合相应类别的对象协议。上面的代码无法编译

Type 'Self.Source' constrained to non-protocol, non-class type 'Self.C.Object'
Run Code Online (Sandbox Code Playgroud)

这个错误至少不清楚,因为 C.Object 被声明为协议。有什么办法可以解决这个问题吗?

编辑:

正如 Rob 所指出的,代码本身没有多大意义。Protocol 是 ObjC 中的一个特定类,而不是描述协议的类型。此外,不存在描述所有协议的类型,因为协议本身不能符合协议,因为它们只是对其他类型的要求。我正在寻找的是一个元类型,其中 Any.Protocol、Sequence.Protocol 等都是其实例。

我将更详细地说明我试图描述哪种结构。

类别是一个对象类型以及每对对象实例之间的同态类型。对于 Object 的两个实例 A 和 B,同态类型通常写为 Hom(A,B),但我会写Hom<A,B>为 Swiftier。然后类别配备有带有签名的组合<A: Object, B: Object, C: Object>(_ f: Hom<A,B>, _ g: Hom<B,C>) -> Hom<A,C>

如果 f 是 的实例Hom<A,B>,则 A 称为 f 的源或域,B 称为 f 的目标或共域。

类型本身就是一个类别,其中 Object 是所有类型的元类型 和Hom<A,B> = (A) -> B

类别在 Swift 中比较困难的主要原因是 Swift 没有依赖类型。无法描述对象类型为 Int 的类别,因为无法拥有类型Hom<0,0>。但是,如果要求对象类型是元类型,那么Hom<A,B>向类型系统描述突然是一件有意义的事情,因为元类型的实例是一种类型(我认为),它可以是泛型参数。这就是我试图通过设置对象:协议来描述的内容。

在 Swift 中,我真的很想描述

Type 'Self.Source' constrained to non-protocol, non-class type 'Self.C.Object'
Run Code Online (Sandbox Code Playgroud)

但这也是行不通的,因为关联类型不能具有泛型参数。

在我的用例中,我有一个描述有限生成的阿贝尔群的协议和一个描述有限生成的单位环的协议,我很想编写通用代码,它不关心它是否与 、GroupHom<A,B> where A: AbelianGroup, B: Abelian GroupRingHom<A,B> where A: Ring, B: Ring作为(A) -> B每个这些都配备了正确的构图。

也许这是不可能的,但我愿意接受。请告诉我这是否足够不同以至于应该作为一个单独的问题提出。

Jes*_*mez 1

dg

在 swift 中,您不能使用协议关联类型作为关联类型,因为它没有定义什么类型。

关联类型只能用作类型的约束,如下所示:

protocol Category {
    associatedtype Object1:Equatable
}

class Homs:Category{
    typealias Object1 = Int

    func sum(element:Object1){

        print(element+element)
    }
}
Run Code Online (Sandbox Code Playgroud)

或者像这样

protocol Category {
    associatedtype Object1: Equatable
}

protocol Homs {
    associatedtype Cat:Category
    associatedtype Source: Category where Source.Object1 == Cat.Object1
    associatedtype Target: Category where Target.Object1 == Cat.Object1
}
Run Code Online (Sandbox Code Playgroud)

您的代码无法编译的原因是,您的关联类型目标被限制为实现协议的关联类型(未定义)。有人需要先定义它才能用作约束。

解决您的问题的方法可能是生成一个通用类。我们来看看:

protocol Category {
    associatedtype Object1: Equatable
}

class Homs<Cat:Category,Source,Target> where Cat.Object1 == Source && Cat.Object1 == Target.Object1{

}
Run Code Online (Sandbox Code Playgroud)

另一种方法可以创建一个通用的 Category 类,以及一个类别类、类别类、源和目标符合类型的协议:

class Category<T>{
}

protocol Homs {
    associatedtype ObjectType
    associatedtype Cat:Category<ObjectType>
    associatedtype Source where Source == ObjectType
    associatedtype Target where Target == ObjectType
}
Run Code Online (Sandbox Code Playgroud)

O类似于第二个例子:

protocol Category {
    associatedtype Object1: Equatable
}

protocol Homs {
    associatedtype Cat:Category
    associatedtype Source: Category where Source.Object1 == Cat.Object1
    associatedtype Target: Category where Target.Object1 == Cat.Object1
}
Run Code Online (Sandbox Code Playgroud)

请记住,您不能将具有关联类型的协议用作关联类型的类型约束或变量或常量的类型,首先需要有人定义关联类型。

我希望我对你有帮助。