简体   繁体   English

Scala,类型不匹配问题和类型推断问题

[英]Scala, A type mismatch issue and type inference issue

I have the following code: 我有以下代码:

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])

(It was result of a question from: Here ) And I want to have: (这是来自这里的一个问题的结果),我想拥有:

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])

I get type mismatch and inferred type argument error on following code: 我在以下代码上得到类型不匹配和推断的类型实参错误:

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)
}

What exactly I have to add to solve the problem? 我到底要添加什么才能解决该问题? In case you want to have the dependencies: 如果您想拥有依赖项:

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: (more explanation) 编辑:(更多说明)

Predicate class is a class with a function "func" that can get variable number of arguments. 谓词类是具有函数“ func”的类,该函数可以获取可变数量的参数。 I implemented this using the question I asked earlier (the link is there) I can instantiate from the Predicate now, p1 and p2 . 我使用前面问过的问题(存在链接)实现了这一点,我现在可以从谓词p1p2实例化。 I have another class "SimplePlan" which has a member of a graph that I want its nodes to be a Predicate. 我还有另一个类“ SimplePlan”,该类具有一个图成员,我希望其节点为谓词。 But because I'm using HList in Predicate definition, type of each p1 and p2 are different. 但是因为我在Predicate定义中使用HList,所以每个p1p2的类型都不同。 I get type mismatch error on: 我收到以下类型的不匹配错误:

val p = SimplePlan(x)

I really don't know, how should I define SimplePlan to resolve this problem. 我真的不知道,我应该如何定义SimplePlan来解决此问题。 The exact error is: 确切的错误是:

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 (Explanation of what exactly I want): I need this for my research project, so what I want to do could be a little bit weird. 编辑2 (我确切想要的解释):我的研究项目需要这个,所以我想做的可能有点奇怪。 I want to have a predicate class that has a function in it with different number and type parameters. 我想有一个谓词类,其中有一个具有不同数字和类型参数的函数。 I want to have a graph (which is my execution graph). 我想要一个图(这是我的执行图)。 I can get rid of HList for parameters but I will loose type information! 我可以摆脱HList的参数,但我会丢失类型信息!

You are having a common problem when dealing with shapeless: Each HList has a different type, and it's very tricky to not lose those types in code that wasn't thinking of HLists in its conception. 在处理无形状时,您经常遇到一个问题:每个HList都有一个不同的类型,并且要避免在概念中没有考虑到HLists的代码中丢失这些类型,这非常棘手。

You build two predicates, one that is Predicate[Arg::Arg::Nil,TypeLike], and another that is Predicate[Arg::Nil,TypeLike] 您建立两个谓词,一个是Predicate [Arg :: Arg :: Nil,TypeLike],另一个是Predicate [Arg :: Nil,TypeLike]

The definition of Graph looks like this: Graph的定义如下所示:

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

Notice that Graph does not have any variance: It's asking for one specific type, and you have two incompatible types, so it cannot compile. 请注意,Graph没有任何差异:它要求一种特定类型,并且您具有两种不兼容的类型,因此无法编译。

If you wonder why they are incompatible, think about this: One of your parameters is a function, taking a specific HList shape, and returning a TypeLike. 如果您想知道为什么它们不兼容,请考虑以下问题:您的参数之一是一个函数,采用特定的HList形状并返回TypeLike。 It does NOT take any HList. 它不需要任何HList。 The same feature of HList that makes sure you have to match its shape when calling the function is the same that makes it impossible to talk about Predicates generically, like in a regular collection, which is what Graph is actually doing. HList的相同功能(确保您在调用函数时必须匹配其形状)相同,因此无法像一般规则集合中一般地讨论谓词,这是Graph实际上正在做的事情。

You can test that this is the case by changing your code a little, and making a couple of types explicit: 您可以通过稍微更改代码并明确几个类型来测试这种情况:

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

It fails if I do not specify the types: Scala type inference has its limitations. 如果我不指定类型,它将失败:Scala类型推断有其局限性。 It's also not what you want to do either, because you do not want all your predicates to have the same shape. 这也不是您想要执行的操作,因为您不希望所有谓词都具有相同的形状。

We can make the type inference work by being a bit more specific in the definition of SimplePlan. 我们可以通过在SimplePlan的定义中更具体一些来使类型推断起作用。 Since you only have one Predicate type, the N <:Predicate[A,B] is not really accomplishing anything for you, so instead we can write 由于您只有一个谓词类型,因此N <:Predicate [A,B]并不能真正为您完成任何事情,因此我们可以编写

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

Which works just the same for your sample code. 对于您的示例代码,它们的工作原理相同。 Then 然后

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

compiles outright, and provides a more descriptive error when you make the edge go from p1 to p2. 完全编译,并在使边缘从p1变为p2时提供更具描述性的错误。

The way to solve your problem really depends on what you are trying to do with this data structure. 解决问题的方法实际上取决于您要使用此数据结构做什么。 If what you are trying is to recover the exact types without reflection after you put a Predicate into the Graph, I am sad to say that I do not see how that is even possible, as Graph will not keep your specific types: Graph is a container, and is not any more capable of keeping types as a regular List would. 如果你正在尝试是恢复的确切类型,而反射你把一个谓语到图表后,我很伤心地说,我看不出这甚至有可能,因为图形不会让你的特定类型:图形是容器,并且不再能够像常规List一样保留类型。

You could wrap predicate in a way that erases the HList type, and then put that into the graph, but the result is still erasing the types before they get into the SimplePlan. 您可以以消除HList类型的方式包装谓词,然后将其放入图形中,但是结果仍然是在将这些类型放入SimplePlan之前将其擦除。

Maybe if you provide more details on what you attempt to do, we can help you better? 也许如果您提供有关您尝试做的事情的更多详细信息,我们可以为您提供更好的帮助吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM