Elm裡的type system相對haskell做了不少簡化,一個是 type alias
,一個是 union type
。先來說說type好了: 以下你可以在你的elm-repl 或是線上的elm-repl試試。
例子來自 elm guide
> "hello"
"hello" : String
> not True
False : Bool
> round 3.1415
3 : Int
> [ "Alice", "Bob" ]
[ "Alice", "Bob" ] : List String
> \n -> n / 2
<function> : Float -> Float
不管是什麼,每一個東西都有type,你沒有寫type,elm會幫你推測,你大概要什麼。所以你自己的程式,要把type加上去,叫 type annotations
half : Float -> Float
half n =
n / 2
divide : Float -> Float -> Float
divide x y =
x / y
如果elm 內建的沒有你要的type 呢?或是一直重複打字也很麻煩:
hasBio : { name : String, bio : String, pic : String } -> Bool
hasBio user =
String.length user.bio >
像這個 hasBio
是一個record type, 但是要自己打這麼長嗎? 可以改寫成:
type alias User =
{ name : String
, bio : String
, pic : String
}
hasBio : User -> Bool
hasBio user =
String.length user.bio > 0
這樣就不會那麼麻煩了。
那 union types
又是在幹麼的呢? 我覺得最好的例子就是elm 內建的Maybe
type Maybe a = Just a | Nothing
那什麼時候會用到這個union type 呢?
完整的code在這裡
type Msg
= SetQuery String
| DeleteById Int
-- other code here
update : Msg -> Model -> Model
update msg model =
case msg of
SetQuery input ->
{ model | query = input }
DeleteById id ->
{ model |
results = List.filter (\result -> result.id /= id) model.results
}
通常我們會和 case expression
一起使用,如上,在 union type Msg 裡,我們有 SetQuery
和DeleteById
我們可以把它當成是一個 function
, SetQuery
可以吃一個 String
, 而DeleteById
可以吃一個 Int
viewSearchResult : SearchResult -> Html Msg
viewSearchResult result =
li []
[ span [ class "star-count" ] [ text (toString result.stars) ]
, a [ href ("https://github.com/" ++ result.name), target "_blank" ]
[ text result.name ]
, button
[ class "hide-result"
, onClick ( DeleteById result.id )
]
[ text "X" ]
]
這裡,在這個按鈕裡, onClick
有看到 DeleteById
嗎? 你如果在elm-repl裡試試
> import Html.Events exposing (..)
> onClick
<function> : msg -> Html.Attribute msg
> type Msg = SetQuery String | DeleteById Int
> onClick (DeleteById 4)
{ key = "EVENT", realKey = "click", value = { options = { stopPropagation = False, preventDefault = False }, decoder = <decoder> } }
: Html.Attribute Repl.Msg
這裡的 msg
是可以給我們自行定義的,我們有定義一個 Msg
是union type,所以按下去後,會傳出這個 msg, msg -> Html.Attribute msg
我們可以看做是 a -> Html.Attribute a
這個 a
是你自己定義的也好,或是內建的 String
也好,總之是要一樣的type
啊,我個人覺得document寫得不太好,一下小寫的msg, 一下大寫的MSG,如果對type想要更瞭解,推薦學習haskell
(學完後,所有的type system language都不是問題了。)
如果還是不太能理解,我們之後實做有機會再多說一點,總之,記得要有type annotations,自己定義的只有兩種,一個是type
alias, 一個是union type。