2016-12-19 6 views
1

Это работает, но я бы хотел избежать помощи компилятору, поскольку я понятия не имею, какой тип тега должен быть, я просто знаю, что он будет иметь тип Field.Scala - отсутствует тип параметра - можно ли избежать помощи компилятору?

val x: TypeString = TypeString("test") 

TypeValidator.validate[TypeString](x, x => { 
    true 
}) 

Что бы в идеале хотели бы иметь это: (где х тип выводится)

TypeValidator.validate(x, x => { 
    true 
}) 

Класс валидации следующим

import models.implementations.Field 

object TypeValidator { 
    def apply(): TypeValidator = { 
    new TypeValidator() 
    } 
    def validate[T <: Field](t: T, v: T => Boolean): Boolean = { 
    new TypeValidator().validate(t, v) 
    } 
} 

class TypeValidator { 
    def validate[T <: Field](t: T, v: T => Boolean): Boolean = v.apply(t) 
} 

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

Пожалуй, ближе я пришел найти ответ здесь:

scala anonymous function missing parameter type error

Update - просто добавить, это делает работу, но я чувствую, что может быть лучшим решением до сих пор:

TypeValidator.validate(x)(x => { 
    true 
}) 

Изменен класс для объявления второго набора параметров для анонимной функции.

class TypeValidator { 
    def validate[T <: Field](t: T)(v: T => Boolean): Boolean = v.apply(t) 
} 
+1

Что не нравится в последнем решении? –

+4

Вы можете удалить фигурные скобки из своего второго решения и заменить скобки скорбью. Меньше печатать, и это решение * на мой взгляд. Currying - довольно распространенная вещь, чтобы сделать вывод о типе. Например, в списке используется 'foldLeft'. –

+0

@MichaelZajac, это просто больше похоже на взлом, чем что-либо еще. Хотя решение работает, оно просто слишком сложно. –

ответ

2

Там нет лучшего решения, чем

class TypeValidator { 
    def validate[T <: Field](t: T)(v: T => Boolean): Boolean = v.apply(t) 
} 

Любое другое решение будет неоправданно усложнять подпись validate.

типа inferencer Scala идет через параметр перечисляет один за другим, так что, когда он увидел старую версию, он попытался вывести T как из аргумента функции и Field аргумента, и не потому, что тип аргумента функции нет полностью был известен. Здесь inferencer принимает аргумент Field, не думая о аргументе функции, и указывает на то, что T = TypeString. Это позволяет затем вывести тип аргумента аргумента функции.

Вы найдете, что это очень распространенный образец всей стандартной библиотеки Scala и в основном всех других библиотек Scala.

Кроме того, вы можете и должны опустить скобки вокруг аргумента функции:

TypeValidator.validate(x) { x => 
    true 
}