龙空技术网

函数式编程中的战斗机(二)---elm语言MUV设计模式应用实例

神足自在 212

前言:

而今兄弟们对“elm模型案例分析”大约比较关切,姐妹们都需要知道一些“elm模型案例分析”的相关知识。那么小编也在网上网罗了一些关于“elm模型案例分析””的相关知识,希望你们能喜欢,同学们一起来了解一下吧!

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为初始值。

--Main
 
Main =
 Browser.sandbox { init = 0, model = model ,update = update, view = view }
 
-- Model
Type alias Model = Int
 
Init : 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,把结论和论据都完满收尾。

-- UPDATE
 
Type Msg = Increment | Decrement
 
Update msg -> model ->model
Update msg model =
 Case msg of
 Increment ->
 Model + 1
 
 Decrement ->
 Model - 1

2.4 声明“V”生成界面

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

-- VIEW
 
View : 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模型案例分析