A functional, reactive and some what type safe javascript library to build UIs
Elvish is heavily inspired from elm-architecture, it is an effort to implement the type safe and functional architecture that elm provides in a non typed language like javascript.
Getting Started
The logic of every Elvish program will break up into three cleanly separated parts:
- Model — the state of your application
- Update — a way to update your state
- View — a way to view your state as HTML
Counter Example
Here is a Code Sandbox
;; const Model = // init :: Modelconst Init = Model // Msg = Increment | Decrementconst Msg = ; // update :: Model -> Msg -> Modelconst Update = Msg // view :: Model -> Html Msgconst View = // Runconst Root = document; ;
Side Effect example
Here is a Code Sandbox
; const Model = // init :: Modelconst Init = Model''false'https://jsonplaceholder.typicode.com/todos/1' // Msg :: FetchData | FetchedData | FetchErrorconst Msg = ; // getJson :: String -> Effect err { number, string }const getJson = // fetchUserData :: String -> Effect FetchError FetchedDataconst fetchUserData = Effect // update :: Model -> Msg -> Model | (Model, Effect)const Update = Msg // view :: Model -> Html Msgconst View = ; // Runconst Root = document; ;
Performance
Elvish uses Inferno as its Vdom which makes it insanely fast, even faster than React and Elm itself.
Here is the jS-benchmark
Types
Record
- Example
const Model = // Returns a type constructor Model(counter, text) const model = Model // create new Model console // 0 console // hello world
- Type safe
const Model = const model = Model // wrong type passed to record
Union Type
Union types are an important part of an elvish application.
- Example
const Bool =
- Adding instance methods to union types.
const T = true const Maybe = Maybe { return Maybe; }; const just = Maybe const nothing = MaybeNothing nothing; // => Nothing just; // => Just(2)
- Pattern Matching
const Action = const initState = number: 0 showNumber: false const reducer = Action
Effect type
Effect types are used to run side effects in an elvish application. Effects is a structure for time-dependent values.
Basically the idea is to abstract the side effects from your pure code and running them separately, so your code stays pure even when you are doing side effects.
You can think of an elvish application as pure and functional code running in an imperative shell.
- Example
const executeEffect = Effect
Only way to run Effects in an elvish application is to return a tuple from the update function containing [ Model, Effect ].
model
Instances
// Constructing Effect // b -> Effect(a, b) // Constructs a new Effect containing the given successful value. Effect // a -> Effect(a, b) // Constructs a new Effect containing the given failure value. Effect // () -> Effect(a, b) // Constructs a Effect that will never resolve. // Transforming Effect // Effect(a, b) => (b -> c) -> Effect(a, c) // Transforms the successful value of the Effect using a regular unary function. Effect // Effect(a, b) => (b -> Effect(a, c)) -> Effect(a, c) // Transforms the succesful value of the Effect using a function over monads. Effect // Effect(a, b) => (a -> Effect(c, b)) -> Effect(c, b) // Transforms the failure value of the Effect into a new Effect. Effect // Effect(a, b) => (a -> c), (b -> c) -> Effect(d, c) // Applies a function to each side of the Effect. Effect // Effect(a, b) => { Rejected: a -> c, Resolved: b -> c } → Effect(d, c) // Applies a function to each side of the Effect. Effect // Effect(a, b) => (a -> c), (b -> d) -> Effect(c, d) // Maps both sides of the Effect.