View Source cure_std (cure v0.1.0)
Cure Programming Language - Standard Library Runtime
Provides core runtime functions that cannot be implemented in pure Cure due to their need for Erlang-specific features. This module contains the essential low-level operations for I/O, monadic operations, FSM integration, and value serialization.
Architecture
This module represents the boundary between pure Cure code and the underlying Erlang runtime. Most standard library functions are now implemented in Cure itself (in lib/std/), but this module contains the irreducible core that requires direct Erlang integration.
Core Responsibilities
- Monadic Operations: Implementation of Result/Option pipe semantics
 - I/O Operations: Console output and formatting functions
 - FSM Integration: Bridge to FSM runtime system
 - Value Serialization: Converting Cure values to string representations
 - Runtime Utilities: Low-level operations for runtime system
 
Function Categories
Monadic Operations
pipe/2- Monadic pipe operator implementationis_monad/1- Type checking for Result/Option values
I/O Functions
print/1- Output without newlineprintln/1- Output with newlineshow/1- Convert values to string representation
FSM Operations
fsm_create/2- Create FSM instancesfsm_send_safe/2- Safe message sending to FSMscreate_counter/1- Specialized counter FSM creation
Utility Functions
list_to_string/1- List serializationjoin_ints/2- Integer list formatting
Monadic Pipe Semantics
The pipe/2 function implements Cure's monadic pipe operator (|>) with
these rules:
- Error Propagation: 
Error(x) |> f=Error(x) - Ok Unwrapping: 
Ok(x) |> f=f(x)(wrapped if not already monadic) - Value Passing: 
x |> f=f(x)(wrapped if not already monadic) 
Example Usage
%% Direct function calls (typically from runtime)
cure_std:print("Hello, World!").
cure_std:pipe({'Ok', 5}, fun(X) -> X * 2 end).
%% Returns: {'Ok', 10}
cure_std:show({'Ok', [1, 2, 3]}).
%% Returns: "Ok([1, 2, 3])"Integration with Cure
Functions in this module are automatically registered in the runtime's global function registry and can be called from Cure code using standard function call syntax. The runtime handles the bridge between Cure's type system and Erlang's dynamic typing.
Error Handling
- I/O functions always succeed (return 'ok')
 - Pipe operations catch Erlang exceptions and wrap them as Error values
 - FSM operations return Result types for safe error handling
 - Show function handles unknown types gracefully
 
Performance Considerations
- All functions are designed for single-call efficiency
 - String operations use efficient list concatenation
 - Monadic operations minimize pattern matching overhead
 - FSM operations are lightweight stubs (full implementation in cure_fsm_runtime)
 
Summary
Functions
Checks if a value is a monadic type (Result or Option).
Implements Cure's monadic pipe operator (|>) with Result type semantics.
Prints a message to standard output without adding a newline.
Prints a message to standard output followed by a newline.
Nat type unary constructor representing successor.
Converts any Cure value to its string representation for debugging and display.
Nat type nullary constructor representing zero.
Functions
Checks if a value is a monadic type (Result or Option).
This function determines whether a value follows the monadic pattern used by Cure's Result and Option types, which is essential for proper pipe operator behavior.
Arguments
Value- Any Erlang term to check
Returns
true- Value is a Result (Ok/Error) typefalse- Value is not a monadic type
Example
cure_std:is_monad({'Ok', 42}).     %% true
cure_std:is_monad({'Error', msg}). %% true
cure_std:is_monad(42).             %% false
cure_std:is_monad([1, 2, 3]).      %% falseSupported Monadic Types
{'Ok', Value}- Successful result with value{'Error', Reason}- Failed result with error reason
Note: Option types (Some/None) are not currently detected as monadic by this function, though they follow similar patterns.
Usage
Primarily used internally by pipe/2 to determine whether function results need to be wrapped in Ok constructors or can be returned as-is.
Implements Cure's monadic pipe operator (|>) with Result type semantics.
This function is the core implementation of Cure's pipe operator, providing monadic composition with automatic error propagation and value wrapping. It handles three distinct cases based on the input value type.
Arguments
LHO- Left-hand operand (value to be piped)RHO- Right-hand operand (function to apply)
Returns
- Result of applying RHO to LHO (possibly unwrapped), with appropriate wrapping
 - Error values are propagated without calling RHO
 - Runtime errors are caught and wrapped as Error values
 
