Я использую шаблон построчного типа Scala для простого запроса на отдых. Это прекрасно работает как беглый api.Неявное преобразование, не работающее с шаблоном построителя типа
sealed abstract class Method(name: String)
case object GET extends Method("GET")
case object POST extends Method("POST")
abstract class TRUE
abstract class FALSE
case class Builder[HasMethod, HasUri](
method: Option[Method],
uri: Option[String]) {
def withMethod(method: Method): Builder[TRUE, HasUri] = copy(method = Some(method))
def withUri(uri: String): Builder[HasMethod, TRUE] = copy(uri = Some(uri))
}
implicit val init: Builder[FALSE, FALSE] = Builder[FALSE, FALSE](None, None)
//Fluent examples
val b1: Builder[TRUE, FALSE] = init.withMethod(GET)
val b2: Builder[TRUE, TRUE] = init.withMethod(GET).withUri("bar")
Я хотел бы сделать это более DSL-как, позволяя Method
экземпляр быть преобразованы в Builder
например, Однако, когда я добавляю попытаться неявно включают в себя init
строителю комбинацию неявных параметров преобразования и типа спутать компилятор.
implicit def toMethod[HasUri](m: Method)
(implicit builder: Builder[_, HasUri]): Builder[TRUE, HasUri] = builder.withMethod(m)
// ** ERROR **: could not find implicit value for parameter builder:
// Builder[_, HasUri]
val b3: Builder[TRUE, TRUE] = GET withUri "foo"
// However the implicit parameter is discovered fine when function is called directly
val b4: Builder[TRUE, FALSE] = toMethod(GET)
val b5: Builder[TRUE, TRUE] = toMethod(GET) withUri "foo"
Все строки компилируются, за исключением b3. Когда функция toMethod
вызывается явно, параметр builder может быть найден неявно. Также, если я удалю общие аргументы (и тип безопасности), код работает так, как ожидалось.
Является ли это ограничением в неявных преобразованиях scala? Или мне не хватает правильного синтаксиса для этого?
Я хочу открыть экземпляр первоначального экземпляра неявно, чтобы позволить пользователям предоставлять свой собственный начальный строитель значениям по умолчанию для некоторых полей строителя.
Обновлено
я оставил некоторые из кода, чтобы сохранить пример простым, так как это просто неявное, что я пытаюсь исправить.
Тип безопасный шаблон строитель изложен очень хорошо здесь: http://blog.rafaelferreira.net/2008/07/type-safe-builder-pattern-in-scala.html
После этого вы можете только вызвать метод build
когда Builder
имеет метод и URI.
Причина, по которой я хочу открыть построитель как неявный параметр, заключается в поддержке следующего случая в DSL.
url("http://api.service.org/person") apply { implicit b =>
GET assert(Ok and ValidJson)
GET/"john.doe" assert(NotFound)
POST body johnDoeData assert(Ok)
GET/"john.doe" assert(Ok and bodyIs(johnDoeData))
}
В этих случаях
- Новый конструктор создается с указанным URI с помощью
url
- Это затем повторно в сторону закрытия, как
implicit b =>
assert
метод доступен только потому, что ури и метод указаны/
прилагается к текущему ури, это доступно только потому, что у конструктора указан uri.
Другой пример, где указанный метод Ури
GET url("http://api.service.org/secure/person") apply { implicit b =>
auth basic("harry", "password") assert(Ok and ValidJson)
auth basic("sally", "password") assert(PermissionDenied)
}
Вы можете дать это посмотреть и увидеть, если он проливает свет на то, что происходит с вашей неявной функцией, которая имеет неявные параметры , http://stackoverflow.com/questions/5080406/implicit-parameters-in-implicit-conversions – cmbaxter
Я бы пересмотрел дизайн. Вы дублируете информацию странным образом - с одной стороны, у вас есть параметр конструктора типа, указывающий, имеет ли компоновщик метод или URL-адрес во время компиляции, в то же время у вас есть параметры, которые могут быть разрешены только во время выполнения. Вопрос в том, чего вы хотите достичь (где должны проверяться типы)? Если вы переходите к параметрам типа, создайте подклассы, которые несут метод и URL (а не параметры). Наконец, вы хотите поднять метод к строителю. Нет необходимости проверять существующий тип 'HasUri', он всегда должен быть FALSE? –
@cmbaxter, спасибо, я постараюсь скомпилировать мой код с этими параметрами отладки, чтобы увидеть, проливает ли он какой-либо свет. – iain