浏览 7683 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2006-12-02
private final static F<Boolean> TRUE = $(true); private final static F<Integer> ONE = $(1); private final static F<Integer> TWO = $(2); private final static F<Integer> THREE = $(3); private void demo() { LF2<Integer, Integer, Integer> add = new LF2<Integer, Integer, Integer>() { protected Integer lambda(Integer left, Integer right) { System.out.println("calc " + left + " + " + right); return left + right; } }; LF3<Boolean, Integer, Integer, Integer> select = new LF3<Boolean, Integer, Integer, Integer>() { protected Integer lambda(Boolean arg1, Integer arg2, Integer arg3) { if (arg1) { return arg2; } return arg3; } }; LF1<Integer, Integer> onePlus = add._(ONE); F<Integer> onePlusTwo = onePlus._(TWO); F<Integer> onePlusThree = onePlus._(THREE); System.out.println(select._(TRUE, onePlusThree, onePlusTwo)._()); } 运行结果 引用 calc 1 + 3 4 结果分析: 1、实现了Curry(利用匿名类,绑定参数) 2、实现了Lazy Evaluation(利用载入时字节码修改,会添加进参数是否已经被求值的判断) 3、类型安全 缺点: 匿名类的语法 调用语法(用_表示调用仍然会有很多括号) 12.9: 更新为最新的语法 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2006-12-06
SICP练习题4.25。定义了一个$函数把值封装成对象。定义了unless来做判断。定义了mul来做乘法。最后是把这些组装起来变成一个求阶乘的函数。如果这个函数不是lazy的话,必然导致堆栈溢出。
private static LF1<Integer, Integer> factorial = new LF1<Integer, Integer>() { protected Integer lambda(Integer n) { F<Integer> val1 = mul._($(n))._(factorial._($(n - 1))); F<Integer> val2 = $(1); return unless._($(n == 1))._(val1)._(val2)._(); } }; |
|
返回顶楼 | |
发表时间:2006-12-08
添加了LazyStream,支持了无穷序列。下面是一个fibonacci数列的例子。和Haskell的版本没得比,但是俺已经竭尽所能了。cons(element1, fibs._(element2)._$(element1 + element2)),Java的语法能做到这样来表示无穷序列已经不容易了。另外谁能给一个和Haskell版本等价的实现?俺想不出来咋用zipWith等高阶函数来组装出来。貌似语法会更加丑陋。所有的源代码都在附件中。
private void demo() { LazyStream<Integer> stream = fibs(); for (int i = 0; i < 10; i++) { System.out.println(stream.current()); stream = stream.rest(); } } private static LazyStream<Integer> fibs() { return fibs._(0, 1); } private static F2<Integer, Integer, LazyStream<Integer>> fibs = new F2<Integer, Integer, LazyStream<Integer>>() { public LazyStream<Integer> _(Integer element1, Integer element2) { return cons(element1, fibs._(element2)._$(element1 + element2)); } }; |
|
返回顶楼 | |
发表时间:2006-12-09
关于Monad,俺也是现学。发觉拿Java做点函数式实验对于理解函数式语言还是很有帮助的。不过这Monad不知道弄对了没有。我也不是很确定。。。
Maybe Monad,用于减少null checking。只要有一个是null,就停止求值。下面是这个Monad的定义。 public abstract class Maybe<T> implements Monad { public final T value; private Maybe(T value) { this.value = value; } public static <T1, T2> Maybe<T2> bind(Maybe<T1> m, F1<T1, Maybe<T2>> f) { return (Maybe<T2>) m.bind(f); } public static <T1, T2, T3> Maybe<T3> bind(Maybe<T1> m, F1<T1, Maybe<T2>> f, F1<T2, Maybe<T3>> g) { return bind(bind(m, f), g); } public static <T> Maybe<T> maybe(T value) { return new Maybe<T>(value) { }; } @SuppressWarnings("unchecked") public Monad bind(F1 f) { if (value == null) { return new Maybe(null) { }; } return (Monad) f._(value); } } 这是一个使用的例子。第一行打印nothing to say...第二行打印null public class MaybeDemo { public static void main(String[] args) { new MaybeDemo().demo(); } private void demo() { Maybe<String> result = (Maybe<String>) exec(maybe(""), remark1, remark2); System.out.println(result.value); System.out.println(bind(maybe("silence"), remark1, remark2).value); } private F1<String, Maybe<String>> remark1 = new F1<String, Maybe<String>>() { public Maybe<String> _(String words) { if ("".equals(words)) { return maybe("be nice, man"); } return maybe(null); } }; private F1<String, Maybe<String>> remark2 = new F1<String, Maybe<String>>() { public Maybe<String> _(String words) { return maybe("nothing to say..."); } }; } |
|
返回顶楼 | |
发表时间:2006-12-10
突然发觉curry的写法和keyword message很相近啊。比如说我定义了一个moveFromTo的方法用来把一个元素从一个序列移动到另外一个序列。用keyword message可以写成move aObject :from aList :to anotherList。那么我用Java定义这么一个函数:
private F3<String, List<String>, List<String>, Nothing> moveFromTo = new F3<String, List<String>, List<String>, Nothing>() { public Nothing _(String element, List<String> fromList, List<String> toList) { fromList.remove(element); toList.add(element); return nothing; } }; 可以写成 moveFromTo._(aObject)._(aList)._(anotherList)。显然不是很好看的说。所以祭出cglib来,搞一搞。我希望能够这么写: List<String> list1 = list("hello", "hi"); List<String> list2 = list("hi"); move("hello").from(list1).to(list2); 所以要定义一下相关的keyword接口: private MoveKeyword move(String element) { return null; //暂时还没实现。 } public static interface MoveKeyword { MoveFromKeyword from(List<String> fromList); } public static interface MoveFromKeyword { Nothing to(List<String> toList); } 一般的做法是自己手写每个keyword接口的实现。但是我们已经有一个function啦(moveFromTo)。所以我只要拿cglib根据这个function和传给move的参数(element),就能自动帮我把这几个keyword接口给实现了。写法是: return implement(MoveKeyword.class, moveFromTo, element); implement是import static进来的。华丽一点可以做到implement(MoveKeyword.class).accordingTo(moveFromTo).with(element);。 代码在前面的压缩包里。 |
|
返回顶楼 | |
发表时间:2006-12-10
Maybe Monad,谈Monad的入门资料,必定谈它。
首先看代码,比如定义了如下函数: f::Int->Int f x = 10 `div` x g::Int->Int g x = x+1 h = g.f当计算: (1)h 2:正常; (2)h 0:程序中断,除数不能为0 此时f的返回值,传给g出现了脱节,导致不匹配。此时怎么办,于是想到了搞一个Maybe type construtor,对它们进行统一封装,使得计算可以正常流动起来。就算是除0操作,也被视为了正常,达到了统一 。统一之后,就不会出现计算中断了。 使用用Maybe统一之后的代码: f::Int->Maybe Int f x = if x==0 then Nothing else Just (10 `div` x) g::Maybe Int->Maybe Int g Nothing = Nothing g (Just x) = Just (x+1) h = g.f看到上面没有,采用Maybe之后,还是有不爽的地方,就是总是要对Maybe的值进行条件判断,看它是Nothing还是Just。一两个函数组合,问题还不大,当函数多了的时候,就麻烦了,很多的重复代码,那可是bad smell。于是对Maybe类型整了return和>>=两个函数,使其变成Monad,这样一切就好办啦。 此时的代码变成了如下的样子: f::Int->Maybe Int f x = if x==0 then Nothing else Just (10 `div` x) g::Int->Maybe Int g x = Just (x+1) h x= (Just x)>>=f>>=g这样,在g函数中,就无需再进行判断了,这些工作都交给了Monad。 |
|
返回顶楼 | |
发表时间:2006-12-10
monad应该比你说的还要广一些。按照ajoo的说法,monad是一种计算模型。还有一种更抽象的是arrow啥的。按照我来看就是通过类型系统的限定(由于f的返回值是Maybe Int不是Int了),迫使程序员不能直接拿f的返回值去调用g。必须拿bind来把f和g“绑定”到一起去。不然你不知道该给g传啥参数,因为f的返回值装载Maybe这个“盒子”里呢。由于我认为Maybe是一个泛型的盒子。随意就把Maybe做成了Maybe<T>。
|
|
返回顶楼 | |
发表时间:2006-12-14
Maybe Monad的应用只限于简单的情况:首先如果可选择的情况多于两种(也就是例外情况多于一种)在计算的每一步都要处理这些选择很麻烦,其次这样把正常逻辑和处理违例的逻辑混在一起,不是个best practice。
|
|
返回顶楼 | |