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和UnionType_Scala_Scalaz - Fatal编程技术网

绑定到泛型类型的Scala和UnionType

绑定到泛型类型的Scala和UnionType,scala,scalaz,Scala,Scalaz,情景: 我们有不同的类A,B,C,它们没有公共基类,但它们都提供了一个方法foo,该方法接受一个与类本身类型相同的参数,并返回一个类型为Boolean的值 然后我们想提出一个相当复杂的方法bar,它接受三个参数,这三个参数都应该是相同的类型,即所有三个参数都是a,或者B,或者C,但不是它们的混合 想法(未编译): 但由于这是一个相当复杂的方法,我不想重复代码 我曾希望scalaz中的UnionTypes在这种情况下会有所帮助,但我得到了一个编译时错误。有人知道如何解决这个问题吗?使用: 你为什么

情景:

我们有不同的类
A
B
C
,它们没有公共基类,但它们都提供了一个方法
foo
,该方法接受一个与类本身类型相同的参数,并返回一个类型为
Boolean
的值

然后我们想提出一个相当复杂的方法
bar
,它接受三个参数,这三个参数都应该是相同的类型,即所有三个参数都是
a
,或者
B
,或者
C
,但不是它们的混合

想法(未编译):

但由于这是一个相当复杂的方法,我不想重复代码

我曾希望scalaz中的UnionTypes在这种情况下会有所帮助,但我得到了一个编译时错误。有人知道如何解决这个问题吗?

使用:


你为什么称之为模式?:)@ErikAllik这不是一种模式,而是一种模式的应用。如果你问为什么类型类模式被认为是一种模式,那是因为它符合定义:)例如,Haskell类型类是语言的一流部分;在Scala中,每次都必须从以相似方式排列的相似部分对它们进行编码。
import scalaz.UnionTypes._

class A { def foo(y: A): Boolean = ??? }
class B { def foo(y: B): Boolean = ??? }
class C { def foo(y: C): Boolean = ??? }

class Foo {

  type T <: t[A]#t[B]#t[C]

  def bar(x: T, y: T, z: T) = x.foo(y) && y.foo(z) // do more complex stuff
}
def bar(x: A, y: A, z: A) = x.foo(y) && y.foo(z) // do more complex stuff
def bar(x: B, y: B, z: B) = x.foo(y) && y.foo(z) // do more complex stuff
def bar(x: C, y: c, z: C) = x.foo(y) && y.foo(z) // do more complex stuff
trait CanFoo[T] {
  def foo(x: T, y: T): Boolean
}

object CanFoo {
  implicit val ACanFoo: CanFoo[A] = new CanFoo[A] {
    def foo(x: A, y: A) = x.foo(y)
  }

  // similar definitions for B and C
}

class Foo {
  def bar[T](x: T, y: T, z: T)(implicit canFoo: CanFoo[T]) = 
    canFoo.foo(x, y) && canFoo.foo(y, z)
}