Types
Kex models data directly: records for product types,
type for unions, ?
for optional values, and Result for fallible flows.
Records
record.kex
record Temperature do
celsius : Float
static do
let Freezing = Temperature { celsius: 0.0 }
end
end
let boiling = Temperature { celsius: 100.0 }
let freezing = Temperature.Freezing Sum types
union.kex
type ParseError = InvalidFormat(String) | Overflow | EmptyInput
let describe(e: ParseError) -> String do
match e do
InvalidFormat(s) -> "bad input: ${s}"
Overflow -> "out of range"
EmptyInput -> "got nothing"
end
end Optional
T? is sugar for an optional value. Constructors are
Just(value) and None. flatMap chains optional
computations.
optional.kex
# Using bare Optional<T>
let findUserTodo(todos, user, todo) -> Optional<Todo>
let todo = todos.find { |t| t.id == todo.id }
return None if todo.userId != user.id
return Just(todo)
end
# Using T? sugar
let findUser(users, name) -> User? do
return users.find { |u| u.name == name }
end
let email = users
.find(&.adult?)
.flatMap(&.email) # String? Result
Result<T, E> is either Ok(value) or
Error(reason). The ? operator returns early on an
Error, unwrapping an Ok.
result.kex
let parsePort(s: String) -> Result<Int, ParseError> do
return Error(EmptyInput) if s.empty?
match Integer.parse(s) do
Ok(n) -> do
return Error(Overflow) if n > 65535
return Ok(n)
end
Error(_) -> Error(InvalidFormat(s))
end
end Result<T, E> can also be simplified as T or! E.
result.kex
let parsePort(s: String) -> Int or! ParseError do
return Error(EmptyInput) if s.empty?
match Integer.parse(s) do
Ok(n) -> do
return Error(Overflow) if n > 65535
return Ok(n)
end
Error(_) -> Error(InvalidFormat(s))
end
end