Haskell is brilliant but production deployment is painful. Elm is delightful but web-only. OCaml is fast but the ecosystem is small. Every functional language makes you choose between theory and practice. Roc is a new functional language designed from day one for building real applications — with compilation speed, helpful error messages, and no PhD required.
What Roc Actually Does
Roc is a functional programming language created by Richard Feldman (former Elm core team). It compiles to machine code via LLVM, with compilation times comparable to Go. The language has no null, no exceptions, no runtime crashes from type errors — but achieves this without Haskell's complexity.
Roc's key innovation is its platform system. Instead of a standard library, Roc has "platforms" — pre-built environments for web servers, CLI tools, WASM apps, etc. Your application code is pure business logic; the platform handles I/O. This means the same Roc code can target different runtimes.
Roc uses structural typing (like TypeScript) rather than nominal typing (like Java). Automatic memory management with reference counting (no GC pauses). Open-source under UPL license.
Quick Start
# Install
curl -fsSL https://roc-lang.org/install | bash
Hello world with the basic-cli platform:
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br" }
import pf.Stdout
main =
Stdout.line! "Hello from Roc!"
Run:
roc run hello.roc
Compile to optimized binary:
roc build --optimize hello.roc
3 Practical Use Cases
1. Data Processing Pipelines
processUsers = \users ->
users
|> List.keepIf \u -> u.active
|> List.map \u -> {
name: u.name,
email: Str.toLower u.email,
score: calculateScore u,
}
|> List.sortWith \a, b -> Num.compare b.score a.score
|> List.takeFirst 100
calculateScore = \user ->
loginScore = Num.min user.loginCount 100
activityScore = user.postsCount * 5 + user.commentsCount * 2
loginScore + activityScore
Pure functions, immutable data, guaranteed no side effects.
2. Pattern Matching on Results
parseConfig : Str -> Result Config [InvalidJson, MissingField Str]
parseConfig = \jsonStr ->
when Json.decode jsonStr is
Ok record ->
when (record |> Dict.get "host", record |> Dict.get "port") is
(Ok host, Ok port) -> Ok { host, port: Num.toI64 port }
(Err _, _) -> Err (MissingField "host")
(_, Err _) -> Err (MissingField "port")
Err _ -> Err InvalidJson
main =
when parseConfig configJson is
Ok config -> Stdout.line! "Server: $(config.host):$(Num.toStr config.port)"
Err InvalidJson -> Stderr.line! "Invalid JSON in config"
Err (MissingField name) -> Stderr.line! "Missing field: $(name)"
3. Web Server
app [main] { pf: platform "basic-webserver" }
import pf.Http
main = Http.serve \request ->
when request.url is
"/" -> Http.respond 200 "Welcome to Roc!"
"/api/health" -> Http.respond 200 (Json.encode { status: "ok" })
"/api/users" -> handleUsers request
_ -> Http.respond 404 "Not found"
handleUsers = \request ->
users = getUsers!
Http.respond 200 (Json.encode users)
Why This Matters
Roc makes functional programming practical for everyday development. No monads to learn, no category theory, no type-level programming. Just pure functions, pattern matching, and a type system that catches bugs at compile time. For developers curious about FP but burned by Haskell's learning curve, Roc is the on-ramp.
Need custom data extraction or web scraping solutions? I build production-grade scrapers and data pipelines. Check out my Apify actors or email me at spinov001@gmail.com for custom projects.
Follow me for more free API discoveries every week!
Top comments (0)