Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 将额外参数传递给多态函数?_Scala_Shapeless - Fatal编程技术网

Scala 将额外参数传递给多态函数?

Scala 将额外参数传递给多态函数?,scala,shapeless,Scala,Shapeless,我有一个多态函数,可以将列表转换为集合: import shapeless.PolyDefns.~> import shapeless._ val lists = List(1,2) :: List("A", "B") :: List(1.1, 2.2) :: HNil object sss extends (List ~> Set) { def apply[T](l:List[T]):Set[T] = { l.toSet } } lists.map(sss)

我有一个多态函数,可以将列表转换为集合:

import shapeless.PolyDefns.~>
import shapeless._

val lists = List(1,2) :: List("A", "B") :: List(1.1, 2.2) :: HNil

object sss extends (List ~> Set) {
  def apply[T](l:List[T]):Set[T] = {
    l.toSet
  }
}

lists.map(sss) // I want: Set(1,2) :: Set("A", "B") :: Set(1.1, 2.2) :: HNil
但是如果我想改变这个函数的行为呢?我现在想添加一个额外的参数,它将指定输入列表中的哪个项应该放入集合中。这里有一个不正确的语法-你能告诉我正确的方法吗

object sss extends (List ~> Set) { // Compiler says no!
  def apply[T](i:Int)(l:List[T]):Set[T] = {
    l.slice(i,i+1).toSet
  }
}

我认为这是失败的,因为附加参数使它不再适合List~>集的签名,所以我如何克服这一点?

正如您已经指出的,您不能更改多态函数的签名。但可以动态创建您的函数:

类sss(i:Int)扩展(列表~>Set){ def应用[T](l:列表[T]):设置[T]={ l、 切片(i,i+1)。toSet } } val sss1=新sss(1) lists.map(sss1)//Set(2)::Set(B)::Set(2.2)::HNil
对于参数化多边形,有两种变通方法,另一个答案中提到了其中一种,尽管那里的确切实现不起作用。相反,您需要这样做:

import shapeless._, shapeless.poly.~>

val lists = List(1, 2) :: List("A", "B") :: List(1.1, 2.2) :: HNil

class sss(i: Int) extends (List ~> Set) {
  def apply[T](l: List[T]): Set[T] = l.slice(i, i+1).toSet
}

object sss1 extends sss(1)

lists.map(sss1)
…其中,
sss1
被定义为对象(而不是
val
)这一事实对于编译最后一行是必要的

这种方法可以编译,但不可能在很多上下文中使用它,例如,在hlist类型为泛型的方法中,不能定义
sss1
(或其他)对象

这里有一个我以前使用过的稍微混乱但更灵活的解决方法:

import shapeless._

val lists = List(1, 2) :: List("A", "B") :: List(1.1, 2.2) :: HNil

object sss extends Poly2 {
  implicit def withI[T]: Case.Aux[List[T], Int, Set[T]] =
    at((l, i) => l.slice(i, i + 1).toSet)
}

lists.zipWith(lists.mapConst(1))(sss)
// Set(2) :: Set(B) :: Set(2.2) :: HNil

现在,您可以实际编写一个方法,该方法采用了泛型
L,但出现了一些错误:
//我想要:1::“a”::3.5::HNil
更正,谢谢!除非您将
sss1
作为一个对象(出于相当神秘的原因),否则这不起作用。奇怪的是,它在我的测试用例中起作用(如果我创建一个
val
来保存实例)。“不过,这两种方法都不是很优雅,我个人倾向于避免使用Poly。大多数时候,定义自定义类型类几乎会更干净,而且在许多情况下都是必需的。”-你能给我指出这个替代实现吗?