• 理解函数式编程语言中的组合--前言(一)


    理解函数式编程语言中的组合--前言(一)

    函数式编程思想可以用一句话总结,即:可组合的类型+可组合的函数,我在《使用函数式语言做领域建模》一文描述了如何使用可组合的类型进行领域建模。这篇文章就是用来说明后半部分,即--理解可组合的函数。我假设读者已经对“Higher order function”, “Currying“, ”Immutable“等基本概念有所了解,并拥有基础的TypeScript知识即可。
    这一切还得从抽象说起。

    抽象的重要性

    人类能够解决复杂事物的一个重要方法就是抽象,代码也一样。有了抽象,你的代码才不会变成流水账,实际上那些让人读起来赏心悦目的好代码,一定拥有良好的抽象。抽象可以让你避免陷入细节,通过几个重要的类名或者接口,让别人快速识别你的设计。
    当然,这一切的前提是,阅读代码的人也拥有类似的抽象思想,他才能够心领神会你的意图。如果你在读代码的时候,自己是怎么想的,正好代码就是这样设计的,你才会觉得代码可读性太强了。
    怎么样大家才能设计出一致的抽象呢?
    《设计模式》就是这样一本把常见问题总结成一些列模式的书籍。换句话说,《设计模式》提供了常见问题的抽象方式并提供了相关的术语。
    当然你的设计好不好,还取决于你是否正确识别到了问题的本质,并恰如其分的实现了某个已知的设计模式。如果阅读代码的人拥有跟你类似的抽象知识,他就能够迅速明白你的设计和意图。

    函数式编程中的抽象

    如果说《设计模式》总结了OO思想中的常见抽象方式,那么函数式编程语言也拥有自己的抽象方式。
    看下面的这两行数学运算:

    1 + 2 = 3
    

    这行数学运算非常简单,以至于靠直觉就能判断他的真确性。这行代码可以描述为:两个“数字”通过“相加”任然为“数字”。
    如果我们把"数字“泛化,将"相加”推广开来,就可以用在其他事物身上,例如:

    "a" + "b" = "ab"
    

    对字符串也是适用的,两个字符串通过一个运算符合并为一个新的字符串。没错,这就是组合的基础。
    函数式编程中的抽象叫做《范畴轮》Category theory,是一门研究如何组合事物的数学科学。其中,“事物”被称为object, 但这个object并不是OO中的那个对象,而事物之间的转化或者映射被称为morphisms,翻译为中文叫射态,对应到编程语言中,就是函数。《范畴论》在函数式编程语言中的地位,可以类比《设计模式》在OO中的地位。

    为什么需要《范畴论》

    这要从函数的组合开始说起,我们知道函数式编程语言没有OO语言中的那些概念,例如类,继承,依赖注入(有的语言有FP和OO两种范式, 例如Scala, F#等,请不要纠结)。只靠函数,为大型的工程化实践带来了挑战。 玩过乐高的同学都知道,乐高的零件都是拥有独立功能的小部件,然而,却有人用它拼出了汽车,飞机甚至是航空母舰,这充分说明了组合的力量。
    那么函数是如何组合的呢?看下面的代码:

    const add = (a: number, b: number) => a + b
    const sub1 = (a: number) => a - 1 
    

    声明两个函数add和sub1, 像lodash或fp-ts等库都会提供一个叫flow的函数,flow的作用就是把若干个函数组合起来:

    const addThenSub1 = flow(add, sub1)
    
    expect(addThenSub1(1, 2)).toBe(2)
    

    此时addThenSub1变成了一个新的函数,最后再将参数作用在上面就可以得到结果。flow理论上可以支持任何数量的函数组合。然而,flow有个致命的问题,他要求上一个函数的返回值类型跟下一个函数的输入类型一致,例如,上面例子中的add如果返回string, 那么连接就失败了。另外对sub1的参数数量也有要求,即除了第一个函数add, 后面的函数只能接受一个参数。
    其实这两条限制就为函数的组合判了死刑,即:
    虽然函数是可以组合的,但并不是所有的函数都能任意组合。
    《范畴论》就是这样一门数学科学,他帮你抽象出了事物的转化或组合模式,你只要按照他总结的模式设计,就能将函数组合起来。

    作者:Richie Zhang
    声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    npm 安装Vue环境时报错
    WinSCP与SecureCRT
    LeetCode100---Same Tree
    LeetCode404---Sum of Left Leaves
    LeetCode283---Move Zeroes
    LeetCode344---Reverse String
    Java多线程一
    Java知识点总结
    Java泛型
    深入浅出设计模式学习笔记四:单例模式
  • 原文地址:https://www.cnblogs.com/richieyang/p/14323640.html
Copyright © 2020-2023  润新知