@函数式编程中的战斗机(二) —运用elm语言MUV设计模式做一个简单的应用实例

1 elm语言设计模式的特点

1.1 面向对象设计模式的特点

每种编程语言都有其独特的语法和优缺点,从而导致与众不同的设计模式和固定架构。面向对象编程因其竭力接近和模拟现实世界的多态和继承,导致面向对象产生了工厂架构等多种设计模式。这些设计的多样性,对于面向对象编程的老手来说,条条大路通罗马,采用那种设计模式都无碍于其实现最终的目标。而对于新手而言,众多面向对象的设计模式令其眼花缭乱无所适从。因此,区别不在于采取的设计模式优劣之分,而在于对编程基础和编程艺术的理解深度。

1.2 函数式编程设计模式的特点

面向对象设计模式众多,那么函数式编程的设计模式又如何呢?
函数式编程强调功能的抽象、代码的简洁、可读性以及可以重复利用的特点。特别是柯里化(curry)后的功能函数嵌套,可以堆积木般产生许多创造力和生产力。因此函数式编程的设计模式遵循这样一个原则:凡有利于引导开发者在实现目标的过程中,不知不觉把功能进一步抽象成为模块函数,在实现目的的同时也完成模块的构建,就是好的设计模式。有点象生产汽车的智能化工厂,在组装出一辆高质量的汽车同时,也完成了组装线的设计生产,这就是函数式编程的设计模式。
要实现引导的效果,必定不能就面向对象编程的随心所欲:万物皆对象,见天地人是对象,见蛇虫鼠蚁也是对象,分分钟建个类,父类子类继承、方法属性引用,创造出自己的世界,甚至不管这个世界是真实世界的反映,还是无关现实。
函数式编程的模式天生是严谨固定的,因为函数式编程的基础起源是数学中的范畴学,而数学是严谨可推理的。一个功能模块的抽象必然是经过数学分析推敲后的提炼,而并非文学想象中的发散性思维。

1.3 elm语言的“MUV”设计模式

这种数学的严谨在elm语言的设计模式中体现得淋漓尽致,甚至苛刻。Elm语言设计模式严格限定为MUV架构。
其中“M”是指“model”模型,相当于react或Vue中的“state”状态。说是状态有点不恰当,因为react或Vue中强调的是组件概念,而“组件+状态=对象”,对象是面对象编程的范式。Elm作为函数式编程的范式,“M”就定义为模型,模型可以是一个数、一个字符,甚至一个复杂的函数,但是一就是一,纯净没有副作用。模型是程序代码的核心,所有的功能变化,都是围绕模型展开。
“U”指的是“update”更新,相当于电脑CPU或发动机引擎,也是一个函数,内置各种操作,但必须以收到指令为前提。指令可以是鼠标或键盘的操作,可以是内置时钟的定时到点,POST或GET到的一段JSON数据,甚至是NOTHING。只有收到动作或讯息,update引擎就一丝不苟地按照内置的流程规定,对模型进行操作,输出一个全新的模型。
“V”是指“view”界面,众所周知,elm是用于前端的函数式编程语言,也是可以直接应用于生产系统的语言,它是为取代javascript、Html和Css三剑客混搭而来,怎么能少得了前端界面的生成功能?View其实也是一个函数,类似于react中的render,但它用的不是JSX语法,而是更易懂和严谨的函数语法。想象一个,一个Html页面就是一个View函数,随时调用,多么美妙的事情。
“MUV”构成了elm函数式设计的固定模式,每段程序、每个模块都以这三个结构为核心,大结构中有小结构、小结构中有微结构。有如分形与混沌,又如须弥世界与大千世界,elm的世界就是如此坚固又扎实地构建起来。
随了MUV外,还有些辅助的函数,如Msg代表消息行动,依附于“U”,Init代表初始化函数,依附于“M”,还有main函数,通常是程序启动的开始。
“MUV”结构中,数据是单向流动的,消息动作由外界中来,“U”收到后发动引擎,对“M”进行修改和更新。而“V”依据“M”的更新而生成界面。由于elm和react一样,也是运用了虚拟DOM的技术,因此对于真实Html页面的渲染速度更快更强。

