这是monad(在Java中)吗?
作者:互联网
在我声称自己已经钉牢之前,我想问一下.请不要退缩,我想首先在这里遇到任何批评.
由于Java缺乏动态语言传递任意参数所具有的灵活性,因此我通过将所有可能的输入捆绑到一个类(人)中来进行补偿,该类构成了输入空间.这些函数在monad的帮助下将其映射到输出空间(Friends).
我并不是要解决一般情况,只是想出一个例子来了解我是否了解设计模式.
单子(如果是这样)将执行以下规则:邀请被拒绝或出现错误后,将不再进行进一步处理.
对不起,长度.毕竟是Java.为了节省空间,我采用了一些约定的捷径.
这实际上是单子的例子吗? (封装在Friends类中)
public class Sample {
public static void main(String[] args) {
People people0 = new People("Bob", "Fred");
Friends friends0 = Friends.pipeline(people0, ToFromFunction.INVITE, ToFromFunction.ACCEPT);
System.err.println(friends0);
People people1 = new People("Bob", "Jenny");
Friends friends1 = Friends.pipeline(people1, ToFromFunction.INVITE, ToFromFunction.ACCEPT);
System.err.println(friends1);
People people2 = new People("Bob", "Fred");
Friends friends2 = Friends.pipeline(people2, ToFromFunction.INVITE, ToFromFunction.BLOCK);
System.err.println(friends2);
}
}
/** this is the space of all inputs */
public class People {
public People(String from, String to) {
this.from = from;
this.to = to;
}
public String from;
public String to;
}
/** this is the output space, and the monad (?) */
public class Friends {
public boolean friends = false;
public boolean rejected = false;
public String errors = "";
public static Friends unit(People from) {
return new Friends();
}
public Friends bind(ToFromFunction f, People from) {
if (! errors.isEmpty()) {
// we have errors; skip the rest
return this;
}
if (rejected) {
// No means no
return this;
}
return f.act(from, this);
}
public static Friends pipeline(People from, ToFromFunction... functions) {
Friends result = Friends.unit(from);
for (ToFromFunction f : functions) {
result = result.bind(f, from);
}
return result;
}
}
/** functions from People to Friends */
public interface ToFromFunction {
Friends act(People from, Friends to);
ToFromFunction INVITE = new ToFromFunction() {
public Friends act(People from, Friends to) {
// Jenny has blocked Bob
if ("Jenny".equals(from.to) && "Bob".equals(from.from)) {
to.errors = "Jenny blocked Bob";
}
return to;
}
};
ToFromFunction ACCEPT = new ToFromFunction() {
public Friends act(People from, Friends to) {
// Good to go!
to.friends = true;
return to;
}
};
ToFromFunction BLOCK = new ToFromFunction() {
public Friends act(People from, Friends to) {
to.friends = false;
to.rejected = true;
return to;
}
};
}
解决方法:
Monad是Type,它实现具有固定签名的两个功能:unit和bind.
用Haskell表示法:
unit :: a -> m a
bind :: m a -> (a -> m b) -> m b
unit将对象从类型a包装到类型a的m中. a的类型必须是任意的.绑定的实现可以是任何东西(但必须满足单子法则).
让我们尝试将您的示例转换为Haskell语法:
人们只是一个元组:
type People = (String, String)
Friends的类型是两个布尔值和一个String的三元组.
如果我们使用这些类型,那么您的Friends.unit方法就是这样:
unit_friends :: People -> Friends
unit_friends _ = (false, false)
这意味着,unit_friends正在丢弃is参数,而只是返回一个新的Friends实例.这是单元的错误类型签名.相反,单元应具有以下类型签名:
unit_friends :: a -> Friends a
在Java中,这看起来类似于:
public static Friends<T> unit(T from) {
// return something of type Friends<T>
}
您的bind函数采用ToFromFunction类型的函数和People类型的对象,并返回Friends类型的东西:
bind_friends :: ToFromFunction -> People -> Friends
让我们将ToFromFunction替换为
type ToFromFunction = People -> Friends -> Friends
因为那是行为的类型特征.
bind_friends :: (People -> Friends -> Friends) -> People -> Friends
让我们翻转bind_friends的参数,因为lambda函数应该是第二个参数:
bind_friends :: People -> (People -> Friends -> Friends) -> Friends
但是它应该具有以下类型签名:
bind_friends :: Friends a -> (a -> Friends b) -> Friends b
您的单位和绑定类型与真正的单子类型不匹配,但这有点接近.
让我们忘记一下,我们需要一个任意类型a. bind_friends的第一个参数必须是Friends类型,而不是People类型,因为bind应该将ToFromFunction提升为Friends monad.
标签:monads,java 来源: https://codeday.me/bug/20191122/2057388.html