Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.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
Generics Haskell与Java';什么是奇怪的重复出现的通用模式?_Generics_Haskell_Types - Fatal编程技术网

Generics Haskell与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中一个或两个例子的等价物

刚刚出现了一个关于java泛型的问题。示例代码为:

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 = (+) }