函数式编程基础(F#,JS)

  前面三篇是关于javascript的函数式特性:

  1. javascript之典型高阶函数
  2. javascript之典型高阶函数二
  3. javascript之Partial Application

  索性就把形式化方法从头复习一遍吧,顺便也温习下f#,并尝试使用javascript来表现一下,同时也会加入C#作为对比。关于f#,请阅读维基百科:F#

  为什么要学习函数式编程?原因有太多,每个人都有他们的说法。而对于我,因为当我第一次在C#中使用LINQ、使用Lambda时,感到非常惊讶,怎么会有这样的用法?但当时仅仅停留在使用的层面,没能理解为什么,或者是怎么做到的。直到学习了这门课程之后,我才真正明白。所以这就是原因,很简单。

基础

  首先是基础部分,看一下如何定义类型。比如我们要定义名为"day"的类型。这个"day"可以是Monday,Tuesday,...,Sunday。下面呢,看看三个版本的定义,首先是F#:

1 type day =
2   | Monday
3   | Tuesday
4   | Wednesday
5   | Thursday
6   | Friday
7   | Saturday
8   | Sunday

  在F#中,type是定义类型的关键字,定义的构造函数的首字母必须大写如应该是"Monday"而不是"monday"。"|"后面的每一个值都是day类型的。第二个是javascript版本的:

 1 var day = function(name){
 2     this.name = name;   
 3 }
 4 var Monday = new day("Monday"),
 5     Tuesday = new day("Tuesday"),
 6     Wednesday = new day("Wednesday"),
 7     Thursday = new day("Thursday"),
 8     Friday = new day("Friday"),
 9     Saturday = new day("Saturday"),
10     Sunday = new day("Sunday");

  在javascript中,day作为一个类,然后其他都是day的实例,跟F#比起来是有点麻烦。这应该是一种表现,有其它更好的方式还望高手告知。最后呢是我们最熟悉的C#啦:

abstract class day
{
}
class Monday:day
{
}
class Tuesday:day
{
}
class Wednesday:day
{
}
class Thursday:day
{
}
class Friday:day
{
}
class Saturday:day
{
}
class Sunday:day
{
}

  在C#代码里,使用了抽象类做类型,其他都从它继承。很明显的,在表达能力上F#最简洁。有了类型后,再定义一个使用此类型的函数:

1 let next_weekday (d:day) : day =
2   match d with
3   | Monday -> Tuesday
4   | Tuesday -> Wednesday
5   | Wednesday -> Thursday
6   | Thursday -> Friday
7   | Friday -> Monday
8   | Saturday -> Monday
9   | Sunday -> Monday

  上面定义一名为"next_weekday"的函数,后边括号中接受一个参数"d","d:day"中冒号后边指的是类型,最后的" : day"表示函数的返回类型是day,"="后面很明显就是函数体啦。函数体中"Monday -> Tuesday"中的箭头右边表示返回值。所以这个函数就是下一个“工作日”,周一的下一个工作日是周二,那“箭头”是最自然、直接的表达方式,一目了然。再看看其它两个版本的:

 1 function next_weekday(d){
 2     switch(d.name){
 3     case "Monday": return new day("Tuesday");
 4     case "Tuesday": return new day("Wednesday");
 5     case "Wednesday": return new day("Thursday");
 6     case "Thursday": return new day("Friday");
 7     case "Friday": return new day("Monday");
 8     case "Saturday": return new day("Monday");
 9     case "Sunday": return new day("Monday");
10     }
11 }

  

day next_weekday(day d)
{
    switch(d.ToString())
    {
        case "Monday": return (new Tuesday());
        case "Tuesday": return (new Wednesday());
        case "Wednesday": return (new Thursday());
        case "Thursday": return (new Friday());
        case "Friday": return (new Monday());
        case "Saturday": return (new Monday());
        case "Sunday": return (new Monday());
        default:return null;
    }
}

  这样定义完了函数,就可以先做一个单元测试。同样的先看F#的:

printfn "%A\n" (next_weekday Friday)
printfn "%A\n" (next_weekday (next_weekday Saturday))

//结果:
Monday
Tuesday

  同样地,javascript与C#的测试:

console.log(next_weekday(Friday));
console.log(next_weekday(next_weekday(Saturday)));

//结果:
day {name: "Monday"}
day {name: "Tuesday"} 

  

1 Console.WriteLine(next_weekday(new Friday()));
2 Console.WriteLine(next_weekday(next_weekday(new Saturday())));

//结果:
Monday
Tuesday

  测试结果都是OK的啦。使用F#又是最简洁的哦。而且语义上面也是最直接的。不知道你是否会爱上F#,嘿嘿。再来定义一个类型,只有True和False的Boolean类型。大家都知道这个类型除了C语言没有,其他语言都内置了,现在我们就自己来实现一下:

type bool =
  | True
  | False
var bool = function(b){
    if(b==="True" || b==="False") this.name=b;
}
abstract class bools
{
}
class True
{
}
class False
{
}

  其中C#中bool为关键字,所以把它改成了bools。如果抛开逻辑,只看类型貌似没啥意义,根本体现不出布尔的特性,所以加上一些辅助函数把这些特性表现出来。他们别是:取反、或和与操作。

let negb (b:bool) : bool = 
  match b with
  | True -> False
  | False -> True

let andb (b1:bool) (b2:bool) : bool = 
  match b1 with 
  | True -> b2 
  | False -> False

let orb (b1:bool) (b2:bool) : bool = 
  match b1 with 
  | True -> True
  | False -> b2
function negb(b){
    if(b.name==="True") return new bool("False");
    if(b.name==="False") return new bool("True");
}
function andb(b1,b2){
    if(b1.name==="True") return b2;
    else return new bool("False");
}
function orb(b1,b2){
    if(b1.name==="True") return new bool("True");
    else return b2;
}
bools negb(bools b)
{
    if(b.GetType().ToString()=="False")
        return new True();
    return new False();
}
bools andb(bools b1,bools b2)
{
    if(b1.GetType().ToString()=="False")
        return new False();
    return b2;
}
bools orb(bools b1,bools b2)
{
    if(b1.GetType().ToString()=="True")
        return new True();
    return b2;
}

  测试和结果就不贴了,上面主要做了一些类型定义方面的工作。感觉javascript在实现的时候有点奇怪,各读者心理也明白这是弱点,也是优点!F#在做类型定义的时候非常直接,简洁。而C#主要就是通过结构体或类来做定义。还是F#更让人喜欢:)

原文地址:https://www.cnblogs.com/mike442144/p/2868774.html