2015-12-13 3 views
0

У меня есть черта, которая определяет связанный тип. В функции, я хочу вернуть этот ассоциированный тип, который отличается в зависимости от прилагаемого значения:Специализирующийся связанный тип внутри функции

sealed trait Abstract { 
    type T 
} 

class Impl1 extends Abstract { 
    type T = Int 
} 

class Impl2 extends Abstract { 
    type T = Boolean 
} 

object G { 
    def get[A <: Abstract] (x: A): A#T = { 
    x match { 
     case i1: Impl1 => 
     5 
     case i2: Impl2 => 
     true 
    } 
    } 
} 

Проблема заключается в том, что не Scala признать, что в случае согласованного A#T является Int или Boolean, соответственно, и я получите следующее сообщение об ошибке:

Expression of type Int doesn't conform to expected type A#T 

Как это решить?

+0

Что вы пытаетесь достичь с помощью такого кода? – metaphori

+0

@metaphori: В моем случае использования у меня есть куча вопросов, которые определяют их тип результата. Затем у меня есть функция 'calculateResponse [Q <: Question] (q: Q): Q # Result', которая дает ответ на вопрос (в зависимости от дополнительного состояния). –

+0

Итак, вы рисуете совпадение по типам вопросов, не так ли? – metaphori

ответ

1

Проблема заключается в том, что Scala не признает, что в случае согласованного A # T является Int или булева соответственно

Строго говоря , это не так. Например, вы могли бы назвать

get[Abstract](new Impl1) 

в этом случае A#T является Abstract#T, который не является ни Int не Boolean. Или

get(throw new Exception) 

так что вы получите Nothing#T (Nothing <: Abstract, в конце концов!).

Вообще-то, по моему опыту, Scala не так хороша даже в GADT, и, делая такие вещи, вам часто приходится «помогать», используя приведения, и ваша ответственность - убедиться, что они в безопасности.

2

Ваше состояние match дает результат AnyVal, он ничего не знает о A#T. Вы должны использовать .asInstanceOf[A#T] на результат или Extrac шаблону

val z = x match { 
    case i1: Impl1 => 
    5 
    case i2: Impl2 => 
    true 
} 
z match { 
    case x: A#T => x 
} 
+0

, так что даже если scala, похоже, не может проверить это ограничение, сохраняет ли это в качестве 'asInstanceOf' в этом случае i. е. он никогда не бросает 'CastClassException' (или' match' не прерывается)? –

+0

в этом конкретном случае вы не получите 'ClassCastException', но в целом вам следует избегать такой необходимости использования' asInstanceOf' – Rumoku

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