Open KHBM opened 3 years ago
@Log4j2 public class Funcs { static class Identity { private final T value;
Identity(T value) { this.value = value; } public <R> Identity<R> map(Function<? super T,R> f) { final R result = f.apply(value); return new Identity<>(result); } public <R> Identity<R> flatMap(Function<? super T, Identity<R>> f) { return f.apply(value); } } static class FList<T> { private final ImmutableList<T> list; public static <T> FList<T> empty() { return new FList<>(Arrays.asList()); } FList(Iterable<T> value) { this.list = ImmutableList.copyOf(value); } public <R> FList<R> map(Function<? super T, R> f) { List<R> result = new ArrayList<>(list.size()); for (T t : list) { result.add(f.apply(t)); } return new FList<>(result); } public <U> FList<U> flatMap(Function<? super T, FList<U>> f) { // [1, 2, 3] with x -> [x*x] => [1, 4, 9] final FList<FList<U>> map = this.map(f); return FList.concat(map); } public List<T> getData() { return this.list; } public static <U> FList<U> concat(FList<FList<U>> lists) { List<U> result = Lists.newArrayList(); for (FList<U> list : lists.getData()) { result.addAll(list.getData()); } return new FList<>(result); } public <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) { return this.list.stream().reduce(identity, accumulator, combiner); } public T reduce(T identity, BinaryOperator<T> accumulator) { return this.list.stream().reduce(identity, accumulator); } public Optional<T> reduce(BinaryOperator<T> accumulator) { return this.list.stream().reduce(accumulator); } } public static void main(String[] args) { try { final List<Integer> integers = Arrays.asList(1, 3, 5, 6, 7); FList<Integer> fList = new FList<>(integers); final FList<Integer> integerFList = fList.flatMap(t -> new FList<>(Arrays.asList(String.valueOf(t), String.valueOf(t - 1)))) // 배열 확대 [1, 0, 3, 2, 5, 4, 6, 5, 7, 6] .flatMap(s -> new FList<>(Arrays.asList(s + "_hello"))) // 각 값에 문자열 조합 ["1_hello", "0_hello", "3_hello", "2_hello", "5_hello", "4_hello", "6_hello", "5_hello", "7_hello", "6_hello"] .map(s -> s.substring(0, 2)) // ["1_", "0_", "3_", "2_", "5_", "4_", "6_", "5_", "7_", "6_"]
// .map(s -> s.substring(0, 1)) // 이게 없으면 정수 변환에 실패하므로 빈 배열이 리턴된다 ["1", "0", "3", "2", "5", "4", "6", "5", "7", "6"] .flatMap(s -> tryParse2(s)); final List data = integerFList.getData(); log.info(data); } catch (Exception e) { e.printStackTrace(); } }
private static void test1ExpandIntegers() { final List<Integer> integers = Arrays.asList(1, 3, 5, 6, 7); FList<Integer> fList = new FList<>(integers); final FList<Integer> fList1 = fList.flatMap((t) -> new FList<>(Arrays.asList(t, t))); // duplicate final List<Integer> data = fList1.getData(); log.info(data); } static class FOptional<T> { private final T valueOrNull; private FOptional(T valueOrNull) { this.valueOrNull = valueOrNull; } public <R> FOptional<R> map(Function<? super T, R> f) { if (valueOrNull == null) return empty(); else return of(f.apply(valueOrNull)); } public static <T> FOptional<T> of(T a) { return new FOptional<T>(a); } public static <T> FOptional<T> empty() { return new FOptional<T>(null); } public <U> FOptional<U> flatMap(Function<? super T, FOptional<U>> f) { if (valueOrNull == null) return empty(); else return f.apply(valueOrNull); } } static FOptional<Integer> tryParse(String s) { try { final int i = Integer.parseInt(s); return FOptional.of(i); } catch (NumberFormatException e) { return FOptional.empty(); } } static FList<Integer> tryParse2(String s) { try { final int i = Integer.parseInt(s); return new FList<>(Arrays.asList(i)); } catch (NumberFormatException e) { return FList.empty(); } }
}
Java 의 상속 기능을 통해서 Monad 구현을 하기는 어려웠다.
@Log4j2 public class Funcs { static class Identity
{
private final T value;
// .map(s -> s.substring(0, 1)) // 이게 없으면 정수 변환에 실패하므로 빈 배열이 리턴된다 ["1", "0", "3", "2", "5", "4", "6", "5", "7", "6"] .flatMap(s -> tryParse2(s)); final List data = integerFList.getData();
log.info(data);
} catch (Exception e)
{
e.printStackTrace();
}
}
}