数组[字节]不接受类型参数

时间:2017-11-12 12:22:47

标签: scala haskell

在Haskell中,我可以将参数约束到类型类,例如:

Prelude> f x y = x * y
Prelude> :t f
f :: Num a => a -> a -> a

我试图在Scala中做同样的事情,如下所示:

def sendMessage[A: Array[Byte], B: Array[Byte]](producer: Eval[KafkaProducer[A, B]])(pr: Eval[ProducerRecord[A, B]]) =  

但是编译器抱怨道:

[error] /home/developer/Desktop/scala/PureProducer/src/main/scala/TheProducer.scala:39:20: Array[Byte] does not take type parameters
[error]   def sendMessage[A: Array[Byte], B: Array[Byte]](producer: Eval[KafkaProducer[A, B]])(pr: Eval[ProducerRecord[A, B]]) =  

如何在Scala中约束类型参数?

2 个答案:

答案 0 :(得分:5)

在Scala中,类类表示为通用特征,其实例作为隐式参数传递。作为示例,请使用以下Haskell类型类:

class Foo a where
    foo :: a
    bar :: a -> a -> a

f :: Foo a => a -> a
f x = bar foo x

instance Foo Int where
    foo = 42
    bar x y = x + y

f 23 -- Result: 42 + 23 = 65

Scala等价物看起来像这样:

// class Foo a
trait Foo[A] {
    def foo: A
    def bar(x: A, y: A): A
}

def f[A](x: A)(implicit foo: Foo[A]) = foo.bar(foo.foo, x)

// instance Foo Int
implicit case object FooInt extends Foo[Int] {
    def foo = 42
    def bar(x: Int, y: Int) = x + y
}

f(23) // Result: 42 + 23 = 65

还有一个定义隐式参数的快捷方式:def f[A: Foo](x: A)def f[A](x: A)(implicit _unnamed: Foo[A])的缩写。但是,这意味着您无法直接在正文中访问类型类的实例(因为您没有给它起一个名字),所以只有当您所做的只是通过时,它才有用。键入类实例到其他方法(可以隐式完成,因此不需要名称)。

在Scala中,Num类型类称为Numeric,它提供plustimes等方法。因此,为了做与Haskell示例相同的事情,您可以写:

def f[A](x: A, y: A)(implicit num: Numeric[A]) = num.times(x,y)

Array[Byte]尝试失败的原因是因为Array[Byte]不是类型类。具体来说,A: Array[Byte]缩写扩展到:

def sendMessage[A, B](producer: Eval[KafkaProducer[A, B]])(pr: Eval[ProducerRecord[A, B]])(implicit _unamed1: Array[Byte][A], implicit _unnamed2: Array[Byte][B])

看看应该清楚为什么这不起作用:Array[Byte][A]没有任何意义。

根据您的评论,您只想避免多次写Array[Byte]。这与类型类没有任何关系(在Haskell和Scala中都没有)。您可以简单地使用类型别名。

答案 1 :(得分:0)

如果你知道总是接受一个数组,只是约束内部类型,并且类型是相等的,所以你只需要一个类型变量,然后你想要成为子类型的类型,我不确定Byte是否可以被分类如此:

def sendMessage[A<:YourClass](producer: Eval[KafkaProducer[Array [A]])(pr: Eval[KafkaProducer[Array [A]]) =...

但我认为你可以做你的情况:

def sendMessage(producer: Eval[KafkaProducer[Array [Byte]])(pr: Eval[KafkaProducer[Array [Byte]]) =...