相互递归的通用枚举

时间:2019-04-30 05:25:50

标签: swift generics enums

通用递归enum

我可以轻松地在Swift中表达一个通用的递归枚举:

indirect enum Tree<T> {
    case empty
    case leaf(T)
    case node(Tree, Tree)
}

鉴于此,我可以实例化Int的一些示例树,例如:

let exampleTrees: [Tree<Int>] = [
    .empty,
    .leaf(10),
    .node(.node(.leaf(1), .leaf(2)), .node(.leaf(3), .leaf(4)))
]

相互递归

Tree枚举以类似于递归函数的方式递归。 emptyleaf情况终止递归,而node是递归情况。

使用递归函数时,通常有一对相互递归函数。一个愚蠢但经典的说明性示例是:

func isEven(_ x: Int) -> Bool {
    return x == 0 ? true : isOdd(x-1)
}

func isOdd(_ x: Int) -> Bool {
    return x == 0 ? false : isEven(x-1)
}

类似地,也可以声明一对相互递归的enum

indirect enum AB {
    case a
    case b(CD)
}

indirect enum CD {
    case c
    case d(AB)
}

鉴于这些,我可以开始创建递归值。这里有一些例子……

let exampleRecursives: [AB] = [
    .a,
    .b(.c),
    .b(.d(.a)),
    .b(.d(.b(.c)))
]

(这些显然完全是愚蠢且无用的-只是为了说明发生了什么!)

通用的相互递归enum

ABCD的定义是限制性的,因为它们不是通用的,我希望它们是通用的:

indirect enum AB<T> {
    case a
    case b(T)
}

indirect enum CD<T> {
    case c
    case d(T)
}

问题

鉴于我有这些通用的替代方案,我希望能够表达与非通用原件相同的相互递归嵌套。我需要迅速告诉我们类型为AB<CD<AB<CD<AB<CD<AB<CD<AB<CD< …,但是可以无限长。

我试图表达如下:

typealias RecursiveABCD = AB<CD<RecursiveABCD>>

这会给出编译错误"Circular reference"

我也尝试过:

typealias RecursiveAB = AB<RecursiveCD>
typealias RecursiveCD = CD<RecursiveAB>

但是同样,编译器错误"Circular reference"

解决

一种解决方法是定义一种包装器,如下所示:

struct W {
    init(_ x: AB<CD<W>>) {
        self.x = x
    }

    let x: AB<CD<W>>
}

如果这样做,我可以创建示例,如下所示:

let exampleRecursives: [W] = [
    W(.a),
    W(.b(.c)),
    W(.b(.d(W(.a)))),
    W(.b(.d(W(.b(.c)))))
]

使用起来似乎很麻烦和笨拙。

问题

是否可以在不引入包装器的情况下使用递归泛型枚举?

0 个答案:

没有答案