DEV Community

Cover image for Announcing NeoHaskell v0.2.0: Bringing Elm-Inspired Architecture to CLI Apps
Nick Tchayka for NeoHaskell

Posted on

Announcing NeoHaskell v0.2.0: Bringing Elm-Inspired Architecture to CLI Apps

We're excited to announce the release of NeoHaskell v0.2.0! This version marks a significant milestone in our journey to create a more accessible and powerful Haskell-based language. With this release, we're introducing a basic scaffolding for CLI applications inspired by Elm's architecture, along with substantial enhancements to our core library.

The Elm-Inspired CLI Architecture

One of the most exciting features in v0.2.0 is the introduction of, an Elm-inspired, event sourcing architecture for building CLI applications. This approach brings the clarity and maintainability of Elm's design to the world of command-line tools.

This architecture allows developers to create CLI apps with a clear separation of concerns, making it easier to reason about application state and user interactions.

Let's look at an example of how to build a simple CLI app:

module SimpleTodo (main) where import Core import Command qualified import Platform qualified type Model = Record '[ "todos" := Array Text, "currentInput" := Text ] data Message = AddTodo | UpdateInput Text | RemoveTodo Int | NoOp deriving (Show) init :: (Model, Command Message) init = let initialModel = ANON { todos = [], currentInput = "" } in (initialModel, Command.none) update :: Message -> Model -> (Model, Command Message) update message model = case message of AddTodo -> if Text.isEmpty model.currentInput then (model, Command.none) else ( model { todos = Array.push model.currentInput model.todos, currentInput = "" }, Command.none ) UpdateInput newInput -> (model {currentInput = newInput}, Command.none) RemoveTodo index -> ( model {todos = Array.removeAt index model.todos}, Command.none ) NoOp -> (model, Command.none) view :: Model -> Text view model = do let todoList = Text.joinWith "\n" model.todos let header = "Todo List:\n" let footer = "\nCurrent input: " ++ model.currentInput header ++ todoList ++ footer main :: IO () main = Platform.init (ANON {init = init, view = view, update = update}) 
Enter fullscreen mode Exit fullscreen mode

This example demonstrates the key components of the Elm-inspired architecture:

  1. Model: Represents the application state
  2. Message: Defines the possible events in the application
  3. init: Sets up the initial model and commands
  4. update: Handles state transitions based on messages
  5. view: Renders the current state as text
  6. main: Initializes the application using the Platform module

Expanded Core Library

We've significantly enhanced our core library to provide more powerful tools for NeoHaskell developers:

  • New concurrency primitives: Channel, Var, and ConcurrentVar
  • AsyncIO module for handling asynchronous operations
  • Extended Array module with useful functions like flatMap and forEach
  • Version module for parsing and working with semantic versions
  • The Unknown type for handling dynamic typing scenarios
  • A Record module for working with extensible records
  • New Json and Yaml modules for data serialization
  • An OptionsParser module to simplify CLI argument parsing
  • A Console module with built-in debugging capabilities

Trait System Enhancements

We've reorganized and expanded our trait system to provide a more cohesive and powerful set of abstractions:

  • Improved Appendable, Applicable, and Combinable traits
  • A new ToText trait for consistent string conversion across types

Get Involved

We're excited to see what the community builds with NeoHaskell v0.2.0! Here's how you can get started:

  1. Check out our GitHub repository for the latest code
  2. Join our Discord community to discuss ideas and get help
  3. Try building a small CLI app and share your experience

Your feedback and contributions are crucial as we continue to evolve NeoHaskell. Let's work together to create a more accessible and powerful development experience!

Happy coding!

Nick

Top comments (0)