Generics Haskell与Java';什么是奇怪的重复出现的通用模式?
刚刚出现了一个关于java泛型的问题。示例代码为:Generics Haskell与Java';什么是奇怪的重复出现的通用模式?,generics,haskell,types,Generics,Haskell,Types,刚刚出现了一个关于java泛型的问题。示例代码为: public interface A < T extends A < T> > { } 公共接口A{ } 一个相关的问题询问 Class Enum<E extends Enum<E>> ... 类枚举。。。 当我试图阅读关于这些类型的泛型表达式的java文档时,我的眼睛呆滞了,对我来说是希腊语 我希望我能用Haskell的等效术语来理解它们 Haskell中一个或两个例子的等价物
public interface A < T extends A < T> > {
}
公共接口A>{
}
一个相关的问题询问
Class Enum<E extends Enum<E>> ...
类枚举。。。
当我试图阅读关于这些类型的泛型表达式的java文档时,我的眼睛呆滞了,对我来说是希腊语
我希望我能用Haskell的等效术语来理解它们
Haskell中一个或两个例子的等价物(或类似物)是什么?我不知道Haskell是否有等价的陈述,但Haskell确实有。例如,Show是一个类型类,许多对象“扩展”或“实现”Show,也就是说,您可以“Show 3”、“Show[1,2,3,4]”等。此技巧用于允许接口引用具体的实现类型,例如,要强制参数的类型和结果的类型与实现类的类型相同,如下所示:
公共接口编号{
A添加(其他);
}
这与您在Haskell中免费获得的类型类类似:
class Num a其中
(+)::a->a->a
这很有趣,因为这也让我感到困惑。让我们尝试对其进行建模。我可能不会以这个习语在Java中的用途结束
如果一个类型a
继承自一个类型B
,那么在功能区,这意味着存在一个功能B->a
。此时不要担心类和接口之间的差异;功能翻译几乎没有什么不同(接口只是功能的记录)。让我们做一个非递归的翻译来感受它:
interface Showable {
string show();
}
interface Describer<T extends Showable> { }
如果我们忘记了向下转换,那么如果我们在Java中有一些对象,我们所知道的只是它是一个可显示的
,那么它对应于在Haskell中有一个可显示的
对象。从表面上看,传递一个Showable
和传递一个string
感觉是不同的,但它们是等价的
扩展可显示的
约束进入,如果我们有一个描述符t
,那么我们知道t
“是”可显示的
;i、 e.存在一个函数t->Showable
makeDescriber :: (t -> Showable) -> Describer t
makeDescriber f = Describer { showable = f }
现在,让我们去哈马尔的埃克斯马普酒店,这里有多态性
interface Number<A extends Number<A>> {
A add(A other);
}
所以现在如果我们有一个数字a
,那么我们知道a
“是一个数字a
;i、 e.有一个函数a->Number a
java接口的实例Number
成为类型上的函数
intNumber :: Integer -> Number Integer
intNumber x = Number { add = \y -> x + y, number = intNumber }
此函数对应于一个类整数扩展数
。如果我们有两个整数x
和y
,我们可以使用这种“OO”样式添加它们:
那么泛型函数呢:
T Add< T extends Number<T> >(T x, T y) { return x.add(y); }
当然,在Haskell中,我们看到将对象与其支持的操作捆绑在一起是多么复杂,因此我们更愿意将它们分开:
data Num t = Num { add :: t -> t -> t }
add' :: Num t -> t -> t -> t
add' n x y = add n x y
我们用实际操作实例化Num
字典,例如
integerNum :: Num Integer
integerNum = Num { add = (+) }
类型类只是后一种思想的一点语法甜点
也许有帮助?我只是想看看它是如何逐字翻译的。你无法真正比较命令式语言和函数式语言。它们只是不能很好地相互转换。@marcof——这不是关于FP与命令的关系,而是关于类型系统。我读过(但忘了是从哪里)Java从Haskell的类型系统中获得了泛型类型的灵感,我想(也希望)我对Haskell的理解更好一些。Haskell没有子类型,因此,很难用Haskell来解释Java的
extends
关键字的细微差别。让我感到困惑的是T扩展了
——所以基本上,这甚至没有出现在Haskell版本中?酷!parametric polymorphics
是正确的术语吗?这实际上并不等同,因为Java版本允许我定义类型Foo implements Num
,而Haskell版本只允许Foo implements Num
@sepp2k:是的,这是一个近似值。我不认为在Java中可以得到与Haskell模式相当的版本。@sepp2k您可以做到,但这种Java模式的典型用法似乎是实现hammar所描述的功能。@MattFenwick参数多态性
引用了所有泛型。也就是说,每当你看到Foo
时,这意味着Foo
通过参数化是多态的。+1尽管最后一部分不清楚。实际添加发生在Num t
中的什么位置?为什么要首先定义它?@is7s添加了Num Integer
的实例化。
T Add< T extends Number<T> >(T x, T y) { return x.add(y); }
add' :: (t -> Number t) -> t -> t -> t
add' n x y = n x `add` y
data Num t = Num { add :: t -> t -> t }
add' :: Num t -> t -> t -> t
add' n x y = add n x y
integerNum :: Num Integer
integerNum = Num { add = (+) }