Programming languages 哈斯克尔';s TypeClasses和Go';s接口

Programming languages 哈斯克尔';s TypeClasses和Go';s接口,programming-languages,haskell,interface,go,typeclass,Programming Languages,Haskell,Interface,Go,Typeclass,Haskell的TypeClass和Go的接口有什么相似之处和不同之处?这两种方法的相对优缺点是什么?看起来像是Go接口,就像Haskell中的单参数类型类(构造函数类) 方法与接口类型关联 对象(特定类型)可能具有该接口的实现 我不清楚Go是否以任何方式通过接口支持有界多态性,这是类型类的主要用途。也就是说,在Haskell中,接口方法可以用于不同的类型 class I a where put :: a -> IO () get :: IO a instance I

Haskell的TypeClass和Go的接口有什么相似之处和不同之处?这两种方法的相对优缺点是什么?

看起来像是Go接口,就像Haskell中的单参数类型类(构造函数类)

  • 方法与接口类型关联
  • 对象(特定类型)可能具有该接口的实现
我不清楚Go是否以任何方式通过接口支持有界多态性,这是类型类的主要用途。也就是说,在Haskell中,接口方法可以用于不同的类型

class I a where
    put :: a -> IO ()
    get :: IO a

instance I Int where
    ...

instance I Double where
    ....
所以我的问题是Go是否支持类型多态性。如果不是,它们根本就不像类型类。而且它们并不具有可比性

Haskell的类型类允许通过“泛型”(更高级的多态性)对代码进行强大的重用,这是一个很好的参考

通过类型类的特殊多态性或有界多态性是。这是Haskell中类型类的主要用途,并且没有通过Go接口来处理,这意味着它们实际上并不十分相似。接口的功能相对较弱,这是一种零阶类型的类

  • 在haskell中,类型类实例化是显式的(即,要使Bar成为Foo的实例,必须说
    instance Foo Bar
    ),而在go中实现接口是隐式的(也就是说,当您定义一个定义了正确方法的类时,它会自动实现相应的接口,而不必说类似
    implementInterfaceName
  • 接口只能描述接口实例是接收方的方法。在typeclass中,实例化类型可以出现在任何参数位置或函数的返回类型(也就是说,如果Foo是Bar类型的实例,那么必须有一个名为baz的函数,它接受一个Int并返回一个Foo——对于接口,你不能这么说)

  • 非常表面的相似性,Go的接口更像OCaml中的结构子类型。

    我将补充Don Stewart的优秀回答,Haskell类型类的一个令人惊讶的结果是,您可以在编译时使用逻辑编程生成任意多个类实例。(Haskell的类型类系统包括Prolog的一个有效的无割子集,非常类似于Datalog。)该系统在QuickCheck库中得到了极大的利用。或者,对于一个非常简单的示例,您可以看到如何定义。我怀疑此功能是类型类系统的意外结果,但事实证明它非常强大


    Go没有类似的东西。

    (它没有进入C++0x)类似于Haskell类型的类。还有“公理”它们在Haskell中根本不存在。它们可以让你形式化monad定律之类的东西。

    多态性的缺乏严重限制了Go接口与类型类的关联程度。我要说的是,如果实例方法中没有多态性,它们就没有真正的关联,而只是表面上的关联。人们正在问这个问题表明它们显然是相关的。我要说的是,Go接口是Haskell的TypeClass提供的严格子集。例如,在Go中可以做的一切在Haskell中都是可能的(甚至是微不足道的),但反过来就不是真的。我不确定你想如何将类型“Bar”作为一个要求。通常你有一个“类型类的实例”它要求类型实例为特定类型。但类型类本身仅包含占位符(“未来”类型类实例)没有绑定到特定类型。Go的接口不同之处在于,它们隐式绑定到类型,而Haskell类型类必须实例化/显式实现。实际上,两者之间的唯一关系似乎是,在这两种情况下,“方法”都独立于“类”而存在。就是这样。Go的接口支持“有界多态性”,正如Wikipedia那篇文章所严格定义的那样,因为只需在函数签名中命名所需的接口。例如,如果我写“func foo(a,b IBar)”,然后编译器确保我只能传入支持IBar的结构。然而,Haskell的类型类支持非结构类型,甚至复合绑定(例如,func-foo(a,b(IBar&&IBaz))在Go中是非法的,但是(IBar a,IBaz a=>foo::a->b->完全合法)。您必须在Go中创建一个复合接口才能执行类似的操作(vis.io.ReadCloser)。采用单一方法
    接口的API可以重新编写为采用函数类型。请参阅。