2026-03-30·9 min read·sota.io team

Deploy Curry to Europe — Functional Logic Programming at CAU Kiel in 2026

In the 1990s, computer science had two powerful but separate paradigms for declarative programming: functional programming (Haskell, ML) and logic programming (Prolog). Functional languages gave you pure functions, strong types, and lazy evaluation. Logic languages gave you non-determinism, constraint solving, and free variables — the ability to say "find a value x such that P(x) holds" rather than specifying exactly how to compute it.

The idea of unifying these two paradigms into a single coherent language had been explored theoretically for years, but Michael Hanus at the Christian-Albrechts-Universität zu Kiel (CAU Kiel) 🇩🇪 in northern Germany turned it into a practical programming language: Curry. Named after the mathematician Haskell Brooks Curry — whose work on combinatory logic and lambda calculus underpins both paradigms — Curry gives you Haskell-style types and higher-order functions alongside Prolog-style non-determinism and logic variables. The result is a language more expressive than either parent.

This guide shows how to deploy Curry backends — compiled via KiCS2 to native Haskell executables — to EU infrastructure with sota.io.

The European Roots of Functional Logic Programming

Curry's intellectual lineage is deeply European, drawing from two traditions that both originated on the continent.

Michael Hanus 🇩🇪 (Christian-Albrechts-Universität zu Kiel) — the primary designer and maintainer of Curry. Hanus has been at CAU Kiel since the late 1990s, where his research group developed both the language specification and the two main implementations: KiCS2 (Kiel Curry System to Haskell) and PAKCS (Portland Augsburg Kiel Curry System, which compiles to SWI-Prolog or SICStus Prolog). Kiel, a university city on the Baltic Sea in Schleswig-Holstein, has been the institutional home of Curry for over two decades.

Alain Colmerauer 🇫🇷 (Université de Marseille) — inventor of Prolog, the logic programming language that forms one half of Curry's heritage. Colmerauer developed Prolog at the Groupe d'Intelligence Artificielle at the Université d'Aix-Marseille in 1972, together with Philippe Roussel 🇫🇷. The core idea — computation as proof search, programs as logic clauses — gave the world constraint logic programming and laid the groundwork for languages like Curry.

Robert Kowalski 🇬🇧 (University of Edinburgh → Imperial College London) — the other founding figure of logic programming. Kowalski at Edinburgh (and later Imperial College) formalized the theoretical basis of Prolog and introduced the procedural interpretation of Horn clauses (SLD resolution). His collaboration with Colmerauer established Prolog as a practical tool. Edinburgh's role in both logic programming and ML (Robin Milner's functional work happened at the same institution) made it a unique confluence of the two traditions Curry would later unite.

Haskell Curry 🇺🇸 (Penn State / Harvard) — the mathematician whose name the language shares, and whose work on combinatory logic (developed partly through correspondence with European logicians including Schönfinkel in Germany) forms the mathematical backbone of every functional language. The Curry-Howard correspondence — the isomorphism between proofs and programs, types and propositions — is named after both Curry and William Howard, and is the theoretical unification of logic and computation that Curry the language makes practically accessible.

German CS Research Community — Curry has been influential in German universities. CAU Kiel, RWTH Aachen, and TU Berlin have used Curry for teaching declarative programming. The Declarative Programming and Logic Programming research tracks at German CS departments regularly feature Curry-based work. The language's design reflects the rigour of German theoretical computer science.

KiCS2 Compiler Toolchain — the modern implementation of Curry, KiCS2, compiles Curry programs to Haskell and then uses GHC to produce native binaries. This means Curry programs on sota.io get GHC's mature optimization pipeline, LLVM backend, and excellent runtime performance — a German research language running on German infrastructure via Glasgow's compiler.

What Makes Curry Different

Curry extends Haskell with two key concepts: free variables and non-determinism. These are not hacks — they are first-class language features with a clean semantics.

Free variables let you write search problems as functions:

-- Standard Haskell-style function
add :: Int -> Int -> Int
add x y = x + y

-- Curry: solve for x such that add x 3 = 7
-- ?= is the constraint operator
example :: Int
example = let x free in x =:= 7 - 3 `seq` x
-- evaluates to: 4

Non-determinism lets functions return multiple values:

-- A non-deterministic choice: either 1 or 2
coin :: Int
coin = 1
coin = 2   -- multiple defining equations = non-deterministic

-- Compose non-deterministic functions
doubleCoin :: Int
doubleCoin = coin + coin
-- evaluates to: 2, 3, or 4 (all combinations)

This is not ambiguity or error — it is fair enumeration of all possible outcomes. The Curry runtime explores all branches.

