2016-05-11 3 views
5

Я использую бесформенные теги и написал код, подобный этому -типов Scala и компиляция

import shapeless.tag 
import [email protected]@ 

object Typeplay { 
    trait StringTrait 
    type MyString = String @@ StringTrait 

    case class StringClass(mps: MyString) 
    val stringClass = StringClass(tag[StringTrait]("test")) 
} 

И этот код не будет компилироваться. Компилятор Scala жалуется на последнюю строку кода:

[error] found : String("test") 
[error] required: shapeless.tag.Tagged[in.bharathwrites.Typeplay.StringTrait] with String 
[error] val stringClass = StringClass(tag[StringTrait]("test")) 

Я не мог понять, что я делал неправильно. Поэтому я внесла небольшое изменение в мой код -

import shapeless.tag 
import [email protected]@ 

object Typeplay { 
    trait StringTrait 
    type MyString = String @@ StringTrait 

    case class StringClass(mps: MyString) 

    val stringTag = tag[StringTrait]("test") 
    val stringClass = StringClass(stringTag) 
} 

В основном это использование явной переменной для тегов. И этот код компилируется !!

Как это может быть? Почему первая программа не компилируется, а вторая?

ответ

1

Кажется, что тип alias смущает вывод типа в этом случае. Если вы предоставляете явные типы в методе tag, все работает отлично:

StringClass(tag[StringTrait][String]("test")) 

или

StringClass(tag[StringTrait]("test"):String @@ StringTrait) 

или если вы объявите параметров StringClass непосредственно:

case class StringClass(mps: String @@ StringTrait) 

StringClass(tag[StringTrait]("test")) 

Видимо ограничение Скала компилятор ,


UPD. Честно говоря, я не могу сказать, какое точное ограничение вы делаете здесь. Поиск подходящих открытых ошибок был бесплодным.

Относительно первого примера. Все становится ясно, если посмотреть на реализацию tag:

object tag { 
    def apply[U] = new Tagger[U] 

    trait Tagged[U] 
    type @@[+T, U] = T with Tagged[U] 

    class Tagger[U] { 
    def apply[T](t : T) : T @@ U = t.asInstanceOf[T @@ U] 
    } 
} 

Итак, когда вы делаете это:

tag[StringTrait][String]("test") 

Вы в основном это сделать:

tag.apply[StringTrait].apply[String]("test") 
+0

Можете ли вы пролить свет на то, что это ограничение. Кроме того, я недоумеваю, как можно отличить значение более чем от 1 типа, как это было сделано в первом предложении. Он работает, но я не понимаю, как это сделать. Я попробовал небольшую программу, чтобы убедиться, что это работает во всех сценариях, и это не так: – Bharadwaj

+0

'scala> def myToString [A] (s: A) = s.toString myToString: [A] (s: A) String scala > myToString [String] [Object] ("hello") : 13: error: метод myToString: (s: String) Строка не принимает параметры типа. myToString [String] [Object] ("hello") ^ scala> myToString [String] ("hello") res1: String = hello' – Bharadwaj

+0

@Bharadwaj, см. Обновление. – Aivean

Смежные вопросы