Skip to the content.

REPL Guide

The Fun REPL (Read-Eval-Print Loop) provides an interactive development environment for experimenting with code and testing functions.

Table of Contents

Starting the REPL

Basic Startup

# Start the REPL
./fun

# You'll see the prompt
>

REPL Prompt

The REPL shows a simple > prompt and waits for input:

$ ./fun
>

Basic Usage

Simple Expressions

> 42
42 : Int

> `hello world`
hello world : Str

> 5 + 3
8 : Int

> True
True : Bool

Function Definitions

> inc = \x -> x + 1
<closure> : Lam<Int, Int>

> inc(5)
6 : Int

> double = \x -> x * 2
<closure> : Lam<Int, Int>

> double(10)
20 : Int

Complex Expressions

> factorial = fix(\rec -> \n ->
    when n == 0 is
        True -> 1;
        False -> n * rec(n - 1)
)
<closure> : Lam<Int, Int>

> factorial(5)
120 : Int

Pattern Matching

> safe_head = \list ->
    when list is
        Cons x xs -> Just x;
        Nil -> Nothing
<closure> : Lam<List<a>, Maybe<a>>

> safe_head([1, 2, 3])
Just 1 : Maybe<Int>

> safe_head([])
Nothing : Maybe<a>

REPL Features

Type Information

The REPL automatically shows type information for all expressions:

> 42
42 : Int

> \x -> x + 1
<closure> : Lam<Int, Int>

> [1, 2, 3]
[1, 2, 3] : List<Int>

Error Reporting

The REPL provides clear error messages:

> inc(5, 3)
Error: invalid number of arguments for function

> undefined_variable
Error: undefined variable: undefined_variable

> 5 + `hello`
Error: cannot apply non closure value of type Int

Multi-line Input

The REPL supports multi-line expressions:

> factorial = fix(\rec -> \n ->
    when n == 0 is
        True -> 1;
        False -> n * rec(n - 1)
)
<closure> : Lam<Int, Int>

Expression History

The REPL maintains a history of expressions (though not currently displayed):

> 1
1 : Int

> 2
2 : Int

> 3
3 : Int
# Previous expressions are remembered internally

Working with Modules

Importing in REPL

> import math from `./math`
<record> : {inc: Lam<Int, Int>, dec: Lam<Int, Int>}

> math.inc(5)
6 : Int

> math.dec(10)
9 : Int

Creating Modules in REPL

> # Define functions
> inc = \x -> x + 1
<closure> : Lam<Int, Int>

> dec = \x -> x - 1
<closure> : Lam<Int, Int>

> # Create module record
> math_module = {inc: inc, dec: dec}
{inc: <closure>, dec: <closure>} : {inc: Lam<Int, Int>, dec: Lam<Int, Int>}

> # Use the module
> math_module.inc(5)
6 : Int

Testing Module Functions

> # Import and test
> import utils from `./utils`
<record> : {head: Lam<List<a>, a>, tail: Lam<List<a>, List<a>>}

> utils.head([1, 2, 3])
1 : Int

> utils.tail([1, 2, 3])
[2, 3] : List<Int>

Debugging

Inspecting Values

> # Check function types
> inc
<closure> : Lam<Int, Int>

> # Check record structure
> person = {name: "Alice", age: 30}
{name: Alice, age: 30} : {name: Str, age: Int}

> person.name
Alice : Str

> person.age
30 : Int

Testing Edge Cases

> # Test with edge cases
> factorial(0)
1 : Int

> factorial(1)
1 : Int

> factorial(10)
3628800 : Int

> # Test error conditions
> safe_head([])
Nothing : Maybe<a>

Step-by-step Development

> # Build complex functions step by step
> add = \x, y -> x + y
<closure> : Lam<Int, Int, Int>

> add(3, 4)
7 : Int

> # Test the function
> add(10, 20)
30 : Int

> # Now use it in more complex expressions
> add(add(1, 2), add(3, 4))
10 : Int

Tips and Tricks

Quick Testing

> # Test arithmetic
> 1 + 2 * 3
7 : Int

> # Test string templates
> name = "Alice"
Alice : Str

> `Hello {name}!`
Hello Alice! : Str

> # Test boolean logic
> 5 == 5
True : Bool

> 3 == 7
False : Bool

Function Composition

> # Define simple functions
> inc = \x -> x + 1
<closure> : Lam<Int, Int>

> double = \x -> x * 2
<closure> : Lam<Int, Int>

> # Compose functions
> compose = \f, g, x -> f(g(x))
<closure> : Lam<Lam<b, c>, Lam<a, b>, Lam<a, c>>

> # Test composition
> compose(inc, double, 5)
11 : Int  # inc(double(5)) = inc(10) = 11

List Operations

> # Create lists
> numbers = [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5] : List<Int>

> # Test list functions
> head = \list ->
    when list is
        Cons x xs -> x;
        Nil -> error "empty list"
<closure> : Lam<List<a>, a>

> head(numbers)
1 : Int

> # Test with empty list
> head([])
Error: empty list

Type Exploration

> # Explore type inference
> id = \x -> x
<closure> : Lam<a, a>

> id(42)
42 : Int

> id(`hello`)
hello : Str

> id(True)
True : Bool

> # Test polymorphic functions
> const = \x, y -> x
<closure> : Lam<a, b, a>

> const(5, `hello`)
5 : Int

> const(`world`, 42)
world : Str

Interactive Development

> # Start with simple functions
> inc = \x -> x + 1
<closure> : Lam<Int, Int>

> # Test the function
> inc(5)
6 : Int

> # Refine the function
> inc = \x -> x + 1
<closure> : Lam<Int, Int>

> # Build more complex functions
> sum_range = fix(\rec -> \n ->
    when n == 0 is
        True -> 0;
        False -> n + rec(n - 1)
)
<closure> : Lam<Int, Int>

> # Test the complex function
> sum_range(10)
55 : Int

Exiting the REPL

To exit the REPL, use Ctrl+C (or Cmd+C on macOS):

> # Type Ctrl+C to exit
Goodbye!
$

Best Practices

Use Clear Variable Names

> # Good: descriptive names
> user_name = "Alice"
Alice : Str

> user_age = 30
30 : Int

> # Avoid: unclear names
> x = 42
42 : Int

Test Incrementally

> # Test each part separately
> add = \x, y -> x + y
<closure> : Lam<Int, Int, Int>

> add(1, 2)
3 : Int

> # Then use in larger expressions
> add(add(1, 2), add(3, 4))
10 : Int

Use Type Annotations for Clarity

> # Add type annotations for complex functions
> factorial : Lam<Int, Int>
> factorial = fix(\rec -> \n ->
    when n == 0 is
        True -> 1;
        False -> n * rec(n - 1)
)
<closure> : Lam<Int, Int>

The REPL is an excellent tool for learning Fun, testing functions, and developing code interactively. Use it to experiment with the language and verify your understanding of concepts.