2017-01-05 4 views
1

Я пытаюсь портировать части библиотеки Haskell для типа данных унифицированной программировании на Scala. Вот проблема, я столкнулся:Scala: несколько параметров типа для неявного класса

Я определил черту, Generic, с некоторым параметром контейнерного типа:

trait Generic[G[_]] { 
    // Some function declarations go here 
} 

Теперь у меня есть абстрактный класс, Collect, с тремя параметрами типа, и объявление функции (это означает тип, чем может собрать все subvalues ​​типа B в контейнер типа F[_] из некоторой структуры типа A):

abstract class Collect[F[_],B,A] { 
    def collect_ : A => F[B] 
} 

В целях сделать его продлить Generic, первые два параметра типа F[_] и B приведены, и A является кэрри (этот эффект моделируется с помощью типа лямбды):

class CollectC[F[_],B] extends Generic[({type C[A] = Collect[F,B,A]})#C] { 
    // Function definitions go here 
} 

Проблема заключается в том, что мне нужно определение последнего класса, чтобы быть неявной , потому что позже в моем коде мне нужно будет, чтобы иметь возможность написать такие функции, как

class GUnit[G[_]](implicit gg: Generic[G]) { 
    // Some definitions 
} 

Когда я просто предварять implicit к определению класса, я получаю ошибку говоря implicit classes must accept exactly one primary constructor parameter. Кто-нибудь сталкивался с подобной проблемой? Есть ли известный способ обойти это? В настоящее время я не вижу, как я мог бы реорганизовать свой код, сохраняя при этом ту же функциональность, поэтому любые советы приветствуются. Заранее спасибо!

ответ

4

Неявные классы не работают таким образом. Они являются сокращением для неявных конверсий. Например, implicit class Foo(i: Int) равно class Foo(i: Int); implicit def Foo(i: Int) = new Foo(i). Таким образом, он работает только с классами, которые имеют только один параметр в своем конструкторе. Это не имеет смысла для большинства классов 0 (type-).

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

Для чего (я думаю), который вы пытаетесь сделать, вам нужно будет предоставить неявный экземпляр CollectC. Я предлагаю поместить его в объект-компаньон Collect. Но вы можете выбрать alternative solution, если это лучше всего соответствует вашим потребностям.

scala> :paste 
// Entering paste mode (ctrl-D to finish) 

trait Generic[G[_]] { 
    // Some function declarations go here 
} 

abstract class Collect[F[_],B,A] { 
    def collect_ : A => F[B] 
} 

object Collect { 
    implicit def mkCollectC[F[_],B]: CollectC[F,B] = new CollectC[F,B] 
} 

class CollectC[F[_],B] extends Generic[({type C[A] = Collect[F,B,A]})#C] { 
    // Function definitions go here 
} 

// Exiting paste mode, now interpreting. 

warning: there were four feature warnings; for details, enable `:setting -feature' or `:replay -feature' 
defined trait Generic 
defined class Collect 
defined object Collect 
defined class CollectC 

scala> implicitly[Generic[({type C[X] = Collect[List,Int,X]})#C]] 
res0: Generic[[X]Collect[[+A]List[A],Int,X]] = [email protected] 
+0

Это было очень полезно, спасибо! – Rrr

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