LISP 基础知识 LISP 是一种通用高级计算机程序语言,长期以来垄断人工智能领域的应用
LISP 作为应用人工智能而设计的语言,是第一个声明式系内函数式程序设计语言,有别于命令式系内过程式的 C,Fortran 和面向对象的 Java,Python 等结构化程序设计语言
数据类型
LISP 只有两种数据结构:
原子 atom:原子为标识符形式的符号或数字的字面值
表 list:表则是由零个或多个表达式组成的序列(不需要使用一般表处理所必需的任意插入及删除操作)
语句结构
LISP 的语法是简洁的典型,程序代码与数据的形式完全相同
以圆括号为边界的表:(A B C D)
数据:有 A,B,C,D 这4个元素的表
函数:将名为 A 的函数作用于 B,C 和 D 这3个参数
嵌套表结构亦是以圆括号来表示:(A(B C)D(E(F G)))
关键字
LISP 是一个函数式程序语言,并无关键字或保留字设,使用者可自行定义
Haskell 基础知识 Haskell 是一种函数式编程语言,专门设计用于处理符号计算和列表处理应用程序,有非限定性语义和强静态类型
数据类型
Haskell 支持的类型如下:
数字:Haskell 可以将某些数字解码为数字(无需像在其他编程语言中通常那样在外部指定它的数据类型)
字符:双引号或单引号中的单个字符
字符串:双引号中的多个字符
布尔型:True / False
列表:用逗号分隔的相同数据类型的集合
元组:在单个数据类型中声明多个值的方法(元组可以视为列表,但是元组和列表之间存在一些技术差异)
函数式编程 函数式编程是一种编程范式,除了函数式编程之外还有:命令式编程,声明式编程
命令式编程
命令式编程是面向计算机硬件抽象(变量、赋值语句、表达式、控制语句等)的编程
可以理解为命令式编程就是冯诺伊曼的指令序列,它的主要思想是关注计算机执行的步骤,即一步一步告诉计算机先做什么再做什么
例如:C语言中,要查找数组 numList 中大于5的所有数字
1 2 3 4 5 6 let results = []; for (let i = 0 ; i < numList.length; i++){ if (numList[i] > 5 ){ results.push(numList[i]) } }
声明式编程
声明式编程是以数据结构的形式来表达程序执行的逻辑
它的主要思想是告诉计算机应该做什么,但不指定具体要怎么做
例如:SQL语句
1 SELECT * FROM collection WHERE num > 5
函数式编程
函数式编程和声明式编程的思想是一致的:只关注做什么而不是怎么做
但函数式编程不仅仅局限于声明式编程
函数式编程是面向数学的抽象,将计算描述为一种表达式求值,其实,函数式程序就是一个表达式
函数式编程中的函数并不指计算机中的函数,而是指数学中的函数(即自变量的映射)
函数的值取决于函数的参数的值,不依赖于其他状态(例如:abs(x)
函数计算 x
的绝对值,只要 x
不变,最终的值都是一样)
函数是第一等公民:是指函数跟其它的数据类型一样处于平等地位,可以赋值给其他变量,可以作为参数传入另一个函数,也可以作为别的函数的返回值
1 2 3 4 5 6 7 8 9 var func1 = function func1 ( ) { } function func2 (fn ) { fn() } function func3 ( ) { return function ( ) {} }
函数是纯函数:纯函数是指相同的输入总会得到相同的输出,并且不会产生副作用的函数(函数内部的操作不会对外部产生影响)
函数式编程的基本运算
函数合成(compose):
案例一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function add (x ) { return x + 10 } function multiply (x ) { return x * 10 } function compose (f,g ) { return function (x ) { return f(g(x)); }; } console .log(multiply(add(2 ))) let calculate=compose(multiply,add); console .log(calculate(2 ))
案例二:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 function compose ( ) { let args = arguments ; let start = args.length - 1 ; return function ( ) { let i = start - 1 ; let result = args[start].apply(this , arguments ); while (i >= 0 ){ result = args[i].call(this , result); i--; } return result; }; } function add (str ) { return x + 10 } function multiply (str ) { return x * 10 } function minus (str ) { return x - 10 } let composeFun = compose(minus, multiply, add); composeFun(2 )
函数柯里化(Currying):
一个柯里化的函数首先会接受一些参数,接受了这些参数之后,该函数并不会立即求值,而是继续返回另外一个函数
刚才传入的参数在函数形成的闭包中被保存起来,待到函数被真正需要求值的时候,之前传入的所有参数都会被一次性用于求值
案例一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 function sum (a, b ) { return a + b; } console .log(sum(2 , 2 )) function sumCurry (a ) { return function (b ) { return a + b; } } console .log(sumCurry(2 )(2 )); var sumCurry=createCurry(sum); console .log(sumCurry(2 )(2 ));
案例二:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 function createCurry (func, arrArgs ) { var args = arguments ; var funcLength = func.length; var arrArgs = arrArgs || []; return function ( ) { var _arrArgs = Array .prototype.slice.call(arguments ); var allArrArgs = arrArgs.concat(_arrArgs) if (allArrArgs.length < funcLength) { return args.callee.call(this , func, allArrArgs); } return func.apply(this , allArrArgs); } } var sumCurry=createCurry(function (a, b, c ) { return a + b + c; }); sumCurry(1 )(2 )(3 ) sumCurry(1 , 2 , 3 ) sumCurry(1 )(2 ,3 ) sumCurry(1 ,2 )(3 )
高阶函数:满足下列条件之一的函数就可以称为高阶函数
案例一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 const fn = (() => { let students = []; return { addStudent (name ) { if (students.includes(name)) { return false ; } students.push(name); }, showStudent (name ) { if (Object .is(students.length, 0 )) { return false ; } return students.join("," ); } } })(); fn.addStudent("liming" ); fn.addStudent("zhangsan" ); fn.showStudent();
案例二:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 const plus = (...args ) => { let n = 0 ; for (let i = 0 ; i < args.length; i++) { n += args[i]; } return n; } const mult = (...args ) => { let n = 1 ; for (let i = 0 ; i < args.length; i++) { n *= args[i]; } return n; } const createFn = (fn ) => { let obj = {}; return (...args ) => { let keyName = args.join("" ); if (keyName in obj) { return obj[keyName]; } obj[keyName] = fn.apply(null , args); return obj[keyName]; } } let fun1 = createFn(plus);console .log(fun1(2 , 2 , 2 )); let fun2 = createFn(mult);console .log(fun2(2 , 2 , 2 ));
GHC - Haskell 编译器 GHC 就是 Haskell 的编译器,可以从如下网站中下载:
执行以下代码就可以完成安装:
1 2 sudo ./configure sudo make install