2015-04-17 6 views
1

У меня есть следующий код:Scala, проблема несоответствие типов и определение типа проблема

import shapeless._ 
trait TypeLike 

case class Arg(name:String) 

case class Predicate[Args <: HList, O <: TypeLike](name: String,args:Args,output:O,func: Args => O)(implicit val lubWitness: LUBConstraint[Args, Arg]) 

(Это было результатом вопрос: Here) И я хочу иметь:

import scalax.collection.edge.LDiEdge 
import scalax.collection.immutable.Graph 
import scalax.collection.edge.Implicits._ 
import shapeless._ 

case class SimplePlan[A<:HList,B<:TypeLike,N<:Predicate[A,B]](plan:Graph[N,LDiEdge]) 

я получаю несоответствие типов и подразумеваемые ошибки аргумент типа на следующий код:

object testMe extends App{ 
    val p1 = Predicate("Example1", Arg("test")::Arg("test")::HNil, new TypeLike {}, 
    (args: Arg ::Arg:: HNil) => { println(args(0));new TypeLike {} }) 


    val p2 = Predicate("Example2", Arg("test")::HNil, new TypeLike {}, 
    (args: Arg :: HNil) => { println(args(0));new TypeLike {} }) 

    val x = Graph((p1 ~+> p2)("booo")) 
    val p = SimplePlan(x) 
} 

Что именно я должен добавить, чтобы решить проблему? В случае, если вы хотите иметь зависимостей:

scalaVersion := "2.10.4" 

libraryDependencies += "com.assembla.scala-incubator" %% "graph-core" % "1.9.1" 

libraryDependencies += "com.chuusai" % "shapeless_2.10.4" % "2.1.0" 

Edit: (больше объяснений)

Predicate класс является классом с функцией «Func», который может получить переменное число аргументов. Я реализовал это, используя вопрос, который я задал ранее (ссылка есть) Я могу создать экземпляр из предиката, p1 и p2. У меня есть еще один класс «SimplePlan», который имеет член графа, который я хочу, чтобы его узлы были Predicate. Но поскольку я использую определение HList в определении Predicate, типы каждого из них различаются. Тип каждого p1 и p2. Я получаю ошибку несоответствия типа на:

val p = SimplePlan(x) 

Я действительно не знаю, как я должен определить SimplePlan, чтобы решить эту проблему. Точная ошибка:

Error: inferred type arguments [Nothing,Nothing,Planner.Predicate[_ >: shapeless.::[Planner.Arg,shapeless.HNil] with shapeless.::[Planner.Arg,shapeless.::[Planner.Arg,shapeless.HNil]] <: shapeless.::[Planner.Arg,shapeless.HList], Planner.TypeLike]] do not conform to method apply's type parameter bounds [A <: shapeless.HList,B <: Planner.TypeLike,N <: Planner.Predicate[A,B]] 
    val p = SimplePlan(x) 
     ^

Error: type mismatch; 
found : scalax.collection.immutable.Graph[Planner.Predicate[_ >: shapeless.::[Planner.Arg,shapeless.HNil] with shapeless.::[Planner.Arg,shapeless.::[Planner.Arg,shapeless.HNil]] <: shapeless.::[Planner.Arg,shapeless.HList], Planner.TypeLike],scalax.collection.edge.LDiEdge] 
required: scalax.collection.immutable.Graph[N,scalax.collection.edge.LDiEdge] 
    val p = SimplePlan(x) 
        ^

Edit 2 (Объяснение того, что именно я хочу): Мне это нужно для моего исследовательского проекта, так что я хочу сделать, может быть немного странно. Я хочу иметь предикатный класс, который имеет в нем функцию с разными параметрами числа и типа. Я хочу иметь график (который является моим графиком выполнения). Я могу избавиться от HList для параметров, но я потеряю информацию о типе!

+0

Трудно сказать, что вы пытаетесь сделать здесь. Можете ли вы минимизировать это и предоставить фактическое сообщение об ошибке. –

+0

@TravisBrown Я добавил несколько подробностей и ошибок. Извините, я действительно не знал, какую часть я должен удалить, чтобы сделать его более понятным, но я надеюсь, что добавленная часть может его прояснить. – Omid

+0

Это выглядит из [здесь] (http://www.scala-graph.org/api/core/api/index.html#scalax.collection.edge.Implicits$$LDiEdgeAssoc) и сообщение об ошибке, которое вы получаете LUB «Arg :: HNil» и «Arg :: Arg :: HNil», что не имеет ничего общего. Что вы ожидаете от 'SimplePlan'? –

ответ

1

У вас общая проблема при работе с бесформенными: каждый HList имеет другой тип, и очень сложно не потерять эти типы в коде, который не думал о HList в его концепции.

Вы строите два предиката, тот, который предикат [Arg :: Arg :: Nil, TypeLike], а другое, который предикат [Arg :: Nil, TypeLike]

Определения графика выглядит следующим образом:

trait Graph[N, E[X] <: EdgeLikeIn[X]] 

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

Если вы задаетесь вопросом, почему они несовместимы, подумайте об этом: Один из ваших параметров - это функция, имеющая конкретную форму HList и возвращающую TypeLike. Он НЕ принимает HList. Та же самая особенность HList, которая гарантирует, что вы должны соответствовать своей форме при вызове функции, то же самое, что делает невозможным говорить о Predicates в целом, как в обычной коллекции, что и делает Graph.

Вы можете проверить, что это так, изменив код немного, и сделать несколько типов явным:

val x = Graph((p1 ~+> p1)("booo")) 
val p = SimplePlan[Arg::Arg::HNil, 
      TypeLike,Predicate[Arg::Arg::HNil,TypeLike]](x) 

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

Мы можем сделать работу вывода типа более конкретным в определении SimplePlan. Поскольку у вас есть только один тип предикате N <: предиката [A, B] на самом деле не выполнения ничего для вас, так что вместо этого мы можем написать

case class SimplePlan[A<:HList, B<:TypeLike](plan:Graph[Predicate[A,B],LDiEdge]) 

, который работает так же для образца кода. Тогда

val x = Graph((p1 ~+> p1)("booo")) 
val p = SimplePlan(x) 

компилирует прямо, и обеспечивает более описательную ошибку, когда вы делаете край перейти от p1 до p2.

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

Вы можете перенести предикат таким образом, который стирает тип HList, а затем помещает его в график, но результат все еще стирает типы до того, как они попадут в SimplePlan.

Возможно, если вы предоставите более подробную информацию о том, что вы пытаетесь сделать, мы можем помочь вам лучше?

+0

спасибо за внимание, я добавил еще одно резюме, пожалуйста, дайте мне знать, если у вас есть какие-либо вопросы. – Omid

+0

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

+0

Каким будет ваш способ использовать отражение? – Omid

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