Elm語言

Elm是一個領域特定編程語言，用於聲明式地創建基於web瀏覽器的圖形用戶界面。Elm是純函數式的，開發它時強調了易用性、性能和健壯性。它宣傳為“實際上沒有運行時間異常”，Elm編譯器的靜態類型檢查使之成為可能。

**歷史**
Elm最初由Evan Czaplicki在2012年作為畢業論文《Elm：用於函數式GUI的併發FRP》而設計的author=csmith111cite web |last1=Czaplicki |first1=Evan |title=A Farewell to FRP |url=http://elm-lang.org/blog/farewell-to-frp |quote=When I started working on my thesis in 2011, I stumbled upon this academic subfield called Functional Reactive Programming (FRP). By stripping that approach down to its simplest form, I ended up with something way easier to learn than similar functional languages. Signals meant piles of difficult concepts just were not necessary in Elm. ……As The Elm Architecture emerged, it became clear that you could do almost all your Elm programming without thinking about signals at all. ……In the end, it was possible to remove signals because Elm has been moving towards an explicit emphasis on concurrency for quite some time now. ……Just like with my thesis, Concurrent FRP, the goal is to get the benefits of concurrency for free. ……Note: Interested readers may find  Lucid Synchrone interesting. Unfortunately for me, I had no idea my thesis had so much in common with synchronous programming languages at the time, but the connections are quite striking. I might argue that Elm was never about FRP. |website=elm |access-date=14 July 2018 |ref=farewell-to-frp |archive-date=2019-05-31 |archive-url=https://web.archive.org/web/20190531181806/https://elm-lang.org/blog/farewell-to-frp 。Elm的首次發行帶有很多例子和一個在線編輯器，使得易於在web瀏覽器中試驗它。Evan在2013年加入Prezi從事Elm的工作，並在2016年轉移到NoRedInk作為開源工程師，啟動了Elm軟件基金會。
Elm編譯器的最初實現執行目標為HTML、CSS和JavaScript。核心工具集持續的擴展，現在包括了REPL、包管理器、時間旅行調試器和針對macOS及Windows的安裝器。 Elm還有一個生態系統，包括社區創建的庫和Ellie，它是一個高級在線編輯器，允許保存工作和包含社區庫。

**特徵**
Elm有一個小集合的語言構造，包括傳統的if表達式，let表達式用於局部狀態，和case表達式用於模式匹配。作為函數式語言，它缺省的支持匿名函數，函數作為實際參數，和部份應用。它的語義包括不可變的值，無狀態函數，和具有類型推論的靜態類型。Elm程序通過虛擬的DOM呈現HTML，還可以使用“JavaScript作為服務”來與其他代碼進行互操作。

**不可變性**
在Elm中所有的值都是不可變的，這意味著一個值不能在創建之後修改。Elm使用持久性數據結構來實現它的Array、Dict和Set庫。

**靜態類型**
Elm是靜態類型的。類型標註（annotation）是可選的（由於有類型推論）但強烈鼓勵。標註存在於定義之上的一行（不同於C家族語言，這裡的類型和名字是夾雜在一起的）。Elm使用單一的冒號表達“擁有類型”。
類型包括原始類型如整數和字符串，和基本數據結構比如列表、元組和記錄。函數擁有用箭頭寫成的類型，例如round : Float -> Int。定製類型允許編程者建立定製類型，以匹配特定問題領域的方式來表示數據。
類型可以推論出其他類型，例如List Int。類型總是首字母大寫；小寫名字是類型變量。例如，List a是未知類型的值的列表。它是空列表和給List.length的實際參數的類型，對於這個列表的元素而言它是不可知的。有一些特殊類型，編程者建立用來與Elm運行時進行交互。例如，Html Msg表示（虛擬）DOM樹，其事件處理類型Msg的所有產生消息。
不再允許任何值是隱含的可空值（比如JavaScript的undefined或空指針），Elm的標準庫定義了Maybe a類型。產生或處理一個可選值的代碼不顯式的使用這個類型，而所有其他代碼得到保證聲稱了類型的值是實際上存在的。
Elm提供有限數目的內建類型類：number，它包括Int和Float，用來利用數值算符比如(+)或(*)；comparable，它包括數值、字符、字符串、可比較者的列表和可比較者的元組，用來利用比較算符；和appendable，它包括字符串和列表，用來利用(++)進行串接。Elm不提供將定製類型包括入這些類型類，或建立新類型類的機制（參見限制章節）。

