type Model = { x : int }
type Msg = Increment | Decrement
let init () =
{ x = 0 }, Cmd.ofMsg Increment
let update msg model =
match msg with
| Increment -> { model with x = model.x + 1 }, Cmd.none
| Decrement -> { model with x = model.x - 1 }, Cmd.none
let view model dispatch =
div []
[
div [] [str (string model.x)]
button [OnClick (fun e -> dispatch Increment)] [str "+" ]
button [OnClick (fun e -> dispatch Decrement)] [str "-" ]
]
Program.mkProgram init update view
|> Program.run
复制代码
整个程序真的是太简洁易懂了,可能会有一些语法须要习惯,好比type Msg = Increment | Decrement
中的|
至关于就是或
,而match msg with
相似switch case
,可是功能强大不少。view里面的div [放HTML标签属性] [放子元素]
。整个程序几乎每一行都是在写本身的业务,冗余的内容不多,真是太优雅了。忍不住要把本身的第一篇文章要用来写这个。html
函数式编程的语言不少,能用作前端的彷佛也很多,包括fsharp, scala等。因为本人主要混在.net平台,因此对fsharp了解比较多。用fsharp写前端主要是靠Fable把fsharp编译成js(FSharp |> Fable |> Bable |> Webpack |> js)。前端
Elmish 是一个设计思想,应该是和mvvm平级,理念相似redux,可是时间是应该更早一点。具体能够参看https://elmish.github.io/elmish/。因此debug的时候也能够用redux的chrome插件查看状态等。vue
Fable只是一个编译器,除了view其余的都是单纯的逻辑,而view里面的东西能够是不少前端的框架技术好比react(上例用的就是), react native, 也能够是原生的html,或者vue等,可是Fable社区里面最流行的仍是react。因此react生态里的全部控件均可以使用,可是为了有fsharp的类型提醒须要写一些类型声明,这个相似于typescript的.d.ts里写的东西;因此社区里也有人写了一些工具把.d.ts的内容直接翻译成fsharp可以使用的类型(目前尚未试过)。固然也能够自行绑定原生js,好比须要引入npm的库的时候就要作这种事情。具体参见http://fable.io/docs/interacting.htmlreact
代码托管在https://github.com/albertwoo/Tetrisandroid
项目初始化是用社区里一个模板生成的[https://github.com/SAFE-Stack],包括的内容不少,如自动化编译,打包,热更新,测试等,代码也有不少如Client, Server, Test等,目前不须要Server,因此目前的主要代码都在src/Client下面。git
TetrisDomain.fs
定义了俄罗斯方块的基本类型以及一些操做好比操做Block,查看是否相撞,或者清除知足条件的行等。Square是指最小的马赛克方块,Block是指下落的物体:github
type Square = { Location: int * int; Color: int * int * int * float }
type BlockType = T | L | J | I | O | Z | RZ | X
type Block = { Type: BlockType; Squares: Square list }
type Action = Rotate | Left | Right | Down
...
复制代码
Tetris.fs
至关于写了一个组件,包括了状态,更新状态,以及界面的一些东西:chrome
type Model = {
SquareSize: int
Boundry: int * int
AllSquares: Square list
PreviewBlock: Block option
MovingBlock: Block option
PrectionBlock: Block option
IsOver: bool
Score: int
DefaultSpeed: int
Speed: int
SpeedCount: int }
type Msg = | Action of Action | ReachBottom | ReachLeft | ReachRight
复制代码
App.fs
是整个程序的入口,会把Tetris定义的东西整合进来,也包含了一些界面的布局,开始,暂停,从新开始等操做。typescript
type Model = {
Tetris: Tetris.Model
TimeCost: int
TouchStartPoint: (float * float) option
TouchMovingPoint: (float * float) option
TouchTime: DateTime option
IsPaused: bool
IsRestarting: bool
HideDetail: bool }
type Msg =
| TetrisMsg of Tetris.Msg
| BeginRestart | CancelRestart | Restart
| Tick
| TouchStart of float * float | TouchMove of float * float | TouchEnd of float * float
| Pause | Continue
| HideDetail
复制代码
整个程序的组件的拆分没有作得很好,逻辑不是很清晰,做为学习勉强接受吧。 整个效果以下,也能够在线体验,触控最佳,键盘勉强可用:npm
函数式编程彷佛离成为主流还有很长的路,在现代的服务器方面的应用应该比较多,毕竟微服务的流行致使框架和语言的选择变得更灵活。可是在前端方面的应用不多,android, xamarin等本地应用的开发都大量使用mvvm的设计模式。之前我开发过wpf,都是基于mvvm,如今开发angular几乎天然上手,设计思想一模一样。React却是特立独行,包括其中流行的redux状态管理也颇有独到之处。vue给个人感受就显得抱负很大什么都想作,可是我的浅尝后最后仍是选择了angular,毕竟有typescript的完美融合。
由于项目启动后已经使用了angular,可是也想利用redux的一些先进思想,后来尝试ngrx,可是发现须要写太多冗余的代码,并且分散在不少不一样的文件,加之js的语言特性,写actions, reducers, selectors的时候简直婆婆妈妈,让我失去耐心,冗余代码几乎遇上业务逻辑代码,因此最后仍是放弃。不过angular自己的设计已经在个人项目够用了,除了有点啰嗦。
面向对象还大行其道,而且对各类问题都有着成熟的解决方案,上面所言都是在下实践所得的经验,没有严格的理论支持,纯属我的妄言,听听就是,也可嗤之以鼻。