我想定义一个这样的类:
class MyClass[C,X](
val states: C,
val transform: C => X
)
但X
只能等于C
或C
的容器,例如List[C]
或Set[C]
- 它对于如果将X
定义为其他任何内容,则会出现问题。
有没有办法在Scala中强加这个限制?
答案 0 :(得分:2)
你可以尝试
import scala.language.higherKinds
class MyClass[C, F[_]](
val states: C,
val transform: C => F[C]
)
type Id[A] = A
new MyClass[Int, Set](1, Set(_)) // Set[Int] is a container for Int
new MyClass[String, List]("a", List(_)) // List[String] is a container for String
new MyClass[Boolean, Id](true, x => x) // Id[Boolean] is Boolean itself
答案 1 :(得分:1)
修改强>
假设XY问题。现在这个帖子有两个答案:
X
<强>子类的溶液强>
如果你跑
List(List(0), Set(0))
解释器中的,您会看到List
和Set
仅在Iterable
统一。
因此,您可以做出的最具体的限制是:
import scala.language.higherKinds
class MyClass[C, Container[X] <: collection.immutable.Iterable[X]] (
val states: C,
val transform: C => Container[C]
)
我不建议让它这个通用。如果有疑问,请先取List
,只有在实际必要时才进行概括。
<强>类型类的溶液强>
从你的评论中看,它看起来好像是一个XY问题,你真正想要的是一个具有适当类型类的类型构造函数F
。
首先定义你的类型类,例如使用一个sholud能够遍历F
的约束:
trait MyTC[F[_]] {
def hasIterator[X](fx: F[X]): Iterator[X]
}
然后为具有类型类实例的任意MyClass
定义F
:
class MyClass[X, F[_] : MyTC] {
val states: X
val transform: X => F[X]
}
然后只需为MyTC
,List
或Set
定义Id
的实例:
implicit object ListMyTC extends MyTC[List] {
def hasIterator[X](lx: List[X]): Iterator[X] = lx.iterator
}
type Id[X] = X
implicit object ListMyTC extends MyTC[Id] {
def hasIterator[X](x: X): Iterator[X] = Iterator(x)
}
然后您可以将MyClass
与List
或Id
一起使用:
val m1 = new MyClass[Int, List] { ... } // Integer states, transforms to List
val m2 = new MyClass[String, Id] { ... } // String-labeled states, transforms to other `String`
等
这个想法主要是用一个内涵定义来替换你扩展枚举你认为你的构造可能起作用的所有容器类型的尝试,它接受任何F
可以证明它满足{的所有要求。 {1}}通过提供MyTC
。