LINUX.ORG.RU

package combinators;

public class Main {
    public static void main(String[] args) {
        System.out.print("factorial(5)==" + 
                (new Y<Long>().eval(new FactY())).eval(new Long(5)) + "\n");
    }
}

abstract class F<R,T> {
    public abstract R eval(T arg);
}

class FactY extends F<F<Long,Long>,F<Long,Long>> {
    public F<Long,Long> eval(final F<Long,Long> f) {
        return new F<Long,Long>() {
            public Long eval(Long n) {
                return n==0 ? 1 : n*f.eval(n-1);
            };
        };
    }
}
class Y<T> extends F<F<T,T>,F<F<T,T>,F<T,T>>> {
    public F<T,T> eval(final F<F<T,T>,F<T,T>> f) {
        F<F<T,T>,F<F<T,T>,F<T,T>>> l1 = new F<F<T,T>,F<F<T,T>,F<T,T>>>() {
            public F<T,T> eval(final F<F<T,T>,F<T,T>> rec) {
                return f.eval(new F<T, T>() {
                    public T eval(T x) {
                        return rec.eval((F<T, T>) rec).eval(x);
                    }
                });
            };
        };
       return l1.eval((F<F<T,T>,F<T,T>>)((F) l1));
    }
}

yyk ★★★★★
() автор топика
Ответ на: комментарий от yyk

Только я схалтурил: l1 передал его-же вместо того чтобы сделать вторую копию - лень :)

И ещё меня "напрягают" приведения - без них никак, но приведение к "корневому" - это слишком...

yyk ★★★★★
() автор топика
Ответ на: комментарий от yyk

Вижу, таки, нашел собеседника! Похвально.

vada ★★★★★
()
Ответ на: комментарий от yyk

посмотри в ru_lambda - там был более элегантный вариант на VB

от ivan_ghandi, ЕМНИП. или от него был именно на Java, точно не скажу. но на VB точно кто-то постил

// jtootf из Мюнхена

anonymous
()
Ответ на: комментарий от wfrr

>Каково практическое применение таких извратов кроме убийства времени?

Удовлетворение интереса - насколько "лаконично" это можно сделать =D

За остальным - к "чистым" ФП-шникам...

yyk ★★★★★
() автор топика
Ответ на: комментарий от yyk

>Надо будет её расковырять - может получится "чистый" вариант :)

Не получится - реализация Branch - тайна за семью печатями.

yyk ★★★★★
() автор топика
Ответ на: комментарий от yyk

Получилось - практически в классическом варианте
и с одним единственным приведением:

package combinators;

public class TestY {
    public static void main(String[] args) {
        System.out.print("factorial(5)==" + 
                (new Y<Long>().apply(new FactY())).apply(new Long(5)) + "\n");
    }
}

abstract class F<R,T> {
    public abstract R apply(T arg);
}

class FactY extends F<F<Long,Long>,F<Long,Long>> {
    public F<Long,Long> apply(final F<Long,Long> f) {
        return new F<Long,Long>() {
            public Long apply(Long n) {
                return n==0 ? 1 : n*f.apply(n-1);
            };
        };
    }
}

class Y<T> extends F<F<T, T>, F<F<T, T>, F<T, T>>> {
    public F<T, T> apply(final F<F<T, T>, F<T, T>> f) {
        return new F<F<T, T>, F>() {
            public F<T, T> apply(final F rec) {
                return f.apply(new F<T, T>() {
                    public T apply(T x) {
                        return ((F<F<T, T>, F>) rec).apply(rec).apply(x);
                    }
                });
            }
        }.apply(new F<F<T, T>, F>() {
            public F<T, T> apply(final F rec) {
                return f.apply(new F<T, T>() {
                    public T apply(T x) {
                        return ((F<F<T, T>, F>) rec).apply(rec).apply(x);
                    }
                });
            }
        });
    }
}


Я успокоился. Обострение закончилось =)

yyk ★★★★★
() автор топика
Ответ на: комментарий от yyk

>Я успокоился. Обострение закончилось 

Не закончилось - всё обо что я ломал голову было найдено на
http://dtm.livejournal.com/36832.html

Что-ж, "мы пойдём другим путём..." =)

class Y<R,T> extends F<F<R, T>, F<F<R, T>, F<R, T>>> {
    abstract class Branch extends F<F<R, T>, Branch>{
        public abstract F<R, T> apply(Branch arg);
    };
    public F<R, T> apply(final F<F<R, T>, F<R, T>> f) {
        return new Branch() {
            public F<R, T> apply(final Branch rec) {
                return f.apply(new F<R, T>() {
                    public R apply(T x) {
                        return (rec).apply(rec).apply(x);
                    }
                });
            }
        }.apply(new Branch() {
            public F<R, T> apply(final Branch rec) {
                return f.apply(new F<R, T>() {
                    public R apply(T x) {
                        return (rec).apply(rec).apply(x);
                    }
                });
            }
        });
    }
}

class AckY extends F<F<F<Long,Long>,Long>,F<F<Long,Long>,Long>> {
    public F<F<Long,Long>,Long> apply(final F<F<Long,Long>,Long> f) {
        return new F<F<Long,Long>,Long>() {
            public F<Long,Long> apply(final Long m) {
                return new F<Long,Long>() {
                    public Long apply(Long n) {
                        if (m==0) return n+1;
                        if (n==0) return f.apply(m-1).apply((long)1);
                        return f.apply(m-1).apply(f.apply(m).apply(n-1));
                    }
                };
            };
        };
    }
}

// A(3,4)=125
final static long m = 3;
final static long n = 4;
System.out.print("Ackerman(" + m + "," + n + ")==" +
                (new Y<F<Long,Long>,Long>()).apply(new AckY()).apply(m).apply(n) + "\n");

yyk ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.