问题上下文:我同时学习函数域建模和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#中,声明本质上都是Ints
的类型安全基元似乎非常容易。在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 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那样易于使用的功能,它已经被讨论过好几次了。Swift中有几个角落的情况,决定如何自动遵守协议(尤其是需要Self的协议(有点复杂。但它可能有一天会实施。
你可以在2019年AltConf关于这个主题的演讲中看到更深入的讨论。