Standard ML
1983fragletMCP + fragletc
Standard ML (SML) is a general-purpose, modular, functional programming language with compile-time type checking and type inference. Developed in the 1980s, it's known for its mathematical foundations and elegant design.
About Standard ML
Standard ML was designed as a meta-language for the Edinburgh LCF theorem prover, but evolved into a standalone programming language. It features:
- Strong static typing with Hindley-Milner type inference
- Functional programming with immutable data structures by default
- Pattern matching for elegant control flow
- Module system for large-scale program organization
- Formal semantics - one of the few languages with a complete formal definition
This Implementation
This container uses Poly/ML, a full implementation of Standard ML that's particularly well-suited for interactive development and deployment. Poly/ML is compatible with musl libc, making it perfect for Alpine Linux containers.
Fun Facts
- Standard ML has influenced many modern languages including OCaml, Haskell, and Rust
- It was one of the first languages to feature garbage collection and polymorphic type inference
- The language definition fits in a relatively small book, yet it's computationally complete
- Robin Milner, one of SML's creators, won the Turing Award partly for his work on type systems
Language Features Showcase
(* This simple "Hello World!" demonstrates SML's clean syntax *)
print "Hello World!\n";
(* But SML can do much more with functions and pattern matching *)
fun factorial 0 = 1
| factorial n = n * factorial (n - 1);
(* Polymorphic data structures *)
datatype 'a option = NONE | SOME of 'a;SML proves that functional programming can be both mathematically rigorous and practically useful!
Hello World
#!/usr/bin/env sh
# If this file is present, this is the file that runs when you add the
# RUN=1 option.
#
# Otherwise, the default behavior is to run the first file in the
# directory that matches the pattern `hello-world.*``.
# Build it
# Run it
poly -q --use /hello-world/hello-world.sml "$@"Coding Guide
Language Version
Poly/ML 5.x (Standard ML implementation)
Execution Model
- Interpreted via Poly/ML REPL
- Code executes at the top level
- Expressions and declarations run immediately
- Uses
poly --quietto suppress startup messages
Key Characteristics
- Strong static typing with Hindley-Milner type inference
- Functional programming with immutable data structures by default
- Pattern matching for elegant control flow
- Case-sensitive identifiers
- Semicolon-terminated statements and declarations
- Top-level bindings - functions and values can be defined at module level
Fragment Authoring
Write valid SML expressions or declarations. Your fragment becomes the script body. Code executes at the top level, so expressions run immediately. You can define functions, values, and use pattern matching.
Available Libraries
Standard ML Basis Library is available. Poly/ML provides additional libraries for I/O, system interaction, and more.
Common Patterns
Print Output
print "Hello, World!\n";Variable Bindings
val x = 42;
val name = "Alice";
print (name ^ "\n");Function Definitions
fun greet name = "Hello, " ^ name ^ "!\n";
print (greet "World");Pattern Matching
fun factorial 0 = 1
| factorial n = n * factorial (n - 1);
print ("Factorial of 5: " ^ Int.toString (factorial 5) ^ "\n");Lists and Higher-Order Functions
val numbers = [1, 2, 3, 4, 5];
val sum = foldl (op +) 0 numbers;
print ("Sum: " ^ Int.toString sum ^ "\n");Recursive Functions
fun length [] = 0
| length (_::xs) = 1 + length xs;
print ("Length: " ^ Int.toString (length [1,2,3]) ^ "\n");Conditional Expressions
fun max a b = if a > b then a else b;
print ("Max of 5 and 10: " ^ Int.toString (max 5 10) ^ "\n");Examples
# Simple output
print "Hello, World!\n";
# Variables and calculations
val a = 5;
val b = 10;
print ("Sum: " ^ Int.toString (a + b) ^ "\n");
# Function definition
fun add x y = x + y;
print ("5 + 10 = " ^ Int.toString (add 5 10) ^ "\n");
# Pattern matching
fun factorial 0 = 1
| factorial n = n * factorial (n - 1);
print ("Factorial of 5: " ^ Int.toString (factorial 5) ^ "\n");
# Lists and higher-order functions
val numbers = [1, 2, 3, 4, 5];
val sum = foldl (op +) 0 numbers;
print ("Sum: " ^ Int.toString sum ^ "\n");
# List comprehensions (using map)
val squares = map (fn x => x * x) [1, 2, 3, 4, 5];
print ("Squares: " ^ String.concatWith ", " (map Int.toString squares) ^ "\n");
# String operations
val s = "Hello";
val t = s ^ " World!";
print (t ^ "\n");
print ("Length: " ^ Int.toString (String.size t) ^ "\n");
# Guards and case expressions
fun absolute x = if x >= 0 then x else ~x;
print ("Absolute of ~5: " ^ Int.toString (absolute (~5)) ^ "\n");I/O Patterns
Stdin
fun loop () =
case TextIO.inputLine TextIO.stdIn of
NONE => ()
| SOME s => (print (String.map Char.toUpper s); loop ());
loop ();Command-Line Arguments
CommandLine.arguments() includes 3 internal interpreter arguments before your arguments. Use List.drop to skip them:
val allArgs = CommandLine.arguments ();
val args = List.drop (allArgs, 3);
print ("Args: " ^ String.concatWith " " args ^ "\n");Caveats and Limitations
- Semicolons required: Top-level expressions must end with semicolons
- Type inference: SML infers types, but type errors will prevent execution
- Immutable by default: Variables are immutable (use
valbindings) - String concatenation: Use
^operator, not+ - Integer negation: Use
~prefix, not-(e.g.,~5not-5) - Print formatting: Use
Int.toString,Real.toString, etc. for number-to-string conversion - Poly/ML specific: Some features may be Poly/ML-specific rather than pure SML
- Program exits automatically after your fragment โ do not call
OS.Process.exit
Fraglet Scripts
Echo Args
#!/usr/bin/env -S fragletc --vein=sml
val allArgs = CommandLine.arguments ();
val args = List.drop (allArgs, 3);
val () = print ("Args: " ^ String.concatWith " " args ^ "\n");Stdin Upper
#!/usr/bin/env -S fragletc --vein=sml
fun loop () =
case TextIO.inputLine TextIO.stdIn of
NONE => ()
| SOME s => (print (String.map Char.toUpper s); loop ());
val () = loop ();Test
#!/usr/bin/env -S fragletc --vein=sml
val () = print "Hello World!\n";