Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.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高级类型:can';t定义在不同集合上工作的泛型函数_Scala_Generics_Higher Kinded Types - Fatal编程技术网

Scala高级类型:can';t定义在不同集合上工作的泛型函数

Scala高级类型:can';t定义在不同集合上工作的泛型函数,scala,generics,higher-kinded-types,Scala,Generics,Higher Kinded Types,我使用的是Scala 2.10.2 我需要一个函数 def extractEither(m: M[(Key, Either[TLeft, TRight])]) : Either[TLeft, M[(Key, TRight)]] 其中M可以是Seq、List、Map或其他任何内容,返回类型仍然合适 我使用以下内容进行测试: val map = Map(1 -> Left("foo"), 2 -> Right('bar), 3 -> Right('baz)) 我目前的尝试如下:

我使用的是Scala 2.10.2

我需要一个函数

def extractEither(m: M[(Key, Either[TLeft, TRight])])
: Either[TLeft, M[(Key, TRight)]]
其中
M
可以是Seq、List、Map或其他任何内容,返回类型仍然合适

我使用以下内容进行测试:

val map = Map(1 -> Left("foo"), 2 -> Right('bar), 3 -> Right('baz))
我目前的尝试如下:

尝试#1

def extractEither[
  Key, TLeft, TRight, M[_] <: TraversableOnce[_]
]
(monad: M[(Key, Either[TLeft, TRight])])
(implicit cbf: CanBuildFrom[
M[(Key, Either[TLeft, TRight])],
  (Key, TRight),
  M[(Key, TRight)]
]): Either[TLeft, M[(Key, TRight)]] = {
  val builder = cbf(monad)
  builder.sizeHint(monad.size)
  (monad: GenTraversableOnce[_]).foreach { x =>
    val (key, either) = x.asInstanceOf[(Key, Either[TLeft, TRight])]
    either.fold(
      leftVal => return Left(leftVal),
      rightVal => builder += ((key, rightVal))
    )
  }
  Right(builder.result())
}
但这根本不是通用的:|


有人能解释一下如何正确地写这篇文章吗?

第一个解决方案就快到了,但您应该使用M[X]def extract[K,L,R,M[X] val(键,任意一个)=x 或者,折叠( leftVal=>返回左(leftVal), rightVal=>builder+=((键,rightVal)) )}) 右(builder.result()) } 警告:有1个功能警告;有关详细信息,请使用-feature重新运行 提取[K,L,R,M[X]val map=map(1->Left(“foo”),2->Right('bar),3->Right('baz)) map:scala.collection.immutable.map[Int,可以用scala.util序列化的产品。或者[String,Symbol]=map(1->Left(foo),2->Right('bar),3->Right('baz)) scala>ExtractOther(映射:TraversableOnce[(Int,或[String,Symbol])) res2:String,TraversableOnce[(Int,Symbol)]=Left(foo) scala>val map2:Map[Int,其中一个[String,Symbol]]=映射(1->Left(“foo”),2->Right('bar),3->Right('baz)) 映射2:Map[Int,或者[String,Symbol]]=Map(1->Left(foo),2->Right('bar),3->Right('baz)) scala>ExtractOri(地图2) res3:String,scala.collection.immutable.Iterable[(Int,Symbol)]=Left(foo)
第一种解决方案就快到了,但您应该使用M[X]def extract[K,L,R,M[X] val(键,任意一个)=x 或者,折叠( leftVal=>返回左(leftVal), rightVal=>builder+=((键,rightVal)) )}) 右(builder.result()) } 警告:有1个功能警告;有关详细信息,请使用-feature重新运行 提取[K,L,R,M[X]val map=map(1->Left(“foo”),2->Right('bar),3->Right('baz)) map:scala.collection.immutable.map[Int,可以用scala.util序列化的产品。或者[String,Symbol]=map(1->Left(foo),2->Right('bar),3->Right('baz)) scala>Extract(映射:TRAVERTABLEABLE ONE[(Int,或[String,Symbol])) res2:String,TraversableOnce[(Int,Symbol)]=Left(foo) scala>valmap2:Map[Int,或[String,Symbol]]=Map(1->Left(“foo”),2->Right('bar),3->Right('baz)) 映射2:Map[Int,或者[String,Symbol]]=Map(1->Left(foo),2->Right('bar),3->Right('baz)) scala>ExtractOri(地图2) res3:String,scala.collection.immutable.Iterable[(Int,Symbol)]=Left(foo)
首先,您不能有此签名:
def extractAther(m:m[(Key,other[TLeft,TRight]):other[TLeft,m[Key,TRight]]
,因为在结果类型中
m
接受两个类型参数,在参数列表中只有一个,
m
在您的情况下不能是单子,因为单子是一种
monad[F[\u]]
而你的
M
不是
M[\u]
就是
M[\uu,\u]
是的,对不起,它应该是
def extractOther(M:M[(Key,任择[TLeft,TRight]):任择[TLeft,M[(Key,TRight)]]
。也许monad这个名字不适合那里。我仍然不太确定它们是什么:)你看过吗?@MilesSabin有一些非常好的实现和你所追求的那种东西的例子。一开始你不能有这个签名:
def extractAther(m:m[(Key,other[TLeft,TRight]):other[TLeft,m[Key,TRight]]
,因为在结果类型
M
中有两个类型参数,在参数列表中只有一个,
M
在您的情况下不能是monad,因为monad是一种
monad[F[\u]]
而您的
M
或者
M[\u,\ u]
是的,对不起,它应该是
extracted def(M:M[(Key,或者是)[TLeft,TRight]):或[TLeft,M[(键,TRight)]]
。也许monad这个名字不适合这里。我仍然不太确定它们是什么:)你看过吗?@MilesSabin有一些非常好的实现和你所追求的那种东西的例子。谢谢。知道为什么它适合map2而不是Map吗?Map#Map是如何实现的吗?谢谢。知道为什么吗对于map2来说,它是可移植的,而不是地图?地图是如何实现的?
scala> extractEither(map)
<console>:20: error: no type parameters for method extractEither: (monad: M[(Key, Either[TLeft,TRight])])(implicit cbf: scala.collection.generic.CanBuildFrom[M[(Key, Either[TLeft,TRight])],(Key, TRight),M[(Key, TRight)]])Either[TLeft,M[(Key, TRight)]] exist so that it can be applied to arguments (scala.collection.immutable.Map[Int,Product with Serializable with scala.util.Either[String,Symbol]])
 --- because ---
argument expression's type is not compatible with formal parameter type;
 found   : scala.collection.immutable.Map[Int,Product with Serializable with scala.util.Either[String,Symbol]]
 required: ?M
              extractEither(map)
              ^
<console>:20: error: type mismatch;
 found   : scala.collection.immutable.Map[Int,Product with Serializable with scala.util.Either[String,Symbol]]
 required: M[(Key, Either[TLeft,TRight])]
              extractEither(map)
                            ^
<console>:20: error: Cannot construct a collection of type M[(Key, TRight)] with elements of type (Key, TRight) based on a collection of type M[(Key, Either[TLeft,TRight])].
              extractEither(map)
                           ^
def extractEither[
  Key, TLeft, TRight, M <: collection.Map[Key, Either[TLeft, TRight]]
](map: M): Either[TLeft, M] = {
  Right[TLeft, M](map.map { case (key, either) =>
    either.fold(
      leftVal => return Left(leftVal),
      rightVal => key -> rightVal
    )
  }.asInstanceOf[M])
}
scala> extractEither(map)
<console>:20: error: inferred type arguments [Nothing,Nothing,Nothing,scala.collection.immutable.Map[Int,Product with Serializable with scala.util.Either[String,Symbol]]] do not conform to method extractEither's type parameter bounds [Key,TLeft,TRight,M <: scala.collection.Map[Key,Either[TLeft,TRight]]]
              extractEither(map)
              ^
<console>:20: error: type mismatch;
 found   : scala.collection.immutable.Map[Int,Product with Serializable with scala.util.Either[String,Symbol]]
 required: M
              extractEither(map)
                            ^
  def extractEither[
    Key, TLeft, TRight
  ](map: Map[Key, Either[TLeft, TRight]]): Either[TLeft, Map[Key, TRight]] = {
    Right(map.map { case (key, either) =>
      either.fold(
        leftVal => return Left(leftVal),
        rightVal => key -> rightVal
      )
    })
  }
scala> def extractEither[K, L, R, M[X] <: TraversableOnce[X]](monad: M[(K, Either[L, R])])(implicit cbf: CanBuildFrom[M[(K, Either[L, R])], (K, R), M[(K, R)]]): Either[L, M[(K, R)]] = {
 val builder = cbf(monad)
 builder.sizeHint(monad.size)
 monad.foreach({x =>
 val (key, either) = x
 either.fold(
 leftVal => return Left(leftVal),
 rightVal => builder += ((key, rightVal))
 )})
 Right(builder.result())
 }
warning: there were 1 feature warning(s); re-run with -feature for details
extractEither: [K, L, R, M[X] <: TraversableOnce[X]](monad: M[(K, Either[L,R])])(implicit cbf: scala.collection.generic.CanBuildFrom[M[(K, Either[L,R])],(K, R),M[(K, R)]])Either[L,M[(K, R)]]

scala> val map = Map(1 -> Left("foo"), 2 -> Right('bar), 3 -> Right('baz))
map: scala.collection.immutable.Map[Int,Product with Serializable with scala.util.Either[String,Symbol]] = Map(1 -> Left(foo), 2 -> Right('bar), 3 -> Right('baz))

scala> extractEither(map: TraversableOnce[(Int, Either[String, Symbol])])
res2: Either[String,TraversableOnce[(Int, Symbol)]] = Left(foo)

scala> val map2: Map[Int, Either[String, Symbol]] = Map(1 -> Left("foo"), 2 -> Right('bar), 3 -> Right('baz))
map2: Map[Int,Either[String,Symbol]] = Map(1 -> Left(foo), 2 -> Right('bar), 3 -> Right('baz))

scala> extractEither(map2)
res3: Either[String,scala.collection.immutable.Iterable[(Int, Symbol)]] = Left(foo)