2 MVU模式实现一个鼠标点击计数器实例

2.1 导入基本库

首先是导入一些基本的标准库,包括了Html页面虚拟Dom、浏览器操作Browser、鼠标键盘事件的Events库,这些库都是elm内置的,并非Javascript库。要使用javascript库与之互动沟通,需要通过一种被称为“Port”码头的简单技巧实现,elm之所以这样做,是有意要把elm函数式编程与多范式的javascrip隔开,保持纯净,不受其影响。

Import Browser
Import Html exposing (Html,button,text)
Import Html.Events exposing (onClick)

2.2 启动主程序和声明模型初始化

使用Browser库建立一个沙箱,其中声明了 “MUV”架构,模型是一个数字,初始值设为0。在沙箱中和init : Model中有两次初始值的声明,以笔者经验,在sandbox中的声明会优先,如sandbox中init = 10,而随后的init : Model中再次声明为0,实际运行时数字会以10为初始值。

--MainMain =Browser.sandbox { init = 0, model = model ,update = update, view = view }-- Model
Type alias Model = IntInit : Model
Init = 0

2.3 声明“U”模型更新引擎

引擎先是声明一个Msg函数,里面有Increment“加”和Decrement“减”两个行为,注意:只是纯声明,并不说明细节,细节在下列的Case中再行说明。Elm语言有个特定,声明类的函数表达如同结论在前,论点在后的论述文写法,先讲结论,再一个个细节敲定,这是一种框架在前的系统性思维。在随后的 update类型签名中,明确看到update引擎是从msg发起,作用于model,再次作用于model三个动作顺序。然后是具体的细节敲定:通过 case of msg语法,把increment敲定为model+1,而decrement敲定为model-1,把结论和论据都完满收尾。

-- UPDATEType Msg = Increment | DecrementUpdate msg -> model ->model
Update msg model = Case msg of Increment ->Model  +  1Decrement ->Model  -  1

2.4 声明“V”生成界面

View还是声明式类型签名,model直接生成Html界面。在界面语言中可以看到函数式表示法的痕迹,先是div []函数,然后是buttong[]函数,再是text 函数。Div用于布局和层次,button 用于按键,按键的作用是 Decrement或 Increment,而text用于显示文字。中间的text 显示是把模型(一个数字)直接转化为字符串文字显示出来。

