Catalyst

Elm 笔记(1):计数器

想学点新东西,同时看下函数式编程是什么样的,所以开始看Elm。不过函数式编程对我来说还是太陌生了,所以强制自己写点博文理解。

初步目标是根据官方文档的三个例子(Buttons,Text Fields,Forms)来做分析。这篇是第一篇,根据Button的计数器。

📝 官方例子地址

概念

Main

-- MAIN

main =
  Browser.sandbox { init = init, update = update, view = view }
  • main在 Elm 里是个特殊的值,它描述什么该显示在屏幕上。这里程序将用init初始化,view显示,update填充用户输入。
  • Browser.sandboxBrowser是 Elm 的浏览器模块,允许用户创建在浏览器中运行的Elm程序。Browser下不同的模块对页面有不同的控制能力:
    • sandbox只处理和用户的交互,不能通信;
    • element能对外通信;
    • document在其上能控制页面的 title, body 等元素 ;
    • application制作完整的单页 app。 能输入的参数也不同,下略。参考这个页面中对 Elm 运行时的说明

Model

-- MODEL

type alias Model = Int

init : Model
init =
  0
  • 数据模型管理所有程序数据的细节。在计数器程序中就是计数的数量。
  • type alias表示类型别名,这里用ModelInt型。

View

-- VIEW

view : Model -> Html Msg
view model =
  div []
    [ button [ onClick Decrement ] [ text "-" ]
    , div [] [ text (String.fromInt model) ]
    , button [ onClick Increment ] [ text "+" ]
    ]
  • view描述数据显示的方法。
  • view : Model -> Html Msg表示view为接受Model类型,输出Html Msg类型的函数。
  • Elm 中的函数和通常的表现方法不一样,为<函数名> [参数...]>view model即为参数为modelview函数。

Update

-- UPDATE

type Msg = Increment | Decrement

update : Msg -> Model -> Model
update msg model =
  case msg of
    Increment ->
      model + 1

    Decrement ->
      model - 1
  • update函数描述model如何变化。
  • type Msg = Increment | Decrement定义了一个自定义类型Msg。它可以为Increment也可以是Decrement
  • update : Msg -> Model -> Model表示update接受Msg类型,输出一个函数(输入Model,输出Model类型的函数)。从概念上讲,每个函数只接受一个参数,但它可以返回带接受一个参数的函数。表现起来就像接受两个参数的函数。(见这里)

练习

最后完成文档后留的作业:给计数器添加“重置”键。

module Main exposing (..)

import Browser
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)



-- MAIN


main =
  Browser.sandbox { init = init, update = update, view = view }



-- MODEL

type alias Model = Int

init : Model
init =
  0


-- UPDATE

type Msg = Increment | Decrement | Reset

update : Msg -> Model -> Model
update msg model =
  case msg of
    Increment ->
      model + 1

    Decrement ->
      model - 1

    Reset ->
      0


-- VIEW

view : Model -> Html Msg
view model =
  div []
    [ button [ onClick Decrement ] [ text "-" ]
    , div [] [ text (String.fromInt model) ]
    , button [ onClick Increment ] [ text "+" ]
    , button [ onClick Reset ] [ text "Reset" ]
    ]