DEV Community

Cover image for DevLog 00002 - A main loop working
Nick Tchayka for NeoHaskell

Posted on

DevLog 00002 - A main loop working

This week I kept working on having a working Elm-style event-sourcing application main loop in NeoHaskell, and I managed it!

What does it look like to use this right now? Well, more or less like the following. Let’s say we want to write an app that reads a file and exits. Here’s an extremely contrived example:

type Model = Record
  '[ "content" := Text
   ]

initialModel :: Model
initialModel = ANON { content = "" }

data Message
  = ContentRetrieved Text
  | FailedToRead

init :: (Model, Command Message)
init = 
  ( initialModel, 
    File.read ANON
      { path = [path|test.txt|],
        onSuccess = ContentRetrieved,
        onFailure = \_ -> FailedToRead
      }
  )

update :: Model -> Message -> (Model, Command Message)
update model message =
  case message of

    ContentRetrieved text -> 
      (ANON { content = text }, Command.none)

    FailedToRead ->
      (ANON { content = "ERROR"}, Command.none)

view :: Model -> Html
view model =
  [html|
    <div>{model.content}</div>
  |]

main = Platform.init ANON
  { init = init,
    view = view,
    update = update
  }
Enter fullscreen mode Exit fullscreen mode

Don’t get too clinged to the syntax, as it will change in the future. I’m aware that it is not pretty 😄

If you know a bit of Elm, you might get it straight away, but if you don’t you probably are wondering how all of this works. Either way, you might be thinking that this is overkill for just reading a file and printing it, and you are right!

If you still have no idea what is happening here, don’t worry, documentation will be on its way once we finalize this first iteration, but to give you a quick hint: This is setting up a loop in the app where the update function gets executed each time an event gets registered in the app, in this case only once when the file gets read (or not). Because no more events happen, the application will end.

The view function is constantly rendering the model (at 60fps approximately).

Commands, update, and view, all run on different threads, ensuring that your app doesn’t choke on any of those.

Next step is to implement subscriptions, to allow doing much more fun stuff, like listening for interactions in the view, or listening for events from external places (like workers written in other programming languages like Python).

On top of that, tracing functions like print, or trace, are being prepared so they print to a separate thread and output too, which will end up in OpenTelemetry.

Either way, once I got the minimum things implemented for writing a simple build command I’ll merge this and probably work on a distribution script for everyone to try this :)

As usual, you’re invited to Discord and GitHub :D

Top comments (0)