Scala: Есть ли способ, где псевдонимы типов могут рассматриваться как отличные от псевдонимов типов? - PullRequest
0 голосов
/ 03 октября 2018

В следующем примере: я хочу обрезать строку для соответствия определенным ограничениям длины, например, совместимости с типами SQL.

type varchar8 = String

implicit def str2Varchar8(str: String): varchar8 = str.take(8)

val a: varchar8 = "abcdefghi"

// wanted: "abcdefgh", actual result:
a: varchar8 = abcdefghi

Похоже, что компилятор не различает эти два типа.

Учитывая псевдоним типа type A = String, я пытаюсь добиться:

  1. , чтобы избежать выделения во время выполнения (т. Е. Класса-оболочки)
  2. возможность примененияутверждения / преобразования только при отображении из String в псевдоним типа A.т.е. избегать дальнейших утверждений / преобразований при работе непосредственно с псевдонимом типа A в качестве входных данных

Пример проверки:

type NotNullA = A

def method(a: A) = if(a != null)
    _method(a: NotNullA) // explicit typing
  else
    ???

// "a" at runtime is a String but we consider it validated, instead relying on the type system
protected def _method(a: NotNullA) = ???
protected def _otherMethod(a: NotNullA) = ???

Есть ли способ, при котором псевдонимы типов можно рассматривать какотделить от типа, который они псевдоним - и, следовательно, сделать возможным неявные преобразования и проверки типа между ними?Есть ли какое-то другое кодирование / метод, который выполняет эту работу?

Сторона: Кажется, я вспомнил момент, когда два были разделены, а тип и псевдоним были разными (не относящимися к типу).вопрос ари).Мой предыдущий код выглядел примерно так:

type FieldAType = Int

// and in a different class
def method(a: FieldAType) = ???

val b: FieldAType = 1
method(b) // worked

val c: Int = 1
method(c) // compiler error
method(c: FieldAType) // worked

Однако я не смог воспроизвести эту проблему (возможно, из-за более старой версии Scala - в настоящее время используется 2.11.8)

Ответы [ 3 ]

0 голосов
/ 04 октября 2018

Я советую вам взглянуть на библиотеку softwaremill.scala-common.tagging .

  • Нет времени выполнения

  • Надежный способ защитить ваш тип

Просто добавьте импорт и определите свой теговый тип:

import com.softwaremill.tagging._

type EvenTag
type EvenInt = Int @@ EvenTag

object EvenInt {
  def fromInt(i: Int): Option[EvenInt] =
    if (i % 2 == 0) Some(i.taggedWith[EvenTag]) else None
}

def printEvenInt(evenInt: EvenInt): Unit = println(evenInt)

EvenInt.fromInt(2).foreach(printEvenInt)

val evenInt: EvenInt = 2 // Doesn't compile
printEvenInt(2) // Doesn't compile

Как мы можем взломать его?

val evenInt: EvenInt = 1.taggedWith[EvenTag]

Наслаждайтесь!

0 голосов
/ 26 июля 2019

Существует функция, которая может быть реализована в Scala 3: opaque type s.

Они буквально решают проблему, которую вы описываете: возможность различать псевдонимы типов с обычными типами на основе их имени, а не наих реальный базовый тип.

Посмотрите на официальное предложение .

0 голосов
/ 03 октября 2018

Насколько я знаю, это невозможно.Псевдонимы - это просто дополнительное имя.Чисто для удобства чтения.

Однако вы можете сделать это с значениями классов .Они по-разному относятся к разным типам, поэтому вы можете по-разному обрабатывать их в своем коде.Но большую часть времени компилятор может избежать фактического выделения объекта-оболочки - на связанной странице есть больше информации о том, что является исключениями.

...