Pattern matching with logic variables — the combination of these features gives you a pattern matching system more powerful than Haskell's:

-- Define last via append (logic search, not computation)
last :: [a] -> a
last xs | xs =:= _ ++ [x] = x  where x free

-- Works for any list, found via constraint solving
-- last [1,2,3]  =>  3

This is genuinely impossible to write this cleanly in Haskell. You would need explicit recursion or a library. In Curry, the logic variable x and the pattern _ ++ [x] express the specification of what last means, and the runtime solves it.

Building an HTTP Backend in Curry

Curry with KiCS2 can produce standalone executables. For HTTP backends, the Network.HTTP library provides socket-level HTTP handling. Here is a complete backend service:

module Main where

import Network.Socket
import Data.Char (isSpace)

-- HTTP response helpers
httpOK :: String -> String
httpOK body =
  "HTTP/1.1 200 OK\r\n" ++
  "Content-Type: application/json\r\n" ++
  "Content-Length: " ++ show (length body) ++ "\r\n" ++
  "Connection: close\r\n\r\n" ++
  body

httpNotFound :: String
httpNotFound = "HTTP/1.1 404 Not Found\r\n\r\n{\"error\":\"not found\"}"

-- Route type — exhaustive handling enforced by Curry's pattern matching
data Route = Health | Items String | Unknown

-- Parse HTTP request line to route
parseRoute :: String -> Route
parseRoute req =
  case words (head (lines req)) of
    [_, "/health",   _] -> Health
    [_, path,        _] | "/api/items" `isPrefixOf` path -> Items path
    _                   -> Unknown

isPrefixOf :: String -> String -> Bool
isPrefixOf []     _      = True
isPrefixOf _      []     = False
isPrefixOf (x:xs) (y:ys) = x == y && isPrefixOf xs ys

-- Route handler — non-exhaustive handled by Unknown catch-all
handleRoute :: Route -> String
handleRoute Health      = httpOK "{\"status\":\"ok\",\"lang\":\"curry\"}"
handleRoute (Items _)   = httpOK "{\"items\":[\"kiel\",\"functional\",\"logic\"]}"
handleRoute Unknown     = httpNotFound

-- Handle a single connection
handleClient :: Socket -> IO ()
handleClient sock = do
  req <- recvFully sock ""
  let route    = parseRoute req
  let response = handleRoute route
  send sock response
  sClose sock

recvFully :: Socket -> String -> IO String
recvFully sock acc = do
  chunk <- recv sock 4096
  if null chunk
    then return acc
    else if "\r\n\r\n" `isInfixOf` (acc ++ chunk)
         then return (acc ++ chunk)
         else recvFully sock (acc ++ chunk)

isInfixOf :: String -> String -> Bool
isInfixOf needle haystack = any (isPrefixOf needle) (tails haystack)

tails :: [a] -> [[a]]
tails []     = [[]]
tails xs@(_:rest) = xs : tails rest

-- Server loop
serve :: Socket -> IO ()
serve server = do
  (client, _) <- accept server
  handleClient client
  serve server

main :: IO ()
main = do
  sock <- socket AF_INET Stream defaultProtocol
  setSocketOption sock ReuseAddr 1
  bind sock (SockAddrInet 8080 iNADDR_ANY)
  listen sock 10
  putStrLn "Curry backend listening on :8080"
  serve sock

Notice the clean separation of concerns, Haskell-style syntax, and the catch-all Unknown route that makes the pattern match exhaustive without needing to enumerate every possible path.

Packaging for sota.io

Curry's KiCS2 compiler produces a native binary via GHC. The Dockerfile uses a two-stage build: compile with GHC+KiCS2 in the builder stage, copy the binary to a minimal runtime image.

Project structure:

myapp/
├── Main.curry          # Application entry point
├── Dockerfile
└── .gitignore

Dockerfile:

FROM haskell:9.4 AS builder

