Introduzione al linguaggio di programmazione Elm
Pubblicato: 2022-03-11Quando lo sviluppatore principale di un progetto molto interessante e innovativo ha suggerito di passare da AngularJS a Elm, il mio primo pensiero è stato: perché?
Avevamo già un'applicazione AngularJS ben scritta che era in uno stato solido, ben testata e collaudata in produzione. E Angular 4, essendo un degno aggiornamento di AngularJS, avrebbe potuto essere una scelta naturale per la riscrittura, così come React o Vue. Elm sembrava uno strano linguaggio specifico del dominio di cui le persone hanno a malapena sentito parlare.
Be', è stato prima che sapevo qualcosa di Elm. Ora, con una certa esperienza con esso, specialmente dopo essere passato ad esso da AngularJS, penso di poter dare una risposta a quel "perché".
In questo articolo, esamineremo i pro ei contro di Elm e come alcuni dei suoi concetti esotici si adattano perfettamente alle esigenze di uno sviluppatore web front-end. Per un articolo in lingua Elm più simile a un tutorial, puoi dare un'occhiata a questo post del blog.
Elm: un linguaggio di programmazione puramente funzionale
Se sei abituato a programmare in Java o JavaScript e ritieni che sia il modo naturale di scrivere codice, imparare Elm può essere come cadere nella tana del coniglio.
La prima cosa che noterai è la strana sintassi: niente parentesi, tante frecce e triangoli.
Potresti imparare a vivere senza parentesi graffe, ma come definisci e annida i blocchi di codice? Oppure, dov'è il ciclo for
, o qualsiasi altro ciclo, se è per questo? Sebbene l'ambito esplicito possa essere definito con un blocco let
, non ci sono blocchi nel senso classico e nessun ciclo.
Elm è un linguaggio client Web puramente funzionale, fortemente tipizzato, reattivo e guidato dagli eventi.
Potresti iniziare a chiederti se la programmazione sia anche possibile in questo modo.
In realtà, queste qualità si sommano per darti un incredibile paradigma di programmazione e sviluppo di un buon software.
Puramente Funzionale
Potresti pensare che utilizzando la versione più recente di Java o ECMAScript 6, puoi eseguire la programmazione funzionale. Ma questa è solo la superficie.
In quei linguaggi di programmazione, hai ancora accesso a un arsenale di costrutti linguistici e la tentazione di ricorrere alle parti non funzionali di esso. Il punto in cui si nota davvero la differenza è quando non si può fare altro che una programmazione funzionale. È a quel punto che alla fine inizi a sentire quanto può essere naturale la programmazione funzionale.
In Elm, quasi tutto è una funzione. Il nome del record è una funzione, il valore del tipo di unione è una funzione: ogni funzione è composta da funzioni parzialmente applicate ai suoi argomenti. Anche gli operatori come più (+) e meno (-) sono funzioni.
Per dichiarare un linguaggio di programmazione puramente funzionale, piuttosto che l'esistenza di tali costrutti, l'assenza di tutto il resto è di fondamentale importanza. Solo allora puoi iniziare a pensare in modo puramente funzionale.
Elm è modellato su concetti maturi di programmazione funzionale e assomiglia ad altri linguaggi funzionali come Haskell e OCaml.
Fortemente tipizzato
Se programmi in Java o TypeScript, allora sai cosa significa. Ogni variabile deve avere esattamente un tipo.
Alcune differenze esistono, ovviamente. Come con TypeScript, la dichiarazione del tipo è facoltativa. Se non presente, verrà dedotto. Ma non esiste un tipo "qualsiasi".
Java supporta tipi generici, ma in un modo migliore. I generici in Java sono stati aggiunti in seguito, quindi i tipi non sono generici se non diversamente specificato. E per usarli abbiamo bisogno della brutta sintassi <>
.
In Elm, i tipi sono generici se non diversamente specificato. Diamo un'occhiata a un esempio. Supponiamo di aver bisogno di un metodo che prenda una lista di un tipo particolare e restituisca un numero. In Java sarebbe:
public static <T> int numFromList(List<T> list){ return list.size(); }
E, in lingua olmo:
numFromList list = List.length list
Sebbene facoltativo, suggerisco vivamente di aggiungere sempre dichiarazioni di tipo. Il compilatore Elm non consentirebbe mai operazioni su tipi errati. Per un essere umano, è molto più facile commettere un errore del genere, soprattutto durante l'apprendimento della lingua. Quindi il programma sopra con le annotazioni di tipo sarebbe:
numFromList: List a -> Int numFromList list = List.length list
All'inizio può sembrare insolito dichiarare i tipi su una riga separata, ma dopo qualche tempo inizia a sembrare naturale.
Lingua del client web
Ciò significa semplicemente che Elm si compila in JavaScript, quindi i browser possono eseguirlo su una pagina web.
Detto questo, non è un linguaggio generico come Java o JavaScript con Node.js, ma un linguaggio specifico del dominio per scrivere la parte client delle applicazioni web. Inoltre, Elm include sia la scrittura della logica aziendale (cosa fa JavaScript), sia la parte di presentazione (cosa fa HTML), il tutto in un linguaggio funzionale.
Tutti questi sono fatti in un modo molto specifico, simile a un framework, chiamato The Elm Architecture.
reattivo
L'architettura Elm è un framework web reattivo. Eventuali modifiche ai modelli vengono visualizzate immediatamente nella pagina, senza esplicita manipolazione del DOM.
In questo modo, è simile ad Angular o React. Ma anche Elm lo fa a modo suo. La chiave per comprenderne le basi è nella firma delle funzioni di view
e update
:
view : Model -> Html Msg update : Msg -> Model -> Model
Una vista Elm non è solo la vista HTML del modello. È HTML che può produrre messaggi di tipo Msg
, dove Msg
è un tipo esatto di unione che definisci.
Qualsiasi evento di pagina standard può produrre un messaggio. E, quando viene prodotto un messaggio, Elm chiama internamente la funzione di aggiornamento con quel messaggio, che quindi aggiorna il modello in base al messaggio e al modello corrente e il modello aggiornato viene nuovamente visualizzato internamente nella vista.
Evento guidato
Proprio come JavaScript, Elm è basato sugli eventi. Ma a differenza, ad esempio, di Node.js, in cui vengono fornite singole callback per le azioni asincrone, gli eventi Elm sono raggruppati in insiemi discreti di messaggi, definiti in un tipo di messaggio. E, come con qualsiasi tipo di unione, le informazioni che contengono valori di tipo separati potrebbero essere qualsiasi cosa.
Esistono tre fonti di eventi che possono produrre messaggi: azioni dell'utente nella vista Html
, esecuzione di comandi ed eventi esterni a cui ci siamo iscritti. Ecco perché tutti e tre i tipi, Html
, Cmd
e Sub
contengono msg
come argomento. Inoltre, il tipo di msg
generico deve essere lo stesso in tutte e tre le definizioni, lo stesso fornito alla funzione di aggiornamento (nell'esempio precedente era il tipo di Msg
, con la M maiuscola), in cui tutta l'elaborazione dei messaggi è centralizzata.
Codice sorgente di un esempio realistico
Puoi trovare un esempio completo di applicazione web Elm in questo repository GitHub. Sebbene sia semplice, mostra la maggior parte delle funzionalità utilizzate nella programmazione client quotidiana: recupero di dati da un endpoint REST, decodifica e codifica di dati JSON, utilizzo di viste, messaggi e altre strutture, comunicazione con JavaScript e tutto ciò che è necessario per compilare e impacchettare Codice Elm con Webpack.
L'applicazione visualizza un elenco di utenti recuperati da un server.
Per un processo di configurazione/dimostrazione più semplice, il server di sviluppo di Webpack viene utilizzato sia per impacchettare tutto, incluso Elm, sia per servire l'elenco dell'utente.
Alcune funzionalità sono in Elm e altre in JavaScript. Questo viene fatto intenzionalmente per un motivo importante: mostrare l'interoperabilità. Probabilmente vorrai provare Elm per iniziare, o passare gradualmente al codice JavaScript esistente o aggiungere nuove funzionalità nel linguaggio Elm. Con l'interoperabilità, la tua app continua a funzionare con codice Elm e JavaScript. Questo è probabilmente un approccio migliore rispetto all'avvio dell'intera app da zero in Elm.
La parte Elm nel codice di esempio viene prima inizializzata con i dati di configurazione da JavaScript, quindi l'elenco degli utenti viene recuperato e visualizzato nel linguaggio Elm. Diciamo che alcune azioni utente sono già implementate in JavaScript, quindi invocare un'azione utente in Elm invia semplicemente la chiamata ad essa.
Il codice utilizza anche alcuni dei concetti e delle tecniche spiegati nella sezione successiva.
Applicazione dei concetti di olmo
Esaminiamo alcuni dei concetti esotici del linguaggio di programmazione Elm in scenari del mondo reale.
Tipo di unione
Questo è l'oro puro della lingua degli olmi. Ricordi tutte quelle situazioni in cui è necessario utilizzare dati strutturalmente diversi con lo stesso algoritmo? È sempre difficile modellare queste situazioni.
Ecco un esempio: immagina di creare un'impaginazione per la tua lista. Alla fine di ogni pagina, dovrebbero esserci collegamenti alle pagine precedenti, successive e tutte in base al numero. Come lo strutturate per contenere le informazioni su quale collegamento l'utente ha cliccato?
Possiamo utilizzare più callback per i clic precedenti, successivi e sui numeri di pagina, oppure possiamo utilizzare uno o due campi booleani per indicare cosa è stato cliccato, o dare un significato speciale a particolari valori interi, come numeri negativi, zero, ecc. Ma nessuno dei queste soluzioni possono modellare esattamente questo tipo di evento utente.
In Elm, è molto semplice. Definiremmo un tipo di unione:
type NextPage = Prev | Next | ExactPage Int
E lo usiamo come parametro per uno dei messaggi:
type Msg = ... | ChangePage NextPage
Infine, aggiorniamo la funzione per avere un case
per verificare il tipo di nextPage
:
update msg model = case msg of ChangePage nextPage -> case nextPage of Prev -> ... Next -> ... ExactPage newPage -> ...
Rende le cose molto eleganti.
Creazione di più funzioni della mappa con <|
Molti moduli includono una funzione map
, con diverse varianti da applicare a un numero diverso di argomenti. Ad esempio, List
ha map
, map2
, … , fino a map5
. Ma cosa succede se abbiamo una funzione che accetta sei argomenti? Non c'è map6
. Ma c'è una tecnica per superarlo. Usa <|
funzione come parametro e funzioni parziali, con alcuni degli argomenti applicati come risultati intermedi.
Per semplicità, supponiamo che una List
abbia solo map
e map2
e vogliamo applicare una funzione che accetta tre argomenti su tre liste.
Ecco come appare l'implementazione:
map3 foo list1 list2 list3 = let partialResult = List.map2 foo list1 list2 in List.map2 (<|) partialResult list3
Supponiamo di voler usare foo
, che moltiplica semplicemente i suoi argomenti numerici, definiti come:
foo abc = a * b * c
Quindi il risultato di map3 foo [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5]
è [1,8,27,64,125] : List number
.
Decostruiamo quello che sta succedendo qui.
Innanzitutto, in partialResult = List.map2 foo list1 list2
, foo
viene applicato parzialmente a ogni coppia in list1
e list2
. Il risultato è [foo 1 1, foo 2 2, foo 3 3, foo 4 4, foo 5 5]
, un elenco di funzioni che accetta un parametro (poiché i primi due sono già applicati) e restituisce un numero.
Il prossimo in List.map2 (<|) partialResult list3
, è in realtà List.map2 (<|) [foo 1 1, foo 2 2, foo 3 3, foo 4 4, foo 5 5] list3
. Per ogni coppia di queste due liste, chiamiamo la funzione (<|)
. Ad esempio, per la prima coppia, è (<|) (foo 1 1) 1
, che è uguale a foo 1 1 <| 1
foo 1 1 <| 1
, che è lo stesso di foo 1 1 1
, che produce 1
. Per il secondo, sarà (<|) (foo 2 2) 2
, che è foo 2 2 2
, che restituisce 8
e così via.
Questo metodo può essere particolarmente utile con le funzioni mapN
per la decodifica di oggetti JSON con molti campi, poiché Json.Decode
li fornisce fino a map8
.
Rimuovi tutti i valori Nothing da un elenco di Maybes
Diciamo che abbiamo un elenco di valori Maybe
e vogliamo estrarre solo i valori dagli elementi che ne hanno uno. Ad esempio, l'elenco è:
list : List (Maybe Int) list = [ Just 1, Nothing, Just 3, Nothing, Nothing, Just 6, Just 7 ]
E vogliamo ottenere [1,3,6,7] : List Int
. La soluzione è questa espressione di una riga:

