Nim*_*sky 75 java monads optional java-8
为了帮助理解monad是什么,有人可以使用java提供一个例子吗?他们有可能吗?
如果你从这里下载预发布的lambda兼容JDK8,可以使用java表达lambda表达式http://jdk8.java.net/lambda/
使用此JDK的lambda示例如下所示,有人可以提供相对简单的monad吗?
public interface TransformService {
int[] transform(List<Integer> inputs);
}
public static void main(String ars[]) {
TransformService transformService = (inputs) -> {
int[] ints = new int[inputs.size()];
int i = 0;
for (Integer element : inputs) {
ints[i] = element;
}
return ints;
};
List<Integer> inputs = new ArrayList<Integer>(5) {{
add(10);
add(10);
}};
int[] results = transformService.transform(inputs);
}
Run Code Online (Sandbox Code Playgroud)
ms-*_*-tg 75
仅供参考:
建议的JDK8 Optional类确实满足三个Monad定律.这是一个证明这一点的要点.
Monad所需要的是提供符合三个定律的两个功能.
这两个功能:
将值放入monadic上下文中
return/JustSomeOption.someOptional.of在monadic上下文中应用函数
>>=又名bind)flatMapflatMapflatMap请参阅上面的要点,了解这三个定律的java演示.
注意:要理解的关键事项之一是要在monadic上下文中应用的函数的签名:它采用原始值类型,并返回monadic类型.
换句话说,如果你有一个实例Optional<Integer>,你可以传递给它的flatMap方法的函数将具有签名(Integer) -> Optional<U>,其中U是一个不必的值类型Integer,例如String:
Optional<Integer> maybeInteger = Optional.of(1);
// Function that takes Integer and returns Optional<Integer>
Optional<Integer> maybePlusOne = maybeInteger.flatMap(n -> Optional.of(n + 1));
// Function that takes Integer and returns Optional<String>
Optional<String> maybeString = maybePlusOne.flatMap(n -> Optional.of(n.toString));
Run Code Online (Sandbox Code Playgroud)
您不需要任何类型的Monad接口来以这种方式编码,或者以这种方式思考.在Scala中,您不编码为Monad接口(除非您使用的是Scalaz库...).似乎JDK8也将使Java人员能够使用这种链式monadic计算方式.
希望这有用!
更新:博客上讲述这个在这里.
Fai*_*aiz 55
Java 8将有lambdas; monads是一个完全不同的故事.它们很难在函数式编程中解释(正如Haskell和Scala中关于该主题的大量教程所证明的那样).
Monads是静态类型函数式语言的典型特征.要用OO说话来描述它们,你可以想象一个Monad界面.实现的类Monad将被称为"monadic",前提是在实现Monad实现时遵循所谓的"monad法则".然后,该语言提供了一些语法糖,使得处理Monad类的实例变得有趣.
现在Iterable在Java中与monad无关,但作为Java编译器特别处理的类型的示例(foreachJava 5附带的语法),请考虑以下事项:
Iterable<Something> things = getThings(..);
for (Something s: things) { /* do something with s */ }
Run Code Online (Sandbox Code Playgroud)
因此,虽然我们可以使用Iterable的Iterator方法(hasNext在旧风格和公司)for环路,爪哇赐予我们这句法糖作为特例.
因此,正如实现Iterable并且Iterator必须遵守Iterator法律的类(示例:hasNext必须返回,false如果没有下一个元素)在foreach 语法中有用- 将存在几个对相应的符号有用的monadic类do(因为它在Haskell中调用) )或Scala的for表示法.
所以 -
在Java 8中,我不知道 - 我知道lambda符号,但我不知道其他特殊的语法糖,所以我将不得不用另一种语言给你一个例子.
Monads通常用作容器类(列表就是一个例子).Java已经有了java.util.List明显不是monadic,但这里是Scala的:
val nums = List(1, 2, 3, 4)
val strs = List("hello", "hola")
val result = for { // Iterate both lists, return a resulting list that contains
// pairs of (Int, String) s.t the string size is same as the num.
n <- nums
s <- strs if n == s.length
} yield (n, s)
// result will be List((4, "hola"))
// A list of exactly one element, the pair (4, "hola")
Run Code Online (Sandbox Code Playgroud)
这是(大致)语法糖:
val nums = List(1, 2, 3, 4)
val strs = List("hello", "hola")
val results =
nums.flatMap( n =>
strs.filter(s => s.size == n). // same as the 'if'
map(s => (n, s)) // Same as the 'yield'
)
// flatMap takes a lambda as an argument, as do filter and map
//
Run Code Online (Sandbox Code Playgroud)
这显示了Scala的一个功能,其中monad被利用来提供列表推导.
因此List,Scala是一个monad,因为它遵守Scala的monad定律,规定所有monad实现必须符合flatMap,map并且filter方法(如果你对法律感兴趣,"Monads is Elephants"博客条目有最好的描述我'到目前为止已发现).并且,正如您所看到的,lambdas(和HoF)是绝对必要的,但不足以使这种事物以实用的方式有用.
除了容器之外,还有许多有用的monad.他们有各种各样的应用程序.我最喜欢的是OptionScala中的Maybemonad(Haskell中的monad),这是一个带来null安全性的包装类型:Optionmonad 的Scala API页面有一个非常简单的示例用法:http://www.scala-lang. org/api/current/scala/Option.html
在Haskell中,monad在表示IO时很有用,可以解决非monadic Haskell代码具有不确定执行顺序这一事实.
拥有lambdas是进入函数式编程世界的第一小步; monads需要monad约定和足够大的可用monadic类型,以及语法糖,以使它们有趣和有用.
由于Scala可以说是最接近Java的语言,它也允许(monadic)函数式编程,如果您(仍然)感兴趣的话,请查看Scala的Monad教程:http: //james-iry.blogspot.jp/2007/09/单子-都-大象-部分- 1.HTML
粗略的谷歌搜索显示至少有一次尝试在Java中执行此操作:https://github.com/RichardWarburton/Monads-in-Java -
遗憾的是,解释Java中的monad(即使使用lambdas)与解释ANSI C(而不是C++或Java)中的完整面向对象编程一样困难.
Mar*_*lli 10
即使monad可以用Java实现,任何涉及它们的计算都注定要成为泛型和大括号的混乱组合.
我会说Java绝对不是用来说明其工作或研究其含义和本质的语言.为此目的,使用JavaScript或支付一些额外的价格并学习Haskell要好得多.
无论如何,我发信号通知你,我刚刚使用新的Java 8 lambdas实现了一个状态monad.它绝对是一个宠物项目,但它适用于一个非平凡的测试用例.
你可能会在我的博客上找到它,但我会在这里给你一些细节.
状态monad基本上是从状态到对(状态,内容)的函数.您通常为状态赋予通用类型S,并将内容赋予通用类型A.
因为Java没有对,我们必须使用特定的类对它们进行建模,让我们称之为Scp(状态 - 内容对),在这种情况下它将具有泛型类型Scp<S,A>和构造函数new Scp<S,A>(S state,A content).在这之后我们可以说monadic函数将具有类型
java.util.function.Function<S,Scp<S,A>>
Run Code Online (Sandbox Code Playgroud)
这是一个@FunctionalInterface.也就是说,可以在不命名的情况下调用其唯一的实现方法,传递具有正确类型的lambda表达式.
该类StateMonad<S,A>主要是函数的包装器.它的构造函数可以用例如
new StateMonad<Integer, String>(n -> new Scp<Integer, String>(n + 1, "value"));
Run Code Online (Sandbox Code Playgroud)
状态monad将该函数存储为实例变量.然后有必要提供一种公共方法来访问它并将其提供给状态.我决定称之为s2scp("状态到状态 - 内容对").
要完成monad的定义,您必须提供一个单元(aka return)和一个bind(aka flatMap)方法.我个人更喜欢将unit指定为static,而bind是实例成员.
在州monad的情况下,单位必须如下:
public static <S, A> StateMonad<S, A> unit(A a) {
return new StateMonad<S, A>((S s) -> new Scp<S, A>(s, a));
}
Run Code Online (Sandbox Code Playgroud)
而bind(作为实例成员)是:
public <B> StateMonad<S, B> bind(final Function<A, StateMonad<S, B>> famb) {
return new StateMonad<S, B>((S s) -> {
Scp<S, A> currentPair = this.s2scp(s);
return famb(currentPair.content).s2scp(currentPair.state);
});
}
Run Code Online (Sandbox Code Playgroud)
您注意到绑定必须引入泛型类型B,因为它是允许链接异构状态monad的机制,并为此和任何其他monad提供了将计算从一个类型移动到另一个类型的卓越功能.
我将停止使用Java代码.复杂的东西在GitHub项目中.与以前的Java版本相比,lambdas删除了很多大括号,但语法仍然相当复杂.
另外,我正在展示如何在其他主流语言中编写类似的状态monad代码.在Scala的情况下,bind(在这种情况下必须称为flatMap)读起来像
def flatMap[A, B](famb: A => State[S, B]) = new State[S, B]((s: S) => {
val (ss: S, aa: A) = this.s2scp(s)
famb(aa).s2scp(ss)
})
Run Code Online (Sandbox Code Playgroud)
而JavaScript中的绑定是我最喜欢的; 100%功能,精益和平均,但当然无类型:
var bind = function(famb){
return state(function(s) {
var a = this(s);
return famb(a.value)(a.state);
});
};
Run Code Online (Sandbox Code Playgroud)
<无耻>我在这里削减一些角落,但如果你对细节感兴趣,你可以在我的WP博客上找到它们.</ shameless>
这是关于 monad 的一个难以理解的事情:monad 是一种模式,而不是特定的类型。Monad 是一种形状,它们是一个抽象的接口(不是 Java 意义上的),而不是具体的数据结构。因此,任何示例驱动的教程都注定不完整和失败。[...] 理解 monad 的唯一方法是了解它们的本质:数学结构。
Java SE 8 中的 Monad
列出单子
interface Person {
List<Person> parents();
default List<Person> greatGrandParents1() {
List<Person> list = new ArrayList<>();
for (Person p : parents()) {
for (Person gp : p.parents()) {
for (Person ggp : p.parents()) {
list.add(ggp);
}
}
}
return list;
}
// <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
default List<Person> greatGrandParents2() {
return Stream.of(parents())
.flatMap(p -> Stream.of(p.parents()))
.flatMap(gp -> Stream.of(gp.parents()))
.collect(toList());
}
}
Run Code Online (Sandbox Code Playgroud)
也许单子
interface Person {
String firstName();
String middleName();
String lastName();
default String fullName1() {
String fName = firstName();
if (fName != null) {
String mName = middleName();
if (mName != null) {
String lName = lastName();
if (lName != null) {
return fName + " " + mName + " " + lName;
}
}
}
return null;
}
// <U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
default Optional<String> fullName2() {
return Optional.ofNullable(firstName())
.flatMap(fName -> Optional.ofNullable(middleName())
.flatMap(mName -> Optional.ofNullable(lastName())
.flatMap(lName -> Optional.of(fName + " " + mName + " " + lName))));
}
}
Run Code Online (Sandbox Code Playgroud)
Monad 是嵌套控制流封装的通用模式。即一种从嵌套的命令式习语中创建可重用组件的方法。
重要的是要了解 monad 不仅仅是具有平面映射操作的通用包装器类。例如,ArrayList使用flatMap方法不会是 monad。因为monad 法律禁止副作用。
Monad 是一种形式主义。它描述了结构,无论内容或含义如何。人们挣扎于与无意义(抽象)事物的联系。所以他们想出了不是单子的隐喻。
另请参阅: Erik Meijer 和 Gilad Bracha 之间的对话。
理解monad的唯一方法是编写一堆组合器库,注意所产生的重复,然后亲自发现monad使您可以排除这种重复。在发现这一点时,每个人都为单子是什么建立了某种直觉……但是这种直觉不是您可以直接与他人交流的那种东西–似乎每个人都必须经历从某种具体事物推广到单子的相同经验。组合器库的示例。然而
在这里,我找到了一些学习蒙达斯的材料。
希望对您也有用。