# Install KiCS2 Curry compiler
RUN apt-get update && apt-get install -y \
    git \
    libncurses-dev \
    && rm -rf /var/lib/apt/lists/*

# Install KiCS2 from source
RUN git clone https://github.com/curry-lang/kics2.git /opt/kics2 \
    && cd /opt/kics2 \
    && make \
    && make install

ENV PATH="/opt/kics2/bin:$PATH"

WORKDIR /app
COPY Main.curry .

# Compile Curry to native binary
RUN cypm exec curry compile Main

FROM debian:12-slim
WORKDIR /app
COPY --from=builder /app/Main .
EXPOSE 8080
CMD ["./Main"]

Build and push:

docker build -t myapp:latest .
docker tag myapp:latest registry.sota.io/YOUR_PROJECT_ID/myapp:latest
docker push registry.sota.io/YOUR_PROJECT_ID/myapp:latest

Deploy on sota.io:

# Create service
sota services create \
  --name myapp \
  --image registry.sota.io/YOUR_PROJECT_ID/myapp:latest \
  --port 8080 \
  --region eu-central

# View logs
sota services logs myapp

Your Curry backend is running on EU infrastructure in Frankfurt, GDPR-compliant by default.

Why EU Teams Use Curry

Constraint solving built into the language. Curry's logic variables and non-determinism are not bolted-on libraries — they are part of the core language semantics. For applications that involve search, optimisation, or constraint satisfaction (scheduling, planning, configuration), Curry expresses these problems more directly than any purely functional language. You write the specification, Curry finds the solution.

German research and education heritage. Curry is actively developed and maintained at CAU Kiel, a public German university. For German software companies, academic institutions, and public sector organisations that prefer software with clear European provenance, Curry's institutional home is about as close as it gets — a Baltic coast university with a 350-year history.

Functional types with logic flexibility. Teams coming from Haskell or OCaml find Curry's type system immediately familiar — it is essentially Haskell 98 with extensions. The addition of logic features does not change the functional subset: pure Haskell-style code compiles and runs as expected. Logic features are additive, not disruptive.

Teaching declarative programming. Curry is widely used in German CS departments for teaching declarative and logic programming in a unified framework. If your team includes graduates from CAU Kiel, RWTH Aachen, TU Berlin, or Freie Universität Berlin, they may already know Curry. It bridges the gap between functional and logic courses.

Formal specification via constraint programming. Curry's deterministic subset can be used for type-safe functional code; the non-deterministic subset can express formal specifications and test oracles. This dual use — specification language and implementation language in one — is valuable for teams doing property-based testing or formal verification.

Supply chain clarity. KiCS2 and PAKCS are open source, developed at German universities under BSD/MIT-compatible licences. The dependency chain is transparent: Curry → GHC → LLVM. No black-box components, no commercial lock-in, no unclear provenance.

Practical Considerations

Ecosystem maturity. Curry is a research language with a smaller library ecosystem than Haskell or Python. The Curry Package Manager (CYPM) has a growing collection of packages, but for production use, evaluate coverage of your specific requirements before committing.

Non-determinism performance. Curry's non-deterministic features require a backtracking or sharing-based evaluation strategy (Curry uses lazy narrowing with sharing). For programs that rely heavily on non-determinism over large search spaces, performance depends on the problem structure. The KiCS2 compiler optimises deterministic code to near-Haskell speed; highly non-deterministic programs may need tuning.

Learning curve. Developers with Haskell experience can read and write Curry immediately — the syntax is nearly identical. The new concepts (free variables, non-determinism, narrowing) take a few days to internalise but are well-documented in Hanus's course materials at CAU Kiel.

When Curry is the right choice:

Deploy on EU Infrastructure

sota.io runs on servers in Germany (Frankfurt) and other EU data centres. All data stays within EU jurisdiction, GDPR compliance is structural, and every deployment is isolated by default.

Get started:

# Install sota CLI
curl -fsSL https://sota.io/install.sh | sh

# Log in
sota login

# Deploy from Dockerfile
sota deploy --port 8080

# Custom domain
sota domains add curry.yourdomain.eu

Your functional logic backend. Built in Kiel. Hosted in Europe.

European Connections Summary

WhoInstitutionContribution
Michael Hanus 🇩🇪CAU Kiel (Schleswig-Holstein)Curry language design, KiCS2, PAKCS
Alain Colmerauer 🇫🇷Université d'Aix-MarseilleProlog — logic programming foundation
Philippe Roussel 🇫🇷Université d'Aix-MarseilleProlog co-inventor
Robert Kowalski 🇬🇧Univ. Edinburgh → Imperial CollegeLogic programming theory, SLD resolution
CAU Kiel Research Group 🇩🇪Christian-Albrechts-UniversitätKiCS2 compiler, CYPM package manager
Haskell Curry 🇺🇸Penn State / HarvardCombinatory logic — language namesake

Curry is the practical output of two European research traditions — French logic programming from Marseille and German functional-logic research from Kiel — unified into a single language that sits at the intersection of Haskell and Prolog. It runs on the same German infrastructure where it was designed.


sota.io is EU-native infrastructure for backend services. Deploy your Curry application to German servers in minutes — GDPR-compliant, managed PostgreSQL, custom domains included.