Skip to main content

Your first Elara program

This guide will walk you through writing, compiling, and running your first Elara program.
Make sure you have installed Elara before continuing.
1

Create your source file

Create a file named hello.elr with the following content:
hello.elr
def main : IO ()
let main = println "Hello, World!"
This simple program defines a main function that prints “Hello, World!” to the console. The type IO () indicates that main performs an I/O operation and returns unit (nothing).
2

Compile your program

Compile the program using the elara build command:
elara build hello.elr
This will generate JVM bytecode in the build/ directory.
3

Run your program

Run the compiled program using either the interpreter or JVM:
elara run hello.elr --target interp
You should see:
Hello, World!

Understanding the program

Let’s break down what’s happening in this simple program:
  • def main : IO () — Declares the type signature for main. It takes no arguments and performs I/O operations
  • let main = ... — Defines the implementation of main
  • println — A built-in function that prints a string followed by a newline
  • The string "Hello, World!" is passed to println

More examples

1

Working with numbers

def main : IO ()
let main = 
    let x = 5
    let y = 10
    println ("The sum is: " ++ toString (x + y))
This example shows:
  • Local bindings with let
  • String concatenation with ++
  • Converting numbers to strings with toString
2

Pattern matching with lists

import Prelude
import Elara.Prim
import List

def sum : List Int -> Int
let sum ls =
    match ls with
        Nil -> 0
        Cons x xs -> x + sum xs

def main : IO ()
let main = 
    let numbers = [1, 2, 3, 4, 5]
    println ("Sum: " ++ toString (sum numbers))
This demonstrates:
  • Pattern matching on lists with match...with
  • Recursive functions
  • The Cons and Nil constructors for lists
3

Higher-order functions

import Prelude
import Elara.Prim
import List
import String

def map : (a -> b) -> List a -> List b
let map f list =
    match list with
        Nil -> Nil
        Cons x xs -> Cons (f x) (map f xs)

def main : IO ()
let main = 
    let numbers = [1, 2, 3, 4, 5]
    let squared = map (\x -> x * x) numbers
    println ("Squared: " ++ listToString squared)
This example shows:
  • Generic type parameters (a and b)
  • Lambda expressions with \x -> ...
  • Higher-order functions (functions that take functions as arguments)

Compiler commands

elara build <file>

Debugging with dump targets

You can inspect intermediate compilation stages using the --dump flag:
elara build hello.elr --dump=typed,core,jvm
Available dump targets:
  • lexed — Lexer output (tokens)
  • parsed — Parser output (AST)
  • desugared — Desugared AST
  • renamed — After name resolution
  • shunted — After operator precedence
  • typed — After type checking
  • core — Core IR
  • ir — JVM IR
  • jvm — JVM bytecode info

Common patterns

IO sequencing

Use the *> operator to sequence multiple IO operations:
let main = 
    println "First line" *>
    println "Second line" *>
    println "Third line"

Importing modules

import Prelude           -- Core functions
import List              -- List operations
import String            -- String functions
import Option            -- Optional values
import Result            -- Error handling

Next steps

Language guide

Learn about Elara’s type system, pattern matching, and more

Examples

Browse more complex examples and real-world patterns

Standard library

Explore the built-in functions and types

Join the community

Get help and connect with other Elara developers

Build docs developers (and LLMs) love