2013-04-03 6 views
2

У меня есть метод со сложным типом возврата, и я хотел бы иметь функцию, которая принимает результат этого метода в качестве параметра. Возможно ли создать псевдоним для возвращаемого типа метода? Что-то вроде typeof от C++Тип псевдонима для выводимого типа

например.

object Obj { 
    def method(x:Int) = 1 to x 
    type ReturnType = ??? 

    //possible solution if i know a parameter for which the method won't fail 
    val x = method(1) 
    type ReturnType = x.type 

    //another possible solution, I don't need a parameter that won't fail 
    //the method but i still think there is a better way 
    lazy val x = method(1) 
    type ReturnType = x.type 

    //I would then like to have a function which takes ReturnType as a parameter 
    def doit(t:ReturnType) = Unit 
} 

Дело в том, что компилятор знает тип, но я не знаю, как его получить.

+0

Насколько я знаю, это называется * зависимыми типами *. –

+0

Если вы используете плагин IntelliJ scala, вы можете проверить тип любого выражения или метода, используя 'Alt' +' = '. В Scala REPL вы можете получить тип любого выражения с помощью команды ': type'. – ghik

+1

@ghik Да, я знаю, что могу найти тип в среде IDE или REPL, но в моем случае полный тип длиной более 80 символов, а его в исходном коде не поможет прочитать. Также возможно, что тип возврата изменится в будущем. –

ответ

2

Единственный способ, которым я мог думать это:

class Return[T](f:() => T) { 
    type Type = T 
} 

def getDifficultReturnType() = 1 to 10 

val Return = new Return(getDifficultReturnType) 

def doIt(t:Return.Type) = { 

} 

Я не уверен, если это то, что вы ищете.

+0

Это действительно более понятно, чем мое решение. Спасибо. Мне интересно, почему этот признак не имеет свойства FunctionN? (Я знаю, что могу создать неявное преобразование, но есть ли какая-то особая причина, почему тип возврата не должен меня беспокоить?) –

+0

В большинстве случаев это не то, что вы хотели бы. Я бы набрал метод doIt с «чертой» или «структурным типом», который содержит функции, которые я буду использовать в этом методе. Если бы я хотел сохранить исходный тип, я бы добавил параметр типа, подобный этому: 'def doIt [T <: TraitOrStructuralType] (t: T)'. Приложение содержит множество функций, было бы немного талии, чтобы добавить псевдоним типа для всех из них. – EECOLOR

+0

Я рассматривал структурный тип, но желаемое поведение тоже не очень просто (тип ReturnType в моем случае - это тип результата сглаженного запроса, делающего объединение нескольких таблиц). В любом случае, спасибо, это действительно лучше способ сделать то, что я хотел. Хотя я попытаюсь подумать, действительно ли это необходимо. –

0

Насколько мне известно, это невозможно. Возможно, в будущей версии Scala с type macros.

В любом случае, оставляя тип подальше, если он нетривиальный, на мой взгляд, не очень хороший дизайн. Я понимаю, что вы не хотите вводить 80 символов, но если важно сохранить этот тип (как он звучит), его следует развернуть по адресу около.

Вы можете использовать типа псевдоним:

object Obj { 
    type ReturnType = My with Very[LongAndComplicated] with Name 
    // explicit type ensures you really get what you want: 
    def method(x: Int): ReturnType = 1 to x 

    def doit(t: ReturnType) {} 
} 
+0

Ну, возможно _is_ (через ленивый val и nulls для параметров метода). Это просто не хорошо. Дело в написании всего типа заключается в том, что я не думаю, что это помогло бы кому-нибудь увидеть его выписанное (тело метода представляет собой довольно сложный гладкий запрос, который приводит к типу, который я даже не понимаю - я был думая об использовании структурного типа для определения того, что мне нужно от типа результата, но это казалось большой работой, не имеющей особой пользы). В любом случае спасибо за вход, если это действительно невозможно, я напишу тип. –

+0

@MartinKolinek Я думаю, вы ошибаетесь. То, что вы делаете, это использование зависимого типа 'x.type' для значения _some, генерируемого методом method_. Это не общий тип возврата этого метода. Просто попробуйте вызвать 'doit' с другим значением, полученным из' method', и вы увидите, что это невозможно. –

+0

Изначально я тоже так думал, но данный метод 'def method (x: Int): List [Int] = throw new Exception()' работает lazy val. Другими словами, ленивый val не оценивается кодом 'x.type'. –

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