List.filterMap identity list
Vediamo perché funziona.
List.filterMap
si aspetta che il primo argomento sia una funzione (a -> Maybe b)
, che viene applicata agli elementi di un elenco fornito (il secondo argomento) e l'elenco risultante viene filtrato per omettere tutti i valori Nothing
, quindi il valore reale i valori sono estratti da Maybe
s.
Nel nostro caso, abbiamo fornito identity
, quindi l'elenco risultante è di nuovo [ Just 1, Nothing, Just 3, Nothing, Nothing, Just 6, Just 7 ]
. Dopo averlo filtrato, otteniamo [ Just 1, Just 3, Just 6, Just 7 ]
e, dopo l'estrazione del valore, è [1,3,6,7]
, come volevamo.
Decodifica JSON personalizzata
Poiché le nostre esigenze di decodifica (o deserializzazione) JSON iniziano a superare ciò che è esposto nel modulo Json.Decode
, potremmo avere problemi a creare nuovi decoder esotici. Questo perché questi decodificatori vengono invocati dalla metà del processo di decodifica, ad esempio all'interno dei metodi Http
, e non è sempre chiaro quali siano i loro input e output, specialmente se ci sono molti campi nel JSON fornito.
Di seguito sono riportati due esempi per mostrare come gestire tali casi.
Nel primo, abbiamo due campi in JSON in entrata, a
, che denotano i lati di un'area rettangolare b
Ma, in un oggetto Elm, vogliamo solo memorizzare la sua area.
import Json.Decode exposing (..) areaDecoder = map2 (*) (field "a" int) (field "b" int) result = decodeString areaDecoder """{ "a":7,"b":4 }""" -- Ok 28 : Result.Result String Int
I campi vengono decodificati individualmente con il field int
decoder, quindi entrambi i valori vengono forniti alla funzione fornita in map2
. Poiché anche la moltiplicazione ( *
) è una funzione e richiede due parametri, possiamo semplicemente usarla in questo modo. L' areaDecoder
risultante è un decoder che restituisce il risultato della funzione quando applicato, in questo caso, a*b
.
Nel secondo esempio, stiamo ottenendo un campo di stato disordinato, che può essere nullo o qualsiasi stringa inclusa vuota, ma sappiamo che l'operazione è riuscita solo se è "OK". In tal caso, vogliamo memorizzarlo come True
e per tutti gli altri casi come False
. Il nostro decoder si presenta così:
okDecoder = nullable string |> andThen (\ms -> case ms of Nothing -> succeed False Just s -> if s == "OK" then succeed True else succeed False )
Applichiamolo ad alcuni JSON:
decodeString (field "status" okDecoder) """{ "a":7, "status":"OK" }""" -- Ok True decodeString (field "status" okDecoder) """{ "a":7, "status":"NOK" }""" -- Ok False decodeString (field "status" okDecoder) """{ "a":7, "status":null }""" -- Ok False
La chiave qui è nella funzione fornita a andThen
, che prende il risultato di un precedente decodificatore di stringa nullable (che è un Maybe String
), lo trasforma in tutto ciò di cui abbiamo bisogno e restituisce il risultato come decoder con l'aiuto di succeed
.
Chiave da asporto
Come si può vedere da questi esempi, la programmazione in modo funzionale potrebbe non essere molto intuitiva per gli sviluppatori Java e JavaScript. Ci vuole del tempo per abituarsi, con molti tentativi ed errori. Per aiutarti a capirlo, puoi usare elm-repl
per esercitare e controllare i tipi di ritorno delle tue espressioni.
Il progetto di esempio collegato in precedenza in questo articolo contiene molti altri esempi di decodificatori e codificatori personalizzati che potrebbero anche aiutarti a capirli.
Ma ancora, perché scegliere Elm?
Essendo così diverso dagli altri framework client, il linguaggio Elm non è certamente "l'ennesima libreria JavaScript". In quanto tale, ha molti tratti che possono essere considerati positivi o negativi rispetto a loro.
Cominciamo prima con il lato positivo.
Programmazione client senza HTML e JavaScript
Infine, hai una lingua in cui puoi fare tutto. Niente più separazioni e combinazioni imbarazzanti della loro miscelazione. Nessuna generazione di HTML in JavaScript e nessun linguaggio di creazione di modelli personalizzato con alcune regole logiche ridotte.
Con Elm, hai solo una sintassi e una lingua, nella sua piena gloria.
Uniformità
Poiché quasi tutti i concetti sono basati su funzioni e poche strutture, la sintassi è molto concisa. Non devi preoccuparti se qualche metodo è definito a livello di istanza o di classe, o se è solo una funzione. Sono tutte funzioni definite a livello di modulo. E non ci sono cento modi diversi per iterare gli elenchi.
Nella maggior parte delle lingue, c'è sempre questo argomento sul fatto che il codice sia scritto nel modo della lingua. Molti modi di dire devono essere padroneggiati.
In Elm, se compila, è probabilmente il modo "Elm". Se no, beh, di certo non lo è.
Espressività
Sebbene concisa, la sintassi di Elm è molto espressiva.
Ciò si ottiene principalmente attraverso l'uso di tipi di unione, dichiarazioni di tipo formali e lo stile funzionale. Tutti questi ispirano l'uso di funzioni più piccole. Alla fine, ottieni il codice che è praticamente auto-documentante.
Nessun Nulla
Quando usi Java o JavaScript per molto tempo, null
diventa qualcosa di completamente naturale per te, una parte inevitabile della programmazione. E, sebbene vediamo costantemente NullPointerException
se vari TypeError
s, non pensiamo ancora che il vero problema sia l'esistenza di null
. È così naturale .
Diventa subito chiaro dopo un po' di tempo con Elm. Non avere null
non solo ci solleva dal vedere più e più volte errori di riferimento null di runtime, ma ci aiuta anche a scrivere codice migliore definendo e gestendo chiaramente tutte le situazioni in cui potremmo non avere il valore effettivo, riducendo così anche il debito tecnico non posticipando null
maneggiare finché qualcosa non si rompe.
La fiducia che funzionerà
La creazione di programmi JavaScript sintatticamente corretti può essere eseguita molto rapidamente. Ma funzionerà davvero? Bene, vediamo dopo aver ricaricato la pagina e testata a fondo.
Con Elm, è il contrario. Con il controllo del tipo statico e i controlli null
forzati, è necessario del tempo per la compilazione, specialmente quando un principiante scrive un programma. Ma, una volta compilato, ci sono buone probabilità che funzioni correttamente.
Veloce
Questo può essere un fattore importante nella scelta di un framework client. La reattività di un'app Web estesa è spesso cruciale per l'esperienza dell'utente e quindi per il successo dell'intero prodotto. E, come dimostrano i test, Elm è molto veloce.
Pro di Elm vs Framework tradizionali
La maggior parte dei framework Web tradizionali offre potenti strumenti per la creazione di app Web. Ma quel potere ha un prezzo: un'architettura eccessivamente complicata con molti concetti e regole diversi su come e quando usarli. Ci vuole molto tempo per padroneggiare tutto. Ci sono controller, componenti e direttive. Poi ci sono le fasi di compilazione e configurazione e la fase di esecuzione. E poi, ci sono servizi, fabbriche e tutto il linguaggio dei modelli personalizzato utilizzato nelle direttive fornite: tutte quelle situazioni in cui dobbiamo chiamare $scope.$apply()
direttamente per aggiornare la pagina e altro ancora.
Anche la compilazione di Elm in JavaScript è certamente molto complicata, ma lo sviluppatore è protetto dal dover conoscerne tutti i dettagli. Basta scrivere un po' di Elm e lasciare che il compilatore faccia il suo lavoro.
E perché non scegliere Elm?
Basta lodare Elm. Ora, vediamo alcuni dei suoi lati meno eccezionali.
Documentazione
Questo è davvero un grosso problema. La lingua Elm manca di un manuale dettagliato.
I tutorial ufficiali sfogliano semplicemente la lingua e lasciano molte domande senza risposta.
Il riferimento API ufficiale è anche peggio. Molte funzioni mancano di qualsiasi tipo di spiegazione o esempio. E poi ci sono quelli con la frase: “Se questo è fonte di confusione, lavora attraverso l'Elm Architecture Tutorial. Aiuta davvero!” Non è la linea migliore che vuoi vedere nei documenti API ufficiali.
Si spera, questo cambierà presto.
Non credo che Elm possa essere ampiamente adottato con una documentazione così scarsa, specialmente con persone provenienti da Java o JavaScript, dove tali concetti e funzioni non sono affatto intuitivi. Per comprenderli, è necessaria una documentazione molto migliore con molti esempi.
Formato e spazio bianco
Sbarazzarsi di parentesi graffe o parentesi e utilizzare lo spazio bianco per il rientro potrebbe sembrare piacevole. Ad esempio, il codice Python sembra molto pulito. Ma per i creatori di elm-format
, non era abbastanza.
Con tutti gli spazi di doppia riga e le espressioni e le assegnazioni divise in più righe, il codice Elm appare più verticale che orizzontale. Quello che sarebbe un one-liner nel buon vecchio C può facilmente estendersi a più di uno schermo nel linguaggio Elm.
Questo può suonare bene se vieni pagato con righe di codice scritte. Ma, se vuoi allineare qualcosa con un'espressione iniziata 150 righe prima, buona fortuna nel trovare il giusto rientro.
Gestione dei record
È difficile lavorare con loro. La sintassi per modificare il campo di un record è brutta. Non esiste un modo semplice per modificare i campi nidificati o per fare riferimento arbitrariamente ai campi per nome. E se stai usando le funzioni di accesso in modo generico, ci sono molti problemi con la digitazione corretta.
In JavaScript, un record o un oggetto è la struttura centrale che può essere costruita, accessibile e modificata in molti modi. Anche JSON è solo una versione serializzata di un record. Gli sviluppatori sono abituati a lavorare con i record nella programmazione web, quindi le difficoltà nella loro gestione in Elm possono diventare evidenti se vengono utilizzati come struttura dati primaria.
Più digitazione
Elm richiede più codice da scrivere rispetto a JavaScript.
Non esiste una conversione di tipo implicita per le operazioni su stringhe e numeri, quindi sono necessarie molte conversioni int-float e in particolare le chiamate toString
, che quindi richiedono parentesi o simboli dell'applicazione di funzione per corrispondere al numero corretto di argomenti. Inoltre, la funzione Html.text
richiede una stringa come argomento. Sono necessarie molte espressioni di maiuscole e minuscole, per tutti quei Maybe
s, Results
, tipi, ecc.
La ragione principale di ciò è il sistema di tipo rigoroso e può essere un prezzo equo da pagare.
Decodificatori e codificatori JSON
Un'area in cui spicca più la digitazione è la gestione di JSON. Ciò che è semplicemente una chiamata JSON.parse()
in JavaScript può estendersi su centinaia di righe nel linguaggio Elm.
Ovviamente è necessaria una sorta di mappatura tra le strutture JSON e Elm. Ma la necessità di scrivere sia i decoder che i codificatori per lo stesso pezzo di JSON è un problema serio. Se le tue API REST trasferiscono oggetti con centinaia di campi, questo sarà molto lavoro.
Incartare
Abbiamo visto su Elm, è tempo di rispondere alle famose domande, probabilmente vecchie quanto gli stessi linguaggi di programmazione: è migliore della concorrenza? Dovremmo usarlo nel nostro progetto?
La risposta alla prima domanda può essere soggettiva, poiché non tutti gli strumenti sono un martello e non tutto è un chiodo. Elm può brillare ed essere una scelta migliore rispetto ad altri framework di client Web in molti casi mentre non è all'altezza in altri. Ma offre un valore davvero unico che può rendere lo sviluppo del front-end web molto più sicuro e semplice rispetto alle alternative.
Per la seconda domanda, per evitare di rispondere anche con l'antico “dipende”, la risposta semplice è: Sì. Anche con tutti gli svantaggi menzionati, solo la sicurezza che Elm ti dà sulla correttezza del tuo programma è una ragione sufficiente per usarlo.
Anche la codifica in Elm è divertente. È una prospettiva totalmente nuova per chiunque sia abituato ai paradigmi di programmazione web “convenzionali”.
Nell'uso reale, non è necessario passare immediatamente l'intera app a Elm o avviarne una nuova completamente. Puoi sfruttare la sua interoperabilità con JavaScript per provarlo, iniziando con una parte dell'interfaccia o alcune funzionalità scritte nel linguaggio Elm. Scoprirai rapidamente se è adatto alle tue esigenze e poi ne amplierai l'utilizzo o lo lascerai. E chissà, potresti anche innamorarti del mondo della programmazione web funzionale.