我正在尝试在java中编写一些函子,monad和applicatives。我发现了一些并选择了下面的那个。
在术语类别理论中,什么是get()返回?
单位()似乎是某种身份,但是从什么到什么?或许这是一个构造函数?
我看到一个带有get()的仿函数的定义。这会回来什么?
abstract class Functor6<F,T> {
protected abstract <U> Function<? extends Functor6<F,T>,? extends Functor6<?,U>> fmap(Function<T,U> f);
}
abstract class Applicative<F,T>extends Functor6<F,T> {
public abstract <U> U get(); // what is this in terms of category theory?
protected abstract <U> Applicative<?,U> unit(U value); // what is this in terms of category theory?
protected final <U> Function<Applicative<F,T>,Applicative<?,U>> apply(final Applicative<Function<T,U>,U> ff) {
return new Function<Applicative<F,T>,Applicative<?,U>>() {
public Applicative<?,U> apply(Applicative<F,T> ft) {
Function<T,U> f=ff.get();
T t=ft.get();
return unit(f.apply(t));
}
};
}
}
答案 0 :(得分:2)
一些Haskell可能有所帮助。首先是一个仿函数:
class Functor f where
fmap :: (a -> b) -> f a -> f b
我们可以这样说,如果类型f
是Functor
,那么必须有fmap
函数,该函数采用a -> b
类型的函数和值oif类型f a
以产生f b
。即该类型允许将函数应用于其中的值。
Java不支持更高级的类型,如上所述定义一个仿函数类型,所以我们必须近似它:
interface Functor6<F, T> {
<U> Function<? extends Functor6<F, T>, ? extends Functor6<?, U>> fmap(Function<T, U> f);
}
这里泛型类型参数F
是Functor类型,相当于Haskell定义中的f
,而T
是包含的类型(就像U
),相当于Haskell定义中的a
(和b
)。在没有HKT的情况下,我们必须使用通配符来引用仿函数类型(? extends Functor6<F, T>
)。
接下来,申请人:
class (Functor f) => Applicative f where
pure :: a -> f a
<*> :: f (a -> b) -> f a -> f b
即,类型f
是一个应用程序,它必须是一个仿函数,有一个pure
操作,它将一个值提升为applicative f
,以及一个apply操作({ {1}}),在<*>
内部有一个函数(a -> b
),f
内有一个a
,可以将该函数应用于该值以产生{在f
内部{1}}。
这是您的Java等价物,使用某些Java 8功能进行了简化,并修正了一些类型:
b
如果我们逐行采取:
f
说申请人是一个玩家。这样:
interface Applicative<F, T> extends Functor6<F, T> {
T get();
<F, U> Applicative<F, U> unit(U value);
default <U> Function<Applicative<F, T>, Applicative<F, U>> apply(Applicative<?, Function<T, U>> ff) {
return ft -> {
Function<T, U> f = ff.get();
T t = ft.get();
return unit(f.apply(t));
};
}
}
似乎是一种获取应用程序中的值的方法。这可能适用于特定情况,但一般不起作用。这样:
interface Applicative<F, T> extends Functor6<F, T> {
应该等同于Haskell定义中的 T get();
函数。它应该是静态的,否则你需要一个应用值才能调用它,但是使它静态会阻止它在实际的应用实现中被覆盖。在Java中没有简单的方法来解决这个问题。
然后你有 <F, U> Applicative<F, U> unit(U value);
方法,其权限应该等同于Haskell中的pure
。正如我们所看到的那样,它只是从applicative和它的参数中获取函数apply
,并返回一个包含将函数应用于参数的结果的应用程序。
这是车轮真正脱落的地方。应用程序如何将函数应用于值的详细信息对于每个应用程序都是特定的,不能像这样推广。
简而言之,这种做法是错误的。这并不是说你不能用Java实现applicative functor - 你可以而且它很容易,但你不能做的就是在语言中说明它们是应用程序,就像你在Haskell中所做的那样(使用类型类)。