关于java泛型的question刚出现。示例代码是:
public interface A < T extends A < T> > {
}
链接的问题询问
Class Enum<E extends Enum<E>> ...
当我尝试阅读关于这些通用表达式的java文档时,我的眼睛瞪着它,这对我来说是希腊语。
我希望我能用Haskell等价物理解它们!
这些例子中的一个或两个在Haskell中的等价(或类似)是什么?
答案 0 :(得分:10)
这个技巧用于允许接口引用具体的实现类型,例如强制参数的类型和结果的类型与实现类的类型相同:
public interface Num<A extends Num<A>> {
A add(A other);
}
这类似于你在Haskell中使用类型类免费获得的内容:
class Num a where
(+) :: a -> a -> a
答案 1 :(得分:3)
这很有趣,因为这也使我感到困惑。我们试着去模拟它。我可能不会在Java中使用这个习惯用法。
如果类型A
继承自类型B
,则在功能域中表示存在函数B -> A
。此时不要担心类和接口之间的区别;功能翻译几乎没有区别(界面只是功能记录)。让我们做一个非递归的翻译来感受它:
interface Showable {
string show();
}
interface Describer<T extends Showable> { }
翻译成功能记录:
data Showable = Showable { show :: String }
data Describer t = Describer { showable :: t -> Showable }
如果我们忘记了向下转换,那么如果我们在Java中有一些对象,我们所知道的就是它是Showable
,那么它对应于在Haskell中有一个Showable
对象。从表面上看,传递Showable
并传递string
感觉就像是不同的东西,但它们是等价的。
extends Showable
约束输入,如果我们有Describer t
,那么我们知道t
“是”Showable
;即存在函数t -> Showable
。
makeDescriber :: (t -> Showable) -> Describer t
makeDescriber f = Describer { showable = f }
现在让我们来看看hammar的例子,并结合多态性。
interface Number<A extends Number<A>> {
A add(A other);
}
转换为功能记录
data Number a = Number {
add :: a -> a,
number :: a -> Number a
}
现在,如果我们有Number a
,那么我们知道a
“是”Number a
;即有一个函数a -> Number a
。
java接口Number
的实例成为类型上的函数。
intNumber :: Integer -> Number Integer
intNumber x = Number { add = \y -> x + y, number = intNumber }
此功能对应class Integer extends Number<Integer>
。如果我们有两个整数x
和y
,我们可以使用这种“OO”样式添加它们:
z :: Integer -> Integer -> Integer
z x y = intNumber x `add` y
通用功能怎么样:
T Add< T extends Number<T> >(T x, T y) { return x.add(y); }
(嗯是正确的Java语法?我对这种风格的体验来自C#)
记住约束成为函数,所以:
add' :: (t -> Number t) -> t -> t -> t
add' n x y = n 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 = (+) }
对于后一种想法,类型类只是一些语法糖。
也许这有帮助吗?我只想看看它是如何按字面翻译的。
答案 2 :(得分:-1)
我不知道是否存在Haskell的等效语句,但Haskell确实有typeclasses。例如,Show是一个类型类,很多对象“扩展”或“实现”显示,也就是说,你可以“显示3”,“显示[1,2,3,4]”等。