首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Java登录函数编程

用Java登录函数编程
EN

Stack Overflow用户
提问于 2014-08-09 12:28:21
回答 3查看 1.9K关注 0票数 5

我对函数式编程相当陌生,我正尝试使用Java中的Lambda特性来尝试执行FP。我知道Java不是学习函数式的好选择,但在我的办公室,我被限制使用Java,并且很乐意在那里应用其中的一些原则。

我在Java中创建了一个可选的monad类型的东西,如下所示:

代码语言:javascript
复制
public abstract class Optional<T> implements Monad<T> {
    //unit function
    public static <T> Optional<T> of(T value) {
        return value != null ? new Present<T>(value) : Absent.<T>instance();
    }

    @Override
    public <V> Monad<V> flatMap(Function<T, Monad<V>> function) {
        return isPresent() ? function.apply(get()) : Absent.<V>instance();
    }
}

我用它来避免代码中嵌套的null检查,这是我使用的一个典型的用例,当我需要类似于firstNonNull的东西时。

使用:

代码语言:javascript
复制
String value = Optional.<String>of(null)
                .or(Optional.<String>of(null)) //call it some reference
                .or(Optional.of("Hello"))      //other reference
                .flatMap(s -> {
                    return Optional.of(s.toLowerCase());
                })
                .get();

这是一种魅力。现在的问题是,如何将日志记录与此结合起来?如果我需要知道这些引用中的哪一个被使用了呢?这是有用的,如果有一些语义附加在这些引用,我需要记录,这个引用没有找到,尝试其他选项。

日志:

代码语言:javascript
复制
some reference is not present and some other business case specific log

这在Java中可以实现吗?我试着从网络上阅读一些可能的解决方案,并找到了哈斯克尔的Writer monad,但我感到困惑,无法理解。

编辑

链接到要旨

EN

回答 3

Stack Overflow用户

发布于 2015-04-16 21:34:28

一个很好的解决方案是单类成分。

组合一元

单样是一个具有标识的关联二进制操作。您的Optional<A>类型为任意A形成一个单面

https://functionaljava.ci.cloudbees.com/job/master/javadoc/fj/Monoid.html#firstOptionMonoid--

在您的示例中,Monoid<Optional<A>>将使用or作为sumAbsent作为zero来实现,因此yourMonoid.sum(x, y)应该与x.or(y)相同。

现在你想把它和另一个单体结合起来--一个由你的日志组成的。因此,假设您使用一个简单的String作为日志。String形成一个单面,其中sum是字符串级联,而zero是空字符串。

您希望将String单样体与firstOptionMonoid组合起来。为此,您需要一个元组类型。Functional有P2。下面是如何组合两个单引号(这实际上应该添加到Monoid类中;发送一个拉请求!):

代码语言:javascript
复制
import fj.*;
import static fj.P.p;
import static fj.Monoid.*;

public final <A,B> Monoid<P2<A,B>> compose(Monoid<A> a, Monoid<B> b) {
  return monoid(
    x -> y -> p(a.sum(x._1, y._1), b.sum(x._2, y._2)),
    p(a.zero, b.zero));
}

然后(在FJ中)合成单面:

代码语言:javascript
复制
Monoid<P2<Option<A>, String>> m = compose(firstOptionMonoid<A>, stringMonoid)

现在,您并不总是想要添加日志。您希望它取决于Option中的值是否存在。为此,您可以编写一个专门的方法:

代码语言:javascript
复制
public final P2<Option<A>, String> loggingOr(
  P2<Option<A>, String> soFar,
  Option<A> additional,
  String msg) {
    return soFar._1.isDefined ?
      soFar :
      m.sum(soFar, p(additional, msg))
  } 

我建议在一般情况下多观察一些单子植物。它们是一个非常通用的工具,而且它们是少数几个在Java中真正令人愉快地使用的纯函数结构之一。如果你不介意用Scala学习,我写了一本叫Scala中的函数编程关于一元论的章节恰好可以在网上找到。的免费书。

组合单子

但是现在您使用的是复合类型P2<Option<A>, String>,而不仅仅是Option<A>,而且这种类型不附带flatMap。您真正想要的是(如果Java可以这样做,但它不能)是使用Writer<String, _> monad和OptionT这样的monad转换器。想象一下Java可以有单台转换器,类型P2<Option<A>, String>将等价于类型OptionT<Writer<String, _>, A>,其中_表示部分应用的类型构造函数(显然不是有效的Java )。

Java中唯一的解决方案是以一阶方式组合这些单体:

代码语言:javascript
复制
import fj.data.Writer

public abstract class OptionWriter<W, A> {
  abstract Writer<W, Option<A>> writer;
  public <B> OptionWriter<W, B> flatMap(Function<A, OptionWriter<B>>) {
    ...
  }
  public static <M, T> OptionWriter<M, T> unit(t: T) {
    return Writer.unit(Option.unit(t))
  }
}
票数 2
EN

Stack Overflow用户

发布于 2014-08-09 13:00:58

我会使用varargs的方法,它将更简单地跟踪和简短的写。

代码语言:javascript
复制
public static <T> Optional<T> of(T... value) {
    for(int i=0;i<values.length;i++) {
        if (value[i] != null) {
            // log that value[i] was chosen
            return new Present<T>(value[i]);
        }
    }
    // log all was null
    return Absent.<T>instance();
}

在你的例子中

代码语言:javascript
复制
String value = Optional.of(null, null, "Hello").get();
票数 0
EN

Stack Overflow用户

发布于 2014-08-11 08:53:47

目前,您有两个OptionalPresentAbsent实现。我建议引入另一种类型,LoggingAbsent,它的行为类似于Absent,但记录任何具有后退行为的操作。

关键是决定何时返回这些类型中的哪一种。例如,当将可空值转换为Optional时,返回LoggingAbsent实例是有用的。但是,当在一个map上调用Optional时,LoggingAbsent实现记录操作并返回一个非日志记录Absent作为结果是合理的,这样只有链的第一个操作报告回退,随后的所有操作都会悄无声息地后退。

您还可以通过提供用于创建日志记录和非日志记录Optional的替代工厂方法来支持显式选择。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25218585

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档