Types that follow your thinking
Inferred static types, immutable data, and exhaustive pattern matching. Expected failures remain visible as Result values.
Your logic. Your handlers.
Declare what your code needs with algebraic effects. Choose the handler that makes it happen.
effect Drafts { save: fn(string, string) -> Result<int, Error> }
fn saveDraft() = match perform Drafts.save("draft.txt", "Ship it.") {
Success _ => "Saved"
Error { message } => "Retry: ${message}"
}
let disk = handler Drafts {
save path text => writeFile(path, text)
}
let offline = handler Drafts {
save _ _ => Error { message: "offline" }
}
print("${disk(saveDraft)} / ${offline(saveDraft)}")
effect Drafts
save : (string, string) => Result<int, Error>
saveDraft () = match perform Drafts.save "draft.txt" "Ship it."
Success _ => "Saved"
Error message => "Retry: ${message}"
disk = handler Drafts
save path text => writeFile path text
offline = handler Drafts
save _ _ => Error(message = "offline")
print "${disk saveDraft} / ${offline saveDraft}"
# osprey: flavor=python
@effect
class Drafts:
def save(path: str, text: str) -> Result[int, Error]: ...
def saveDraft():
match perform(Drafts.save("draft.txt", "Ship it.")):
case Success():
return "Saved"
case Error(message=message):
return f"Retry: {message}"
@handler(Drafts)
class disk:
def save(path, text):
return writeFile(path, text)
@handler(Drafts)
class offline:
def save(_path, _text):
return Error(message="offline")
def main():
print(f"{disk(saveDraft)} / {offline(saveDraft)}")
Three uncompromising flavors. No lock-in.
01 / A different way to connect
Save a draft. Handle success or failure. Keep storage outside the function.
One handler writes to disk. Another simulates being offline. Swap the handler; keep the logic.
Understand algebraic effects ↗Osprey is alpha software. Native control effects support single-shot resumption; full scoped effect rows and reusable continuations remain in development. Current support →
02 / Less ceremony. More intent.
Inferred static types, immutable data, and exhaustive pattern matching. Expected failures remain visible as Result values.
Default, ML, Python. Each uncompromising. All share Osprey’s types, effects, and compiler. Choose per file; mix all three in one project.
Find your syntax ↗Native fibers and channels keep concurrent work in ordinary functions. Choose the default allocator, tracing GC, or reference counting for your native build.
Follow the fibers ↗Integer overflow asks an Arith handler for the region's chosen behavior. Wrapping and saturating helpers make that choice explicit.
03 / Take it into the world
Compile through LLVM to native programs, WebAssembly, or application logic for native mobile hosts.
Direct executables. C interop. A choice of memory backends.
--target=native
02 / BROWSER & WASIShared application logic, connected to the browser through a host.
--target=wasm32
03 / IN YOUR HANDOsprey modules behind SwiftUI and native Android interfaces.
--target=ios / android-arm64
Build for the capabilities of your target. Unsupported dynamic control effects are rejected on WebAssembly and mobile.
Real measurements, open benchmarks ↗04 / Bring your Python thinking
Keep def, lambda, and f-strings. Port computation into Osprey’s Python flavor with inferred types and checked effects. Keep Python libraries through explicit interop.
GPT-2 is the worked port: one Tensor effect, a CPU handler, and a GPU handler using Metal or OpenCL. The handler decides where the arithmetic runs.
# osprey: flavor=python
def product(a, b, rows, inner, cols):
"""a [rows, inner] times b [inner, cols]; the handler aborts on failed work."""
return perform(Tensor.mat_mul(a, b, rows, inner, cols))
Python flavor is Osprey source; porting requires adapting Python’s dynamic behavior. Shared tensor storage across Python interop is planned. GPU kernels are not fused; GPT-2 generation is not faster than CPU. Measurements and source →
05 / From language to application
Issue Inbox puts its model, updates, UI layout, GitHub decoding, and SQLite commands in shared Osprey modules. SwiftUI and Android widgets render the application.
Actual simulator and emulator captures. Also verified on a physical iPhone. Native hosts provide rendering, SQLite, HTTPS, and lifecycle services.
Your next idea starts here
Start with a small program. Make the behavior your own.
brew install nimblesite/tap/ospreyscoop bucket add nimblesite https://github.com/Nimblesite/scoop-bucket
scoop install ospreyNative compilation requires clang (LLVM 15+). Installation guide → · Contribute on GitHub ↗