Как мне создать новый типобезопасный примитивный тип, основанный на Int? - PullRequest
2 голосов
/ 31 октября 2019

Контекст проблемы: я изучаю функциональное моделирование домена и 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 s, но я далеко не настолько изощрен, чтобы понимать Swiftкодовая база, чтобы выяснить, как Int был создан. Кто-нибудь знает простой безопасный для типов Swift, эквивалентный объявлению F #?

1 Ответ

3 голосов
/ 31 октября 2019

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 {}

ИКонечно, вы можете добавить аналогичные расширения, используя ExpressibleByIntegerLiteral, если вам нужен такой синтаксис, как = 42.

Конкретный синтаксис, который вы обсуждаете в F #, часто упоминается в мире Swift по имени Haskell, newtype. Swift не имеет такой простой в использовании функции, как newtype, и это обсуждалось несколько раз . В Swift есть несколько ключевых случаев, когда немного сложно решить, как вы будете автоматически соответствовать протоколам (особенно протоколам, которые требуют Self). Но это может быть реализовано когда-нибудь.

Вы можете увидеть гораздо более глубокое обсуждение этого доклада AltConf 2019 по этому вопросу .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...