使用Java登录函数式编程

使用Java登录函数式编程,java,functional-programming,java-8,monads,Java,Functional Programming,Java 8,Monads,我对函数式编程相当陌生,我正在尝试使用Java中的Lambda特性来尝试执行FP。我知道Java不是学习函数式语言的好选择,但在我的办公室里,我只能使用Java,我很想在那里应用这些原则 我在Java中创建了一个可选的monad类型,如下所示: public abstract class Optional<T> implements Monad<T> { //unit function public static <T> Optional<

我对函数式编程相当陌生,我正在尝试使用Java中的Lambda特性来尝试执行FP。我知道Java不是学习函数式语言的好选择,但在我的办公室里,我只能使用Java,我很想在那里应用这些原则

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

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();
    }
}
这是一种魅力。现在的问题是,如何将日志记录与此相结合?如果我需要知道这些引用中的哪一个被使用了呢?如果这些引用附带了一些语义,并且我需要记录没有找到该引用,尝试其他选项,那么这将非常有用

日志:

这可以用Java实现吗?我试着从网上阅读一些可能的解决方案,找到了哈斯克尔的
作者
莫纳德,但我感到困惑,无法理解

编辑


链接到

我将使用varargs方法,它将更易于跟踪和编写

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();
}

目前,您有两个
可选的
存在的
不存在的
。我建议引入另一种类型,
logginging缺席
,其行为类似于
缺席
,但记录任何具有回退行为的操作

关键是决定何时返回这些类型中的哪一种。例如,当将可空值转换为
可选值时,返回
logging缺席
实例将非常有用。但是,当在
可选
上调用
map
时,
loggingInquisite
实现会记录操作并返回一个非logging
Inquisite
作为结果,以便只有链的第一个操作报告回退,所有后续操作都会以静默方式回退


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

组合幺半群

A是具有标识的关联二进制操作。您的
是可选的


在你的例子中,
monoid为什么要重新发明可选的?Java8已经被引入。@Eran我这样做只是为了学习一元类型的基本原理。只是为了好玩。那么你想数一数哪一个引用是和计数器一起使用的吗?@PeterLawrey也许我解释错了,实际上我需要知道的是哪一个引用被跳过了,哪一个被使用了。用于调试级日志。您能发布所有代码以便我/我们可以玩吗?例如,在哪里定义了or()?是的,我可以这样做,但这不允许我拥有特定于上下文的日志。如果我在两种不同的情况下使用optional,那么我需要两个在这种情况下有意义的不同日志。所以我想,如果日志也可以做为组成。这样做可以选择进行日志记录,这是一种正交责任。也许我错了,把事情弄糊涂了。
some reference is not present and some other business case specific log
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();
}
String value = Optional.of(null, null, "Hello").get();
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));
}
Monoid<P2<Option<A>, String>> m = compose(firstOptionMonoid<A>, stringMonoid)
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))
  } 
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))
  }
}