Pipe Rules
Rule 1: Error Propagation
cure_std:pipe({'Error', reason}, Fun).
%% Returns: {'Error', reason} (Fun is not called)Rule 2: Ok Unwrapping
cure_std:pipe({'Ok', 5}, fun(X) -> X * 2 end).
%% Returns: {'Ok', 10} (value unwrapped, result wrapped)
cure_std:pipe({'Ok', 5}, fun(X) -> {'Ok', X * 2} end).
%% Returns: {'Ok', 10} (already monadic, not double-wrapped)Rule 3: Value Passing
cure_std:pipe(5, fun(X) -> X * 2 end).
%% Returns: {'Ok', 10} (non-monadic input, result wrapped)
cure_std:pipe(5, fun(X) -> {'Error', 'too_big'} end).
%% Returns: {'Error', 'too_big'} (monadic result preserved)Error Handling
If RHO throws an exception during execution:
cure_std:pipe({'Ok', 0}, fun(X) -> 1/X end).
%% Returns: {'Error', {pipe_runtime_error, error, badarith}}Usage in Cure
%% In Cure code, this becomes:
value |> function1 |> function2
%% Which compiles to:
pipe(pipe(value, function1), function2)Type Safety
The pipe operator maintains type safety by:
- Never double-wrapping already monadic values
 - Propagating errors without execution
 - Catching runtime exceptions as Error values
 - Preserving monadic invariants through composition chains
 
Prints a message to standard output without adding a newline.
This function outputs text directly to the console using Erlang's I/O formatting system. It's designed for inline output where you want to continue writing on the same line.
Arguments
Message- String or list to print (must be printable)
Returns
ok- Always succeeds
Example
cure_std:print("Hello ").
cure_std:print("World!").
%% Output: "Hello World!"
cure_std:print("Count: ").
cure_std:print(integer_to_list(42)).
%% Output: "Count: 42"Usage in Cure
print("Processing...")
// Continue with other operations
print("Done!")Character Encoding
Supports Unicode text through Erlang's ~ts format specifier, ensuring proper handling of international characters.
Error Handling
I/O errors are handled by the underlying Erlang system. This function always returns 'ok' from the Cure perspective.
Prints a message to standard output followed by a newline.
This is the most commonly used output function, automatically adding a newline character after the message for line-by-line output formatting.
Arguments
Message- String or list to print (must be printable)
Returns
ok- Always succeeds
Example
cure_std:println("First line").
cure_std:println("Second line").
%% Output:
%% First line
%% Second line
cure_std:println("Value: " ++ integer_to_list(42)).
%% Output: Value: 42Usage in Cure
println("Hello, World!")
println("This is on a new line")Character Encoding
Supports Unicode text through Erlang's ~ts format specifier, ensuring proper handling of international characters.
Comparison with print/1
Error Handling
I/O errors are handled by the underlying Erlang system. This function always returns 'ok' from the Cure perspective.
Nat type unary constructor representing successor.
Takes a natural number and returns its successor (n+1). This is the inductive case of Peano-encoded natural numbers.
Arguments
N- A natural number (Nat)
Returns
- N+1 (next natural number)
 
Example
cure_std:'Succ'(0).        %% Returns: 1 (successor of Zero)
cure_std:'Succ'(5).        %% Returns: 6 (successor of 5)Usage in Cure
let one = Succ(Zero)
let two = Succ(Succ(Zero))
let three = Succ(two)Type
- Succ : Nat -> Nat
 
Converts any Cure value to its string representation for debugging and display.
This function provides comprehensive string serialization for all Cure data types, with special handling for monadic types (Result/Option) and structured data like lists and tuples.
Arguments
Value- Any Cure/Erlang term to convert to string
Returns
- String representation of the value
 - "unknown" for unrecognized value types
 
Examples
Monadic Types
cure_std:show({'Ok', 42}).        %% "Ok(42)"
cure_std:show({'Error', failed}). %% "Error(failed)"
cure_std:show({'Some', data}).    %% "Some(data)"
cure_std:show('None').            %% "None"Basic Types
cure_std:show(42).           %% "42"
cure_std:show(3.14).         %% "3.14"
cure_std:show(hello).        %% "hello"
cure_std:show("string").     %% "string"Structured Types
cure_std:show([1, 2, 3]).           %% "[1, 2, 3]"
cure_std:show({a, b}).              %% "{a, b}"
cure_std:show({1, 2, 3, 4}).        %% "{1, 2, 3, 4}"
cure_std:show({1, 2, 3, 4, 5}).     %% "{1, 2, 3, 4, ...}"Nested Structures
cure_std:show({'Ok', [1, 2, {'Some', 3}]}).
%% "Ok([1, 2, Some(3)])"Usage in Cure
let value = Ok([1, 2, 3])
println(show(value))  // Outputs: Ok([1, 2, 3])Tuple Handling
- Tuples with 0-4 elements: Full representation
 - Tuples with 5+ elements: Truncated with "..." suffix
 - Nested tuples are recursively formatted
 
Error Handling
Unknown or unsupported types return "unknown" rather than crashing, making this function safe for debugging any Cure value.
Performance Notes
- Recursive formatting for nested structures
 - String concatenation using Erlang's efficient list operations
 - Optimized for readability over performance
 
Nat type nullary constructor representing zero.
In Cure's Peano encoding of natural numbers:
- Zero represents 0
 - Succ(Zero) represents 1
 - Succ(Succ(Zero)) represents 2, etc.
 
Returns
- 0 (represented as integer for runtime efficiency)
 
Example
cure_std:'Zero'().  %% Returns: 0Usage in Cure
def length(list: List(T)): Nat =
  match list do
    [] -> Zero
    [_ | t] -> Succ(length(t))
  endType
- Zero : Nat