Code Examples
Explore Keel through practical code examples. Click any example to open it in the playground.
253 examples
Basics
Comments
-- This is a line comment
{- This is a
block comment -}
let x = 42 -- inline comment...
Functions
fn add: Int -> Int -> Int
fn add x y =
x + y
add 2 3 -- Returns 5If Indentation
let condition = True
if condition then
"result1"
else
"result2" -- Must align with 'result1'Indentation
fn example: Int -> Int
fn example x =
let y = 1 -- Block must be indented
x + y
example 5Inline Module
module Math exposing (add)
fn add: Int -> Int -> Int
fn add x y =
x + y
...
Operators
-- Arithmetic
let sum = 1 + 2
let diff = 5 - 3
let prod = 4 * 2...
Shadowing
let x = 1
let x = x + 1
xValues Types
-- Numbers
let intVal = 42 -- Int
let floatVal = 3.14 -- Float
let price = 19.99d -- Decimal (exact precision)...
Variables
let x = 42
let name = "Alice"
let pi = 3.14159
...
Collections
Building Lists
-- Prepend element
let list1 =
1 :: [2, 3]
-- Concatenate lists
let list2 =...
Filter
-- Filter: keep matching elements
import List
[ 1
, 2
, 3...
Fold
-- Fold: reduce to single value
import List
[ 1
, 2
, 3...
Length
import List
fn length: [a] -> Int
fn length list =
case list of
[] -> 0...
List Access
let items =
[10, 20, 30]
items[0]List Ops
-- Prepend (cons)
let consed =
1 :: [2, 3]
-- Concatenation
let joined =...
List Pattern
let list =
[1, 2, 3]
case list of
[] -> "empty"
[x] -> "single element"...
Lists
let numbers =
[ 1
, 2
, 3
, 4
, 5...
Map
-- Map: transform each element
import List exposing (map)
[1, 2, 3]
|> map (|x| x * 2) -- [2, 4, 6]Nested Record
let data =
{ user = { profile = { name = "Alice" } } }
data.user.profile.nameRecord Access
let user =
{ name = "Alice", age = 30 }
user.nameRecord Destructure
let person =
{ name = "David", age = 40 }
let { name, age } = person
nameRecord Multi Update
let person =
{ name = "Alice", age = 30 }
let updated = { person | age = 31, name = "Alicia" }
updated.nameRecord Pattern
let person =
{ name = "Bob", age = 25 }
case person of
{ name, age } -> nameRecord Rest
let user =
{ name = "Carol", age = 35, email = "carol@example.com" }
case user of
{ name, .. } -> "Hello, " ++ nameRecord Update
-- Record update syntax
type alias Person = { name: String, age: Int }
let person =
{ name = "Alice", age = 30 }...
Record Workflow
let user =
{ name = "Eve", age = 28 }
-- Update fields (creates new record)
let updatedUser = { user | age = user.age + 1 }
...
Records
let user =
{ name = "Alice", age = 30, email = "alice@example.com" }
user.nameReverse
import List
fn reverse: [a] -> [a]
fn reverse list =
case list of
[] -> []...
Tuple Access
let pair = (1, "hello")
let first = pair.0 -- 1
let second = pair.1 -- "hello"
...
Tuple Access 2
let triple = (True, 42, "world")
triple.2Tuple Destructure
let (x, y) = (10, 20)
x + yTuple Pattern
let pair = (3, 0)
case pair of
(0, 0) -> "origin"
(x, 0) -> "on x-axis"
(0, y) -> "on y-axis"...
Tuples
let pair = (1, "one")
let triple = (True, 42, "hello")
let point = (3.5, 4.2)
...
Control Flow
Case Enum
type Color = Red | Green | Blue
let color = Color::Green
let description =
case color of...
Catchall
type Color = Red | Green | Blue
let color = Green
case color of
Red -> "primary"...
Else If
let score = 85
let grade =
if score >= 90 then "A"
else if score >= 80 then "B"
else if score >= 70 then "C"...
Exhaustive
type Color = Red | Green | Blue
let color = Blue
case color of
Red -> "red"...
Guard Exhaustive
let x = 0
case x of
n if n > 0 -> "positive"
n if n < 0 -> "negative"
_ -> "zero"Guards
let number = -5
case number of
n if n < 0 -> "negative"
n if n == 0 -> "zero"
n if n > 0 -> "positive"...
If Expression
let x = 5
let result =
if x > 0 then
"positive"
else...
If Multiline
let condition = True
if condition then
"yes"
else
"no"If Same Type
let condition = True
-- Valid: both branches return Int
if condition then
1
else...
If Type Mismatch
if condition then 1 else "zero" -- Error: type mismatchList Pattern
let numbers =
[1, 2, 3]
case numbers of
[] -> "empty list"
[x] -> "single element"...
Maybe Handling
let maybeUser = Just "Alice"
let displayName =
case maybeUser of
Just name -> name
Nothing -> "Anonymous"...
Maybe Type
type Maybe a = Just a | NothingMultiple Head
let list =
[ 1
, 2
, 3
, 4
]...
Nested Match
let data = (3, 4)
case data of
(a, b) -> a + bOr Patterns
type Day
= Monday
| Tuesday
| Wednesday
| Thursday
| Friday...
Recursive Sum
fn sum: [Int] -> Int
fn sum list =
case list of
[] -> 0
x :: xs -> x + sum xs
...
Result Handling
let parseResult = Ok 42
case parseResult of
Ok n -> "Parsed: " ++ show n
Err msg -> "Error: " ++ msgResult Type
type Result a e = Ok(a) | Err(e)Dataframe
Expr Aggregation
-- Aggregation with DataFrame.Expr
import DataFrame
import DataFrame.Expr as Expr
DataFrame.fromRecords
[ { value = 10 }...
Expr Basics
-- DataFrame.Expr for composable column operations
import DataFrame
import DataFrame.Expr as Expr
DataFrame.fromRecords
[ { name = "Alice", revenue = 100 }...
Expr Conditional
-- Conditional expressions with DataFrame.Expr
import DataFrame
import DataFrame.Expr as Expr
DataFrame.fromRecords
[ { name = "Alice", score = 95 }...
Expr String Ops
-- String operations with DataFrame.Expr
import DataFrame
import DataFrame.Expr as Expr
DataFrame.fromRecords
[ { name = "alice" }...
Lineage Tracking
-- Track data transformation history
import DataFrame
-- Create data and track transformations
DataFrame.fromRecords [{ product = "Laptop", revenue = 1200 }, { product = "Phone", revenue = 800 }]
|> DataFrame.filterGt "revenue" 700...
Recode
-- Remap values with automatic label transfer
import DataFrame
let df =
DataFrame.fromRecords
[ { id = 1, score = 1 }...
Value Labels
-- Attach value labels for coded variables
import DataFrame
import ValueLabelSet
let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female")]
...
Variable Labels
-- Variable labels for column descriptions
import DataFrame
let df =
DataFrame.fromRecords
[ { id = 1, gender = 1 }...
Window Functions
-- SQL-style window functions
import DataFrame
-- Sample sales data and window functions
DataFrame.fromRecords [{ product = "Laptop", revenue = 1200 }, { product = "Phone", revenue = 800 }]
|> DataFrame.withColumn "rank" [1, 2]...
Date
Arithmetic
-- Date arithmetic
import Date
let date = case Date.fromYmd 2024 3 15 of
Ok d -> d
Err _ -> Date.today ()...
Comparison
-- Comparing dates and computing differences
import Date
let start = case Date.fromYmd 2024 1 1 of
Ok d -> d
Err _ -> Date.today ()...
Components
-- Extracting date components
import Date
let date = case Date.fromYmd 2024 3 15 of
Ok d -> d
Err _ -> Date.today ()...
Create
-- Creating dates from year, month, day
import Date
Date.fromYmd 2024 3 15Parse
-- Parsing dates from strings
import Date
Date.parseIso "2024-06-15"Datetime
Interop Combine
-- Combine Date and Time into DateTime
import DateTime
import Date
import Time
let date = case Date.fromYmd 2024 6 15 of...
Interop Fromdate
-- Convert Date to DateTime at midnight UTC
import DateTime
import Date
let date = case Date.fromYmd 2024 1 1 of
Ok d -> d...
Interop Getdate
-- Extract Date component from DateTime
import DateTime
import Date
let dt = case DateTime.fromDate 2024 6 15 of
Just d -> d...
Interop Gettime
-- Extract Time component from DateTime
import DateTime
import Time
let dt = case DateTime.fromParts 2024 6 15 14 30 0 of
Just d -> d...
Decimal
Comparison
-- Decimal comparison and checks
import Decimal
let a = 10.5d
let b = 3.2d
...
Conversion
-- Converting between Decimal and other types
import Decimal
let price = 19.99d
-- Convert to string...
Literals
-- Decimal literals use the 'd' suffix
import Decimal
let price = 19.99d
let taxRate = 0.073d
...
Parsing
-- Parse a string into a Decimal
import Decimal
Decimal.parse "42.5"Rounding
-- Rounding decimals to specific precision
import Decimal
let price = 19.99d
let taxRate = 0.073d
let total = price + price * taxRate...
Duration
Arithmetic
-- Duration arithmetic
import Duration
let oneHour = Duration.fromHours 1
let thirtyMin = Duration.fromMinutes 30
...
Comparison
-- Duration comparison and checks
import Duration
let d = Duration.fromMinutes 90
Duration.isPositive dConversion
-- Converting between duration units
import Duration
let d = Duration.fromMinutes 150
-- Get total hours (truncated)...
Create
-- Creating and converting durations
import Duration
let twoHours = Duration.fromHours 2
Duration.toSeconds twoHoursError Handling
Block Align
if condition then
result1
else -- Error: 'else' must align with 'if'
result2Block Nest
let x =
x + 1 -- Error: Block must be indented more than parent
-- Hint: Indent the block to 4 spacesBool Correct
let x = True
let y = False
x && yBool Error
let x = true -- Error: 'true' is not a Keel keyword
-- Hint: Use `True` for boolean trueBounds Error
let items =
[1, 2, 3]
items[10] -- Error: Index 10 out of bounds for list of size 3Bounds Safe
let items =
[1, 2, 3]
items[0] -- 1Branch Correct
let x = 2
case x of
1 -> "one"
2 -> "two"
_ -> "other"Branch Mismatch
case x of
1 -> 42 -- Int
2 -> "hello" -- Error: Case branches have incompatible types: Int and String
_ -> 0Constructor Type
case Just 5 of
Ok n -> n -- Error: Pattern type mismatch: expected Maybe, but pattern is Result (Ok)
_ -> 0Correct Syntax
fn double: Int -> Int
fn double x =
x * 2
-- Pattern matching uses case...of
let value = Just 5...
Enum Case
type Direction = North | south -- Error: Enum variant must start with uppercaseFuzzy Multiple
let userName = "Alice"
let userAge = 30
let userEmail = "alice@example.com"
print usrNme
-- Error: Variable 'usrNme' is not declared. Did you mean 'userName', 'userAge', or 'userEmail'?Fuzzy Single
let userName = "Alice"
let userAge = 30
print usrName
-- Error: Variable 'usrName' is not declared. Did you mean 'userName'?Guard Correct
let x = 5
case x of
n if n > 0 -> "positive"
n if n < 0 -> "negative"
_ -> "zero"Guard Type
case x of
n if n + 1 -> "bad" -- Error: Guard expression must be Bool, found Int
_ -> "ok"Indent Error
fn example x =
let y = 1 -- Error: Expected indentation of at least 4 spaces
x + yJs Record
{ name: "Alice", age: 30 }
-- Error: JavaScript-style record syntax is not allowed
-- Hint: Use `=` instead of `:` for record field assignment
-- Example: `{ name = "Alice" }`Keywords
return 5 -- Hint: Keel is expression-based; the last expression is the return value
match x of -- Hint: Use `case ... of` for pattern matching
function add -- Hint: Use `fn` to define functions
var x = 5 -- Hint: Use `let` for variable bindingsMaybe Correct
let present = Just 42
let absent = Nothing
case present of
Just n -> "Got a value"...
Maybe Types
-- Safe error handling with Maybe
import List
import Maybe
-- Extract values with default fallback...
Null Error
let x = null -- Error: 'null' is not a Keel keyword
-- Hint: Use `Nothing` for absent valuesPattern Type
case 42 of
"hello" -> 1 -- Error: Pattern type mismatch: expected Int, but pattern is String
_ -> 0Record Correct
{ name = "Alice", age = 30 }Scope
let x =
let inner = 5
inner
print inner -- Error: Variable 'inner' is not in scopeType Mismatch
fn add: Int -> Int -> Int
fn add x y =
x + y
add "hello" 5 -- Error: Expected Int but got StringUndeclared
let x = unknownVar -- Error: Variable 'unknownVar' is not declaredFunctions
Arity Overloading 1
module Math exposing (..)
fn add: Int -> Int
fn add x =
x + 1
...
Arity Overloading 2
module Math exposing (..)
fn add: Int -> Int
fn add x =
x + 1
...
Defining
fn greet: String -> String
fn greet name =
"Hello, " ++ name ++ "!"
greet "Alice" -- "Hello, Alice!"Factorial
fn factorial: Int -> Int
fn factorial n =
if n <= 1 then
1
else
n * factorial (n - 1)...
Factorial Case
fn factorial: Int -> Int
fn factorial n =
case n of
0 -> 1
1 -> 1
_ -> n * factorial (n - 1)...
Fibonacci
fn fibonacci: Int -> Int
fn fibonacci n =
if n <= 1 then
n
else
fibonacci (n - 1) + fibonacci (n - 2)...
Higher Order
-- Takes a function as argument
fn applyTwice: (Int -> Int) -> Int -> Int
fn applyTwice f x =
f (f x)
applyTwice (|x: Int| x + 1) 5 -- 7Higher Order Context
module M exposing (..)
fn apply: (Int -> Int) -> Int -> Int
fn apply f x =
f x
...
Overloaded Hof
module Apply exposing (..)
fn apply: (Int -> Int) -> Int -> Int
fn apply f x =
f x
...
Overloading Int
module Math exposing (..)
fn double: Int -> Int
fn double x =
x * 2
...
Overloading String
module Math exposing (..)
fn double: Int -> Int
fn double x =
x * 2
...
Overloading Toplevel
fn inc: Int -> Int
fn inc x =
x + 1
fn inc: Float -> Float
fn inc x =...
Pipe Chain
fn double: Int -> Int
fn double x =
x * 2
fn addOne: Int -> Int
fn addOne x =...
Pipe Operator
-- Pipe operator provides context from the left operand
5
|> |x| x + 1Stdlib Chained Inference
import List
-- Type inference flows through chained operations
-- Each lambda's parameter type is inferred from the previous result
[ 1
, 2...
Stdlib Filter Inference
import List
-- Lambda parameter type inferred from List.filter signature
List.filter (|x| x > 2)
[ 1...
Stdlib Foldl Inference
import List
-- Accumulator and element types inferred from List.foldl signature
-- foldl : (b -> a -> b) -> b -> List a -> b
-- With initial value 0 (Int) and List Int, acc : Int and x : Int
List.foldl (|acc x| acc + x)...
Stdlib Map Inference
import List
-- Lambda parameter type inferred from List.map signature
List.map (|x| x * 2)
[1, 2, 3]...
Stdlib Zipwith Inference
import List
-- Both parameters inferred from List.zipWith signature
-- zipWith : (a -> b -> c) -> List a -> List b -> List c
-- With List Int and List Int, both x : Int and y : Int
List.zipWith (|x y| x * y)...
Type Signatures
fn add: Int -> Int -> Int
fn add x y =
x + y
add 3 4 -- 7Http
Indentation
Basic Blocks
-- Function body must be indented
fn addOne : Int -> Int
fn addOne x =
x + 1
addOne 5 -- 6Case Indentation
-- Case branches must be indented from 'case'
let value = 2
let result = case value of
1 -> "one"
2 -> "two"...
Case Multiline Body
-- Case branch bodies can span multiple lines
let value = 2
let result = case value of
1 ->
let x = 10...
Continuation Argument
-- Multiline arguments work with COLLECTIONS (lists, records, tuples)
-- NOT with simple values like integers
import List
-- This works: list on new indented line continues as argument...
If Multiline
-- If-then-else branches with multiline bodies
let condition = True
let result =
if condition then
let a = 1...
Let Block
-- Multiple let bindings at same indentation form a block
fn compute : Int -> Int
fn compute x =
let a = x + 1
let b = a * 2
let c = b - 3...
List Multiline
-- Lists can span multiple lines (Elm-style)
import List
let numbers =
[ 1
, 2...
Multiline Function Call
-- Multi-line function calls work with collections on new lines
import List
-- Lambda on same line, list on indented new line
let doubled = List.map (|x| x * 2)
[ 1...
Pipe Multiline
-- Pipes work naturally with multiline formatting
import List
let result = [1, 2, 3, 4, 5]
|> List.map (|x| x * 2)
|> List.filter (|x| x > 4)...
Record Multiline
-- Records can span multiple lines (Elm-style)
let person =
{ name = "Alice"
, age = 30
, city = "Paris"
}...
Scope Nested
-- Indentation creates nested scopes within a block
fn example : Int -> Int
fn example x =
let a = x + 1
let b = a * 2 -- 'a' is visible here
let c = a + b -- both 'a' and 'b' are visible...
Separate Expressions
-- Lines at the SAME indentation are separate expressions
let x = 1
let y = 2
let z = 3
-- Each let is a separate statement, evaluated in sequence...
Landing
Data Lineage
-- Automatic data lineage tracking
import DataFrame
let sales =
DataFrame.fromRecords
[ { product = "Laptop", revenue = 1200 }...
Data Processing
-- List operations with pipes
import List
let numbers =
[ 1
, 2...
Functional
-- Pipe operator for data flow
import String
let result =
"hello"
|> String.toUpper...
Pattern Matching
-- Maybe type for safe operations
import String
fn safeDivide: Float -> Float -> Maybe Float
fn safeDivide num denom =
if denom == 0.0 then...
Type System
-- Define a custom type
type Result a e = Ok(a) | Err(e)
-- Record with type alias
type alias Person = { name: String, age: Int }...
Modules
Access Add
module Math exposing (add, multiply)
fn add: Int -> Int -> Int
fn add x y =
x + y
...
Access Multiply
module Math exposing (multiply)
fn multiply: Int -> Int -> Int
fn multiply x y =
x * y
...
Exposing
-- Expose specific items
module exposing (functionA, functionB, TypeA)
-- Expose all
module exposing (..)
...
Fibonacci
module Math exposing (fibonacci)
fn fibonacci: Int -> Int
fn fibonacci n =
if n <= 1 then n
else fibonacci (n - 1) + fibonacci (n - 2)...
File Level
module exposing (User, createUser, getName)
type alias User = { name: String, age: Int }
fn createUser : String -> Int -> User
fn createUser name age = { name = name, age = age }...
Geometry Area
module Geometry exposing (Shape, area, perimeter)
import Math
type Shape = Circle(Float) | Rectangle(Float, Float) | Triangle(Float, Float, Float)
...
Geometry Perimeter
module Geometry exposing (perimeter)
fn perimeter: Float -> Float
fn perimeter r =
2.0 * 3.14159 * r
...
Import
import StringImport Alias
import Math as SomethingImport Aliases
-- Modules and import aliases
import Math as M
import List as L
M.abs (L.length [1, 2, 3])Import Exposing
import List exposing (map)
-- Using built-in list functions directly
[1, 2, 3]
|> map (|x| x * 2) -- [2, 4, 6]Indent Correct
module Math exposing (add)
fn add: Int -> Int -> Int
fn add x y =
x + y
...
Indent Error
-- Error: Inline module content must be indented
module Math exposing (add)
fn add x y = x + y -- Wrong: not indentedInline
module Math exposing (add, multiply)
fn add: Int -> Int -> Int
fn add x y =
x + y
...
Recursive
module Math exposing (factorial, fibonacci)
fn factorial: Int -> Int
fn factorial n =
if n <= 1 then 1
else n * factorial (n - 1)...
Operators
Arithmetic
let addition = 5 + 3
let subtraction = 10 - 4
let multiply = 6 * 7
...
Comparison
let eq = 5 == 5
let neq = 5 != 6
let lt = 3 < 5
...
Compose Backward
-- Backward composition (g first, then f)
let addOne = |x: Int| x + 1
let double = |x: Int| x * 2
let doubleThenAdd = addOne << double...
Compose Forward
-- Forward composition (f first, then g)
let addOne = |x: Int| x + 1
let double = |x: Int| x * 2
let addThenDouble = addOne >> double...
Division
let floatDiv = 10 / 3
let intDiv = 10 // 3
(floatDiv, intDiv)List Ops
-- Cons (prepend element)
let consed1 =
1 :: [2, 3]
let consed2 : List Int = 1 :: (2 :: [])
...
Logical
-- And (both must be True)
let and1 = True && True
let and2 = True && False
-- Or (at least one must be True)...
Pipe Forward
fn double: Int -> Int
fn double x =
x * 2
fn addOne: Int -> Int
fn addOne x =...
Pipeline
import List
-- Pipeline example
[ 1
, 2
, 3...
Short Circuit
-- False && ... returns False immediately without evaluating the right side
let result = False && True
result -- FalseString Concat
"Hello, " ++ "World!"Type Promotion
let x = 1 + 2.5
let y = 3 * 1.5
x + yPattern Matching
As Pattern
let maybe = Just 42
case maybe of
Just x as original -> (x, original)
Nothing -> (0, Nothing)As Pattern List
let list =
[1, 2, 3]
case list of
x :: xs as all -> "Head"
[] -> "empty"Branch Mismatch
case x of
1 -> 42 -- Int
2 -> "hello" -- Error: Case branches have incompatible types
_ -> 0Cons
let list =
[1, 2, 3]
case list of
x :: xs -> x -- x is the head, xs is the tail
[] -> 0 -- empty list caseConstructor
let maybeValue = Just 42
case maybeValue of
Just x -> "Got value"
Nothing -> "Nothing"Exhaustive
type TrafficLight = Red | Yellow | Green
let light = TrafficLight::Yellow
case light of
TrafficLight::Red -> "stop"...
Fn Nested
fn addPairs: (Int, Int) -> (Int, Int) -> (Int, Int)
fn addPairs p1 p2 =
case (p1, p2) of
((x1, y1), (x2, y2)) -> (x1 + x2, y1 + y2)
addPairs...
Fn Pattern
fn fst: (a, b) -> a
fn fst pair =
case pair of
(x, _) -> x
fst...
Guard Exhaustive
let x = 0
case x of
n if n > 0 -> "positive"
n if n < 0 -> "negative"
_ -> "zero"Guards
let number = 42
case number of
n if n < 0 -> "negative"
n if n == 0 -> "zero"
n if n < 10 -> "small positive"...
Lambda Record
-- Record destructuring
let describe =
|{ name: String, age: Int }| name
describe { name = "Bob", age = 25 }Lambda Tuple
-- Tuple destructuring
let addPair = |(x: Int, y: Int)| x + y
addPair
(3, 4) -- 7Let Record
let user =
{ name = "Alice", age = 30 }
let { name, age } = user
nameLet Tuple
let point = (10, 20)
let (x, y) = point
x + yList Exact
let list =
[1, 2]
case list of
[] -> "empty"
[x] -> "single"...
Literal
let x = 1
case x of
0 -> "zero"
1 -> "one"
_ -> "many"Multi Cons
let list =
[ 1
, 2
, 3
, 4
]...
Nested
import String
let result = Ok (Just 5)
case result of
Ok (Just x) -> "Success with value: " ++ String.fromInt x...
Or Binding
let point = (5, 2)
case point of
(x, 1) | (x, 2) | (x, 3) -> x -- x is bound in all alternatives
_ -> 0Or Pattern
type Direction
= North
| South
| East
| West
...
Record
let person =
{ name = "Alice", age = 30 }
case person of
{ name, age } -> nameRecord Rest
let user =
{ name = "Bob", age = 25, email = "bob@example.com" }
case user of
{ name, .. } -> "Hello, " ++ nameRecursive
fn sum: [Int] -> Int
fn sum numbers =
case numbers of
[] -> 0
x :: xs -> x + sum xs
...
Tuple
let pair = (3, 0)
case pair of
(0, 0) -> "origin"
(x, 0) -> "on x-axis"
(0, y) -> "on y-axis"...
Type Mismatch
case 42 of
"hello" -> 1 -- Error: Pattern type mismatch: expected Int, but pattern is String
_ -> 0Type Unify
let x = 2
case x of
1 -> 42 -- Int
2 -> 3.14 -- Float: compatible, unifies to Float
_ -> 0Unreachable
let x = False
case x of
_ -> "anything" -- This matches everything
True -> "true" -- Warning: Unreachable patternVariable
let point = (3, 4)
case point of
(x, y) -> x + yWildcard
let tuple = (42, "ignored")
case tuple of
(x, _) -> x -- Ignore second elementTable
Builder
-- Builder pattern for custom tables
import DataFrame
import Table
DataFrame.fromRecords
[ { region = "North", sales = 100 }...
Cross
-- Two-way cross-tabulation
import DataFrame
import Table
DataFrame.fromRecords
[ { gender = "M", group = "A" }...
Freq
-- One-way frequency table
import DataFrame
import Table
DataFrame.fromRecords
[ { category = "A" }...
Summary Stats
-- Summary statistics by group
import DataFrame
import Table
DataFrame.fromRecords
[ { region = "North", sales = 100 }...
Time
Arithmetic
-- Time arithmetic
import Time
let t = case Time.fromHms 14 30 0 of
Ok t -> t
Err _ -> Time.midnight ()...
Components
-- Extracting time components
import Time
let t = case Time.fromHms 14 30 0 of
Ok t -> t
Err _ -> Time.midnight ()...
Create
-- Creating time values
import Time
Time.fromHms 14 30 0Parse
-- Parsing time from strings
import Time
Time.parseIso "09:15:30"Types
Alias Resolved
type alias UserId = Int
let x = 42 -- UserId resolves to Int
let y = x -- Compatible: UserId is Int
...
Case Pattern
-- Case expression patterns
case (42, "test") of
(x, y) -> yCompound
-- List of integers
let numbers =
[1, 2, 3]
-- Tuple
let pair = (42, "answer")...
Dataframe Schemas
-- Compile-time schema validation
import DataFrame
-- Create typed data
DataFrame.fromRecords [{ name = "Alice", age = 30 }, { name = "Bob", age = 25 }]
|> DataFrame.select ["name", "age"]...
Generic Pair
type Pair a b = Pair a b
let p = Pair 1 "hello"
pGeneric Tree
type Tree a
= Leaf a
| Node (Tree a) a (Tree a)
let tree: Tree Int =
Node...
Hof Context
-- Higher-order function context
[1, 2, 3] |> map (|x| x * 2) -- x inferred as Int from list contextInference
let x = 42 -- Inferred as Int
let name = "Alice" -- Inferred as String
let ratio = 3.14 -- Inferred as Float
...
Inference Annotation
let empty: List Int = [] -- Needed: can't infer element type
length emptyLambda Annotation
|x| x + 1
|x: Int| x + 1Lambda Pattern
-- Lambda parameter patterns with context
(1, 2)
|> |(a, b)| a + bMaybe Type
type Maybe a = Just a | NothingMaybe Usage
let present = Just 42
let absent = Nothing
case present of
Just n -> "Got a value"...
Multiline Enum
type Direction
= North
| South
| East
| West
...
Numeric Promotion
let x = 1 + 2.5
let y = 3 * 1.5
x + yParameterized Alias
type alias Container a = { value: a }
let intBox =
{ value = 42 }
intBox.valuePipe Context
-- Pipe operator provides context
5
|> |x| x + 1Primitives
let x = 42
let pi = 3.14
let active = True
...
Record Type
type alias User = {
id: Int,
name: String,
email: String,
active: Bool
}...
Recursive
type MyList a = Nil | Cons a (MyList a)
let nums = Cons 1 (Cons 2 (Cons 3 Nil))
numsResult Err
let failure = Err "something went wrong"
case failure of
Ok value -> "Success"
Err msg -> "Error: " ++ msgResult Ok
let success = Ok 42
case success of
Ok value -> "Success"
Err msg -> "Error: " ++ msgResult Type
type Result a e = Ok a | Err eSimple Enum
type Direction = North | South | East | West
let heading = North
headingTuple Destructure
-- Tuple destructuring
let pair = (1, "hello")
let (x, y) = pair -- x: Int, y: String
yType Alias
type alias Name = String
type alias Age = Int
let userName = "Bob"
...
Using Enum
type Direction = North | South | East | West
let favorite: Direction = North
case favorite of
North -> "Going up"...
Variant Data Circle
type Shape
= Circle Float
| Rectangle Float Float
fn area : Shape -> Float
fn area shape = case shape of...
Variant Data Rect
type Shape
= Circle Float
| Rectangle Float Float
fn area : Shape -> Float
fn area shape = case shape of...
Variant Record
type User
= Guest
| Member { name: String, id: Int }
let user = Member { name = "Alice", id = 42 }
...
Valuelabelset
Coverage
-- Check which values lack labels
import ValueLabelSet
let labels = ValueLabelSet.fromList [(1, "Agree"), (2, "Disagree")]
let result = ValueLabelSet.coverage [1, 2, 3] labels
result.unlabeledCreate Lookup
-- Create a value label set and look up labels
import ValueLabelSet
let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female")]
ValueLabelSet.getLabel 1 genderMerge Filter
-- Merge two label sets and check size
import ValueLabelSet
let base = ValueLabelSet.fromList [(1, "Low"), (2, "Medium")]
let extra = ValueLabelSet.fromList [(3, "High")]
...
Reverse Lookup
-- Reverse lookup: find the code for a label
import ValueLabelSet
let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female")]
ValueLabelSet.getValue "Female" genderVariables
Data Transformation
let data = getRawData ()
let data = parseData data
let data = validateData data
-- each step shadows the previous bindingDeclaring
let name = "Alice"
let age = 30
let pi = 3.14159
...
Immutability
let x = 10
let x = 20 -- Error: Cannot reassign variable 'x'Let Expressions
let area =
let width = 10
let height = 5
width * height
area -- 50Multiple Bindings
let x = 1
let y = 2
let z = 3
...
Nested Destructuring
let (x, { a, b }) =
(1, { a = 2, b = 3 })
a -- 2Record Destructuring
let { name, age } =
{ name = "Bob", age = 25 }
name -- "Bob"Scope
let outer = 1
let result =
let inner = 2 -- Only accessible in this block
outer + inner
...
Shadowing
let x = 10
let x = x + 5
x -- 15Shadowing Type Change
let x = 1
let x = x + 1
let x = "hello" -- x can change type when shadowed
...
Tuple Destructuring
let (x, y) = (10, 20)
x -- 10Type Annotations
let count = 42
let message = "Hello"
let ratio = 0.75
...