KHBM / fuc_study

Whatever fp
0 stars 1 forks source link

Monad 구현 분석 #7

Open KHBM opened 3 years ago

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

}

KHBM commented 3 years ago

Java 의 상속 기능을 통해서 Monad 구현을 하기는 어려웠다.