swift - 如何基于 Int 创建一个新的类型安全的原始类型?

标签 swift types functional-programming

问题背景:我正在同时学习功能域建模和 Swift。我正在使用的示例是在 F# 中。一个这样的例子是声明单例联合:

//F# code
type CustomerId = CustomerId of int
type OrderId = OrderId of int

let customerId = CustomerId 42
let orderId = OrderId 42

printfn "%b" (orderId = customerId) //produces a compile error

因此,在 F# 中声明本质上都是 Int 的类型安全基元似乎非常容易。 在 Swift 中,typealias 不做同样的事情:

typealias CustomerId = Int
typealias OrderId = Int

let customerId: CustomerId = 42
let orderId: OrderId = 42

customerId == orderId // true!

现在,我明白 Swift 中的所有基本类型本质上都是 struct,但我还远未成熟到足以理解 Swift 代码库来弄清楚 Int 已创建。 有谁知道与 F# 声明等效的简单类型安全 Swift?

最佳答案

typealias 实际上只是一个别名。它不创建类型。它只是让输入别名的东西更容易。

做你想做的事情的方法是:

struct CustomerID {
    let value: Int
}

struct OrderID {
    let value: Int
}

如果您想要一个“裸”初始化程序(CustomerID(4) 而不是 CustomerID(value: 4)),您可以添加:

struct CustomerID {
    let value: Int
    init(_ value: Int) { self.value = value }
}

因为你可能会经常这样做,所以你可以将它提取到一个协议(protocol)中

protocol Identifier {
    typealias IDType
    init(value: IDType)
}

extension Identifier {
    init(_ value: Int) { self.init(value: value) }
}

extension CustomerID: Identifier {}

当然,如果您想要类似 = 42 的语法,您可以使用 ExpressibleByIntegerLiteral 添加类似的扩展。

您在 F# 中讨论的特定语法在 Swift 世界中通常通过其 Haskell 名称 newtype 来引用。 Swift 没有像 newtype 和 it's been discussed several times 这样易于使用的特性.在 Swift 中有几个极端情况,决定如何自动遵守协议(protocol)(尤其是需要 Self 的协议(protocol))有点复杂。但它可能有一天会实现。

您可以看到更深入的讨论 2019 AltConf talk on the subject .

关于swift - 如何基于 Int 创建一个新的类型安全的原始类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58647261/

相关文章:

ios - UITextView 左侧图像图标 swift

c# Reflection - 查找集合的通用类型

scala - Scala 中 Map 键和值类型参数之间的依赖关系

javascript - 将函数声明为 var 有什么好处?

ios - 将可变参数列表分配给变量

swift - 如何重置 Swift REPL?

ios - Xcode 8.2 使用旧版 Swift 问题

Oracle:使用 'N' 函数进行查询 - 我应该使用哪种数据类型?

javascript - 使用函数继承时, `instanceof` 相当于什么?

python - 什么时候应该使用函数柯里化(Currying)?