写点什么

《函数式编程精粹》(2) 热身:A STACK BASED CALCULATOR

用户头像
陈皓07
关注
发布于: 2021 年 02 月 28 日

热身:A STACK BASED CALCULATOR



https://swlaschin.gitbooks.io/fsharpforfunandprofit/content/posts/stack-based-calculator.html



先定义类型



-type stack()::{stack_contents, list(float())}.-spec push(float(), stack()) -> stack().-spec pop(stack()) -> {float(), stack()}.
复制代码



实现 stack

-type stack()::{stack_contents, list(float())}.make_stack() ->    {stack_contents, []}.-spec push(float(), stack()) -> stack().push(F, {stack_contents, S}) ->    {stack_contents, [F|S]}.-spec pop(stack()) -> {float(), stack()}.pop({stack_contents, [F|S]}) ->    {F, {stack_contents, S}}.
复制代码



One

one 是一个指令,one 是什么类型?

-spec one(stack()) -> stack().
复制代码

or

-spec one() -> fun((stack()) -> stack()).
复制代码



实现:

-spec one() -> fun((stack()) -> stack()).one() ->     fun(S) ->        push(1.0, S)    end.
复制代码



two() -> fun(S) -> push(2.0, S) end.three() -> fun(S) -> push(3.0, S) end.four() -> fun(S) -> push(4.0, S) end.
复制代码



empty() -> make_stack().
复制代码



test one two three

test() ->    (three())((two())((one())(empty()))).
复制代码



add/面向组合的设计



提问:add 是什么类型?

-spec add() -> fun((stack()) -> stack()).
复制代码



这样设计就是面向组合的设计。



-spec add() -> fun((stack()) -> stack()).add() ->    fun(S) ->        {F1, S1} = pop(S),        {F2, S2} = pop(S1),        push((F1+F2),S2)    end.
复制代码



compose



h(f(g(X))) ===> 这样的写法其实是 operational 的写法,我们需要一个 compose 的操作,把 h,f,g 组合起来



pipe(InitParam, FS) ->    lists:foldl(fun(F, I) ->                    F(I)                end, InitParam, FS).compose(FS) ->    fun(S) ->        pipe(S, FS)    end.
复制代码



改写原来的使用



test2() ->    (compose([one(),two(),add()]))(empty()).
复制代码



延迟执行

compose 的方法还有另一个区别,compose 之后的结果可以不马上传入参数执行,而是延迟执行。而之前的方法必须立即执行。

代数系统的映射

以上内容对于理解 Monad 的概念很有帮助。如果一个问题能跟代数映射的话,那威力就相当大了。



去重复

假设将来实现了乘法,MUL,那么就会发现和 ADD 加法很类似。在函数式编程里面,最直接的解决方案就是把计算过程参数化,抽象出运算符的类型。当然面向对象有面向对象的解决方法。



binary(MF,S) ->    {X, S1} = pop(S),    {Y, S2} = pop(S1),    Z = MF(X, Y),    push(Z, S2).
复制代码



add() -> fun(S) -> binary(fun(X,Y) -> X*Y end, S) end.sub() -> fun(S) -> binary(fun(X,Y) -> X-Y end, S) end.mul() -> fun(S) -> binary(fun(X,Y) -> X*Y end, S) end.
复制代码



这就是 High Order Function.



OO VS FP




很简单,更抽象,但是不好理解。



用户头像

陈皓07

关注

还未添加个人签名 2019.04.11 加入

还未添加个人简介

评论

发布
暂无评论
《函数式编程精粹》(2) 热身:A STACK BASED CALCULATOR