-- VIEWView : Model -> Html Msg
View : model = Div [][  button [  onClick Decrement  ] [  text “-”  ],  div []  [  text  (String.fromInt model) ],  button [  onClick Increment  ] [   text “+”  ]

2.5 实际效果



如此,简单的几行代码,便把一个单页面应用给写出来了,不用html和javascrtipt混搭,而且高效、简洁、纯净。更重要的是,在写代码的过程中,我们自然而然地按照模型定义、更新引擎、生成界面三个框架开展,先声明再细节,让自己的思维有迹可循,逻辑清晰,这就是函数式编程的“MUV”模式。

函数式编程中的战斗机(二) --运用elm语言MUV设计模式做一个简单的应用实例相关推荐

  1. 函数式编程中的战斗机--elm编写实例(薛定鄂的猫

    函数式编程中的战斗机--elm编写实例(薛定鄂的猫) 1.初始设置 2.薛定谔的猫 3.定义规则 4.建立模型 5.建立更新模型的逻辑 6.构建前端界面 7.连接代码 8.运行程序 1.初始设置 今天 ...

  2. elm具体实现过程_函数式编程中的战斗机(二)---elm语言MUV设计模式应用实例...

    1 elm语言设计模式的特点 1.1 面向对象设计模式的特点 每种编程语言都有其独特的语法和优缺点,从而导致与众不同的设计模式和固定架构.面向对象编程因其竭力接近和模拟现实世界的多态和继承,导致面向对 ...

  3. 多角度让你彻底明白yield语法糖的用法和原理及在C#函数式编程中的作用

    如果大家读过dapper源码,你会发现这内部有很多方法都用到了yield关键词,那yield到底是用来干嘛的,能不能拿掉,拿掉与不拿掉有多大的差别,首先上一段dapper中精简后的Query方法,先让 ...

  4. 函数式编程中的组合子

    函数式编程是一个比较大的话题,里面的知识体系非常的丰富,在这里我并不想讲的特别的详细.为了应对实际中的应用,我们讲一下函数式编程中最为实用的应用方式--组合子.组合子本身是一种高阶函数,他的特点就是将 ...

  5. Python函数式编程中map()、reduce()和filter()函数的用法

    Python中map().reduce()和filter()三个函数均是应用于序列的内置函数,分别对序列进行遍历.递归计算以及过滤操作.这三个内置函数在实际使用过程中常常和"行内函数&quo ...

  6. 函数式编程中的两个棘手问题

    作者 | Matthew Butt­erick 译者 | 弯月 出品 | CSDN(ID:CSDNnews) 大约从十年前,我开始使用Lisp编程语言,后来我喜欢上了函数式编程.每当使用非Lisp语言 ...

  7. 如何在函数式编程中存在时间函数?

    本文翻译自:How can a time function exist in functional programming? I've to admit that I don't know much ...

  8. 2. Python函数式编程中的字符串,元组,函数的分类,高阶函数,一篇文章都介绍一遍

    函数式编程中的字符串 在函数式编程中,经常用到 Python 字符串,因其是不可变数据结构. 字符串本身是一个对象,具备很多对象方法,与常识中函数的使用不太相同,例如下述代码 my_str = &qu ...

  9. 简单介绍函数式编程中的Functor(函子),Applicative(加强版函子),Monad(单子)

    原文地址:http://skaka.me/blog/2015/12/19/functor-applicative-monad-scala-haskell/ 如果你是刚接触函数式编程,可能很容易被下面这 ...

最新文章

  1. codeforces#597 C. Constanze's Machine(简单dp)
  2. sphinx-release 2.1.4
  3. LeetCode——分治
  4. XCTF-高手进阶区:Web_php_unserialize(详解)
  5. linux下性能测试mon,Linux性能评测工具之一:nmon篇
  6. WCF 基础 契约 和 绑定
  7. (开源)微信小程序实时控制stc89c51,通过esp8266
  8. php文章详情页排版,WordPress自定义文章详情页模板
  9. 《软件随想录》读书笔记
  10. 网站访问量统计的重要指标
  11. 临床公共数据库挖掘系列1---seer数据库注册
  12. 在Win32下使用OpenGL
  13. 计算机音乐谱子 追光者,岑宁儿《追光者》简谱
  14. 微信云开发配置自有域名(短信跳转小程序)
  15. matlab 图像二值化 后0、1像素的个数统计
  16. 生日悖论 Birthday Paradox 至少有两人同一天生日概率
  17. 【C语言】用递归编写程序计算Hermite Polynomials(厄密多项式)
  18. 强哥语录摘抄(郑强教授)
  19. TCP协议(Socket,ServerSocket)
  20. ExtJS 6 的一些 样式类配置项

热门文章

  1. word文档如何重新另起序号/继续编号
  2. 兼容IE与FF浏览器的CSS技巧总结
  3. 数学建模系列-评价模型(五)---灰色综合评价法
  4. HRnet之目标检测环境搭建指南
  5. C#之:并行编程 -4
  6. 纯量产经验 | 谈谈目标检测中正负样本的问题
  7. 布局“负数”的妙用——少年自负凌云笔(未完待续)
  8. 方法返回多个值,使用Pair,Triple
  9. TP5框架的生命周期
  10. (DT系列三)系统启动时, dts 是怎么被加载的