**模塊系統**
Elm擁有模塊系統來允許用戶將其代碼分解到叫做模塊的更小的部份之中。模塊可以隱藏實現細節比如幫助函數，並組織有關的代碼在一起。模塊為可導入代碼充當名字空間，比如Bitwise.and。第三方庫（或包）構成自一個或多個模塊，並可從Elm公共庫中獲得到。所有的庫都採用語義版本號，這是編譯器和其他工具所強制的。就是說，移除一個函數或改變它的類型只能在主要發行中進行。

**同HTML、CSS和JavaScript的互操作**
Elm使用叫做端口的抽象來與JavaScript通信。它允許值流入和流出Elm程序，確使了在Elm和JavaScript之間的通信。
Elm有一個叫做elm/html的庫，編程者可以用來在Elm內書寫HTML和CSS。它使用虛擬DOM方式來使更新有效率。

**後端**
Elm官方上不支持服務器端開發。核心開發團隊不將它作為主要目標考慮，並且偏好聚焦於在增進前端開發體驗上的開發。儘管如此，有一些獨立的計劃，它們嘗試探索將Elm用於後端的可能性。這些計劃主要系附於Elm版本0.18.0，因為更新的版本不支持“原生”代碼和其他可利用特徵。有兩個嘗試將Elm用在BEAM（Erlang虛擬機）之上。其中一個計劃直接在這個環境上執行Elm，而另一個計劃把它編譯成Elixir。還有一個嘗試通過Node.js下部結構為Elm建立後端框架。這些計劃都沒有準備好用於生產。

**Elm架構**
Elm架構是建造交互式web應用的模式。Elm應用本質上以這種方式來構造，但是其他項目可能發現這個概念很有用。
Elm程序總是分解成三個部份：- 模型：這個應用的狀態，- 視圖：一個把模型轉變成HTML的函數，- 更新：一個基於消息更新模型的函數。
這些是Elm架構的核心。 
例如，想象顯示一個數值和在按下時增加這個數值的一個按鈕的一個應用。在這種情況下，所有我們需要存儲的是一個數值，所以我們的模型可以簡單的就是type alias Model = Int。view函數將用Html庫來定義並顯示這個數值和按鈕。為了讓這個數值被更新，我們需要能夠向update函數發送消息，這是通過定製類型比如type Msg = Increase來完成的。 Increase值被附著於在view函數內定義的按鈕，使得在用戶點擊這個按鈕的時候，Increase被傳遞到update函數之上，它可以通過增加這個數值來更新這個模型。
在Elm架構中，發送消息至update是改變狀態的唯一方式。在更加複雜的應用中，消息可以來自各種來源：用戶交互，模型初始化，來自update的內部調用，訂閱的外部事件（窗口改變大小、系統時鐘、JavaScript互操作等等）和URL變更及請求。

**限制**
Elm不支持高種類多態，這是同為函數式的語言Haskell和PureScript所提供的，Elm還不支持創建類型類。
這意味著，例如Elm沒有跨越多種數據結構如List和Set的通用的map函數。在Elm中，這種函數典型的要限定上它們的模塊名字來調用，例如調用List.map和Set.map。在Haskell或PureScript中，只有一個函數map。自從2015年這就是在Czaplicki的粗略路線圖上的一個周知的特徵要求。
另一個缺陷是在中到大型項目中有大量的Boilerplate code，如《Elm in Action》作者在他們的單一頁面應用例子中所展示的那樣，具有幾乎同樣的片段被重複於更新、視圖、訂閱、路由解析和建造函數之中。

**樣例代碼**
下面的例子代碼通過註釋展示了Elm的基本特徵：
-- 這是一個單一行註釋。
{-
這是一個多行註釋。
它是 {- 可嵌套的。 -}
-}
-- 這裡定義叫做greeting的一個值。類型被推論為String。
greeting =
"Hello World!"
-- 對頂層聲明最好增加類型標註。
hello : String
hello =
"Hi there."
-- 函數以相同方式聲明，具有跟隨在函數名字後的實際參數。
add x y =
x + y
-- 再次的，最好增加類型標註。
hypotenuse : Float -> Float -> Float
hypotenuse a b =
sqrt (a^2 + b^2)
-- 函數可以柯里化；這裡我們柯里化乘法中綴算符於數2之上。
multiplyBy2 : number -> number
multiplyBy2 =
(*) 2
-- If表達式用於在Bool值上的分支。
absoluteValue : number -> number
absoluteValue number =
if number  Int
depth tree =
case tree of
Empty ->
0
Node value left right ->
1 + max (depth left) (depth right)

**參見**
 PureScript：一個強類型的、純函數式的編譯成JavaScript的編程語言。- Reason：OCaml的語法擴展和工具鏈，也可以轉譯成JavaScript。- 函數式響應式編程

**引用**

**外部鏈接**
 archive-url=https://web.archive.org/web/20210117020553/https://project-awesome.org/sporto/awesome-elm