Examples
Practical Sounio code examples
Examples
Learn Sounio through practical examples covering various domains.
Basic Examples
Hello World
fn main() with IO {
print("Hello, World!")
}
Variables and Types
fn main() with IO {
// Immutable
let name = "Sounio"
let version = 1.0
// Mutable
var count = 0
count = count + 1
// With units
let distance: m = 100.0
let time: s = 9.58
let speed = distance / time // m/s
print("Speed: " + speed.to_string())
}
Functions with Effects
fn greet(name: String) with IO {
print("Hello, " + name + "!")
}
fn add(a: i32, b: i32) -> i32 {
a + b // No effects needed
}
fn main() with IO {
greet("World")
print("Sum: " + add(3, 5).to_string())
}
Epistemic Computing
BMI Calculator with Uncertainty
fn main() with IO {
let mass: Knowledge<kg> = measure(
value: 75.3,
uncertainty: 0.5,
source: "bathroom_scale"
)
let height: Knowledge<m> = measure(
value: 1.82,
uncertainty: 0.01,
source: "tape_measure"
)
let bmi = mass / (height * height)
print("BMI: " + bmi.to_string())
// Output: BMI: 22.73 ± 0.31 kg/m²
if bmi.confidence > 0.90 {
let category = match bmi.value {
v if v < 18.5 => "Underweight",
v if v < 25.0 => "Normal",
v if v < 30.0 => "Overweight",
_ => "Obese",
}
print("Category: " + category)
}
}
Sensor Fusion
fn fuse_sensors(sensors: Vec<Knowledge<celsius>>) -> Knowledge<celsius> {
// Weighted average by inverse uncertainty
let weights = sensors.map(|s| 1.0 / s.uncertainty.pow(2))
let total_weight = weights.sum()
let fused_value = sensors
.zip(weights)
.map(|(s, w)| s.value * w)
.sum() / total_weight
let fused_uncertainty = 1.0 / total_weight.sqrt()
Knowledge {
value: fused_value,
uncertainty: fused_uncertainty,
provenance: sensors.flat_map(|s| s.provenance).collect(),
confidence: sensors.map(|s| s.confidence).min(),
}
}
fn main() with IO {
let readings = vec![
measure(value: 23.5, uncertainty: 0.2, source: "sensor_A"),
measure(value: 23.8, uncertainty: 0.3, source: "sensor_B"),
measure(value: 23.3, uncertainty: 0.25, source: "sensor_C"),
]
let fused = fuse_sensors(readings)
print("Fused temperature: " + fused.to_string())
print("Sources: " + fused.provenance.join(", "))
}
Scientific Computing
Numerical Integration
fn integrate(f: fn(f64) -> f64, a: f64, b: f64, n: i32) -> f64 {
let h = (b - a) / (n as f64)
var sum = 0.0
for i in 0..n {
let x = a + (i as f64) * h
sum = sum + f(x) * h
}
sum
}
fn main() with IO {
// Integrate x² from 0 to 1
let result = integrate(|x| x * x, 0.0, 1.0, 1000)
print("∫x² dx from 0 to 1 = " + result.to_string())
// Expected: 0.333...
}
ODE Solver (Runge-Kutta)
fn rk4_step(f: fn(f64, f64) -> f64, t: f64, y: f64, h: f64) -> f64 {
let k1 = f(t, y)
let k2 = f(t + h/2.0, y + h*k1/2.0)
let k3 = f(t + h/2.0, y + h*k2/2.0)
let k4 = f(t + h, y + h*k3)
y + h * (k1 + 2.0*k2 + 2.0*k3 + k4) / 6.0
}
fn solve_ode(f: fn(f64, f64) -> f64, y0: f64, t_end: f64, dt: f64) -> Vec<(f64, f64)> {
var t = 0.0
var y = y0
var results = vec![(t, y)]
while t < t_end {
y = rk4_step(f, t, y, dt)
t = t + dt
results.push((t, y))
}
results
}
fn main() with IO {
// Solve dy/dt = -y, y(0) = 1 (exponential decay)
let solution = solve_ode(|t, y| -y, 1.0, 5.0, 0.1)
for (t, y) in solution {
print("t=" + t.to_string() + ", y=" + y.to_string())
}
}
Data Processing
CSV Analysis
use std::csv::CsvReader
fn main() with IO {
let reader = CsvReader::open("measurements.csv")?
var values: Vec<Knowledge<f64>> = vec![]
for row in reader {
let value: f64 = row.parse("value")?
let uncertainty: f64 = row.parse("uncertainty")?
let source = row.get("source")?
values.push(measure(
value: value,
uncertainty: uncertainty,
source: source
))
}
let mean = values.iter().map(|v| v.value).mean()
print("Mean value: " + mean.to_string())
}
GPU Computing
Vector Addition
use std::gpu::{kernel, launch, Device}
#[kernel]
fn vector_add(a: &[f32], b: &[f32], c: &![f32]) {
let i = thread_idx() + block_idx() * block_dim()
if i < a.len() {
c[i] = a[i] + b[i]
}
}
fn main() with IO, GPU {
let device = Device::default()
let a = vec![1.0f32; 1000000]
let b = vec![2.0f32; 1000000]
var c = vec![0.0f32; 1000000]
let d_a = device.alloc(&a)
let d_b = device.alloc(&b)
let d_c = device.alloc_mut(&mut c)
launch(vector_add, blocks: 1024, threads: 1024, d_a, d_b, d_c)
device.sync()
print("First result: " + c[0].to_string()) // 3.0
}
Effect Handlers
Custom Logging
effect Log {
fn log(level: Level, msg: String)
}
handler ConsoleLog for Log {
fn log(level: Level, msg: String) with IO {
print("[" + level.to_string() + "] " + msg)
}
}
fn process_data(data: Vec<f64>) with Log {
perform Log::log(Info, "Processing " + data.len().to_string() + " items")
for item in data {
if item < 0.0 {
perform Log::log(Warn, "Negative value: " + item.to_string())
}
}
perform Log::log(Info, "Processing complete")
}
fn main() with IO {
handle ConsoleLog {
process_data(vec![1.0, -2.0, 3.0, -4.0, 5.0])
}
}