我今天偶然发现了一个小问题。考虑一个小包装类:
class Event<T> {
T value;
Class<T> type;
// other fields, getters and setters omitted for brevity
}
现在我想转换 Event<Long>
进入 Event<String>
同时保留其他字段并更新 type
成员(member)。
最终我得到了最简单的“解决方案”:
Event<String> new = new Event(old.getValue().toString(), String.class, other, fields);
然而,在我的宠物项目中使用 Haskell,我自然渴望像 fmap :: Functor f => (a -> b) -> f a -> f b
这样的函数。 (阅读:给定一个从 a 到 b 的函数和一个包含 a 类型的东西的仿函数给我一个包含 b 的结果)并且在发现没有标准实现之后我开始自己写一个:
interface Functor<T> {
Functor<S> fmap( Func1<T,S> f );
}
// ... in Event<T>:
Functor<S> fmap( Func1<T,S> f ) {
S newValue = f.call(this.value);
return new Event( newValue, newValue.getClass(), other, fields);
}
现在这个解决方案有一个问题:在 Java 中调用 fmap 之后,我剩下一个类型为 Functor<String>
的实例。而 Haskell 中的相同函数将返回 Event<String>
.
有没有办法得到我的Event
返回(没有不安全地转换它)?
最佳答案
不,这是不可能的。为此,我们需要对界面中的 Functor
进行抽象,例如
interface Functor<T> as F<T> {
F<S> map(f : Function<T, S>);
}
但 Java 不允许您抽象类型构造函数,只是类型。这称为高级类型 (HKT)。只有少数(非依赖)语言有 HKT,Scala 和 Haskell 是我能想到的仅有的两种。
其实HKTs是表达很多抽象的必要条件,
- Control.Monad
- 控制.应用
- Data.Traversable
- Data.Foldable
- Control.Monad.Trans
- 任何 monad 转换器,句号
- 免费单子(monad)
- 透镜/棱镜
- 流媒体库(它们是 monad 转换器)
category-extras
中的几乎所有内容
所有这些都涉及对类型构造函数的抽象,而不仅仅是具体类型。
关于java - 是否可以用 Java 实现 `Functor<T>`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22944661/