miso-lynx - A Haskell mobile framework

4 months ago 3

A tasty Haskell mobile framework 🍜 🐈 📱

Matrix #haskell-miso:matrix.org Haskell Cachix Build Status Hackage LICENSE

Miso Lynx 🍜 is a mobile framework that uses miso and LynxJS 🐈 for building iOS and Android applications. Miso Lynx uses LynxJS 🐈 to facilitate drawing to native iOS UIView and Android ViewGroup, and for interacting with APIs on the device.

The Haskell miso project 🍜 is excited to be an open-source technology partner with innovative China 🇨🇳 technology companies like ByteDance 🦾, creators of the #1 global app 🌎 TikTok and LynxJS 🐈, to advance native mobile app development 📱 in the functional programming space.

As seen at ReactSummit by @huxpro !

Alt text

The Haskell miso portion is queued here.

To run the example locally execute the following command

$ git clone [email protected]:dmjio/miso-lynx.git $ http-server ./miso-lynx/examples

This will host the main.lynx.bundle which can be loaded into the LynxExplorer for interactive development.

Note

You will need to have the LynxExplorer installed which works with the iOS simulator. Please see the LynxJS getting started guide for installation.

Warning

miso-lynx depends on the latest version of miso (version 1.9), this includes custom renderers (ala React Renderer) and Components as well. Currently all event handling and drawing are performed on the main thread. Selectively scheduling Haskell code on the Lynx MTS / BTS is ongoing research. This project is under heavy development and is considered experimental.

To start developing applications with miso-lynx you will need to acquire GHC and cabal. This can be done via GHCup or Nix.

Tip

For new Haskell users we recommend using GHCup to acquire both GHC and cabal

This file contains a simple miso-lynx counter application.

----------------------------------------------------------------------------- {-# LANGUAGE DataKinds #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} ----------------------------------------------------------------------------- module Main where ----------------------------------------------------------------------------- import Miso import Miso.Lynx ----------------------------------------------------------------------------- import Miso.Lens import Miso.String import qualified Miso.Style as CSS ----------------------------------------------------------------------------- -- | Type synonym for an application model newtype Model = Model { _value :: Int } deriving (Show, Eq, ToMisoString) ----------------------------------------------------------------------------- value :: Lens Model Int value = lens _value $ \m v -> m { _value = v } ----------------------------------------------------------------------------- data Action = AddOne | SubtractOne | SayHelloWorld | Tap Int deriving (Show, Eq) ----------------------------------------------------------------------------- -- | Entry point for a miso application main :: IO () main = run $ native counterComponent { events = nativeEvents , initialAction = Just SayHelloWorld } ----------------------------------------------------------------------------- counterComponent :: Component Model Action counterComponent = component (Model 0) updateModel viewModel ----------------------------------------------------------------------------- updateModel :: Action -> Effect Model Action updateModel SayHelloWorld = io_ (consoleLog "Inside Say Hello World!") updateModel AddOne = do io_ (consoleLog "Inside AddOne") value += 1 updateModel SubtractOne = do io_ (consoleLog "Inside SubtractOne") value -= 1 updateModel (Tap x) = io_ $ consoleLog ("tapped: " <> ms (show x)) ----------------------------------------------------------------------------- -- | Constructs a virtual DOM from a model viewModel :: Model -> View Action viewModel m = view_ [ CSS.style_ [ CSS.height "200px" , CSS.display "flex" , CSS.alignItems "center" , CSS.justifyContent "center" ] ] [ view_ [ onTap AddOne , id_ "plus" , CSS.style_ [ CSS.backgroundColor CSS.yellow , CSS.width "100px" , CSS.height "100px" , CSS.margin "2px" , CSS.display "flex" , CSS.alignItems "center" , CSS.justifyContent "center" ] ] [ text_ [ CSS.style_ [ CSS.fontSize "48px" ] ] [ "🐈" ] ] , view_ [ CSS.style_ [ CSS.backgroundColor CSS.orange , CSS.width "100px" , CSS.height "100px" , CSS.display "flex" , CSS.alignItems "center" , CSS.justifyContent "center" ] ] [ text_ [ CSS.style_ [ CSS.fontSize "48px" ] ] [ text $ ms (m ^. value) ] ] , view_ [ onTap SubtractOne , id_ "minus" , CSS.style_ [ CSS.backgroundColor CSS.pink , CSS.width "100px" , CSS.height "100px" , CSS.margin "2px" , CSS.display "flex" , CSS.alignItems "center" , CSS.justifyContent "center" ] ] [ text_ [ CSS.style_ [ CSS.fontSize "48px" ] ] [ "🍜" ] ] ] -----------------------------------------------------------------------------

Now that your project files are populated, development can begin.

This will entails creating a LynxExplorer application with the jsaddle-warp hot-reload package. This will require using rspack and the BTS to access WebSockets via the lynx object.

nix users on a Linux or OSX distros can take advantage of a binary cache for faster builds. To use the binary cache follow the instructions on cachix.

Tip

We highly recommend nix users consume the cachix cache. cachix use haskell-miso-cachix.

$ cachix use haskell-miso-cachix

@dmjio

Feel free to dive in! Open an issue or a submit Pull Request.

See CONTRIBUTING for more info.

BSD3 © dmjio

Read Entire Article