Как заставить это неявное преобразование Scala работать? - PullRequest
3 голосов
/ 09 декабря 2011

Я использую библиотеку, которая дает мне следующее (отношения могут быть неявно преобразованы в узлы):

class Relation[A,B]
class Node[A,B](r: Relation[A,B])
implicit def relation2node[A,B](r: Relation[A,B]) = new Node(r)

Я расширяю отношение для собственного использования:

class XRelation[A] extends Relation[A,Int]

Отношения / X-отношения должны быть подклассами:

class User extends XRelation[Int]

Теперь я также определяю свои собственные вспомогательные методы, такие как GET, предназначенные для работы с любым узлом и всем, что преобразуется в узел:

class Helper[A,B](n: Node[A,B]) { def GET {} }

// note: this is the only way I know of to make the next example work.
implicit def xx2node2helper[A,B,C[_,_]](x: C[A,B])(implicit f: C[A,B] => Node[A,B]) = new Helper(x)

Итак, этот пример работает:

new Relation[Int,Int]().GET

И если я добавлю еще одно неявное преобразование:

// don't understand why this doesn't work for the previous example
// but works for the next example
implicit def x2node2helper[A,B,C](x: C)(implicit f: C => Node[A,B]) = new Helper(x)

Я также могу сделать следующее преобразование работы:

new XRelation[Int]().GET

Но это не работает:

new User().GET

К сожалению, это не с:

error: No implicit view available from Sandbox3.User => Sandbox3.Node[A,B]

Может кто-нибудь разобраться во всем этом и объяснить, как заставить работать последний пример? Заранее спасибо.

Обновление : я знаю, что вы можете просто ввести неявные преобразования из Relation, но я прошу (1) выяснить, как это сделать, не вводя импликации из каждого отдельного типа, который мог бы возможно, неявно преобразовать в Node и (2) укрепить мое понимание последствий.

Ответы [ 2 ]

4 голосов
/ 09 декабря 2011
implicit def nodeLike2Helper[R, C <: R](r:C)(implicit f: R => Node[_,_]) = {
  new Helper(r)
}

Как указано в сообщении об ошибке, User не имеет неявного преобразования в Node.Но это супер-супер-класс Relation.Таким образом, вы просто даете правильные границы для параметров типа.

К вашему сведению, существует синтаксис <% для границ представления, поэтому приведенный выше код может быть короче:

implicit def nodeLike2Helper[R <% Node[_,_], C <: R](r:C) = {
  new Helper(r)
}
1 голос
/ 09 декабря 2011

Разрешение scala распространяется только на один суперкласс при проверке, соответствует ли пользователь шаблону типа C[_,_]. Вы можете исправить это, покончив с шаблоном в следующем коде.

implicit def x2node2helper[A,B](x: Relation[A,B])(implicit f: Relation[A,B] => Node[A,B]) = new Helper(x)

И если для определения x2node2helper находится область неявного отношения 2, это можно записать

implicit def x2node2helper[A,B](x: Relation[A,B]) = new Helper(x)
...