在Java中实现功能fold_right

时间:2019-02-14 00:56:59

标签: java functional-programming

我正在尝试使用Java的某些功能来实现功能方法fold_right。我下面的代码可以工作,但是我真的不明白为什么为什么-我认为主要的问题是我对lambda在Java中的工作方式有点不确定(尤其是在使用它们时)与泛型)。例如,为什么我必须通过再次调用apply来调用在apply()中返回的lambda?我要上的课是在OCaml中教授的,对我来说,很容易理解OCaml在其标准库中具有的fold_right函数。我在Java中实现它的方式似乎更加笨拙和冗长-有人可以为我提供一些启示吗?

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

interface Func<A,B> {
    B apply(A a);
}

class Add implements Func<Integer, Func<Integer,Integer>> {
    @Override
    public Func<Integer,Integer> apply(Integer a) {
        return (b) -> a + b;
    }
}

public class Fold {
    public static <E> E fold(Func<E,Func<E,E>> f, E acc, LinkedList<E> lst) {
        if (lst.isEmpty()) {
            return acc;
        } else {
            LinkedList<E> listClone = (LinkedList<E>) lst.clone();
            E theHead = listClone.removeFirst();
            return (E) f.apply(theHead).apply((fold(f,acc,listClone)));
        }
    }

    public static void main(String[] args) {
        Integer[] nums = {1,2,3,4,5};
        List<Integer> nums_lst = Arrays.asList(nums);
        LinkedList<Integer> lst = new LinkedList<Integer>(nums_lst);
        int result = Fold.fold(new Add(), 0, lst);
        System.out.println(result);  // should be 15
        System.out.println(lst);  // should be [1,2,3,4,5]
    }
}

1 个答案:

答案 0 :(得分:0)

稍微偏离主题,但是java具有内置的Function<T, R>,也就是说,要了解代码的工作原理,让我们从<select> <option value="Test1">test1</option> <option value="Test2" selected="selected">test2</option> <option value="Test3">test3</option> </select> <hr/> 接口开始:

Func<A, B>

因此,乍看之下,我们有两种类型,即interface Func<A,B> { B apply(A a); } A, B方法告诉我,它接受类型为apply的参数并返回类型为{{ 1}}。好的,现在转到A类,该类将B接口实现为:

Add

因此,根据我们先前的推理,在Func中实现的Func<Integer, Func<Integer, Integer>> 方法将接受一个apply并返回一个Add。因此,当我们查看Integer类旁边的Func<Integer, Integer>方法时:(为简单起见,您可以将fold视为Fold

E

请注意,由于您的Objectpublic static <E> E fold(Func<E,Func<E,E>> f, E acc, LinkedList<E> lst) { if (lst.isEmpty()) { return acc; } else { LinkedList<E> listClone = (LinkedList<E>) lst.clone(); E theHead = listClone.removeFirst(); // A B <- remember the Func interface? here A is E and B is Func<E,E> // f is a Func<E, Func<E, E>> that takes in an E and returns // another Func<E, E> after calling apply thus // breaking the steps: // f.apply(E) <- we just called the apply method thus this should return a "B" // Since B is a Func<E, E> we need to call apply to perform the operation // onto the next element, which in this case is an addition. You can think // of it as a -> b -> a + b. // Now you played that nice trick of using recursion to call this function // and traverse all elements till the end of the collection and accumulate // all the intermediate results. return (E) f.apply(theHead).apply((fold(f,acc,listClone))); // the listClone is one element shorter in each recursion // since you are removing the first element } } 的签名匹配,因此您可以将Func<A, B>作为lambda传递,而无需实现java.util.Function类的显式性: / p>

Add