(This document is a draft.)
- GitHub Community: http://github.com/fold-lang
-- Single-line comments start with a doulbe dash.
---
In addition to the single-line comments there are block comments that start
with a triple dash and inline block comments delimited by `-- { ... }`.
---
-- Boolean operators are infix functions `and` and `or`.
-> true and true or false
= true :: Bool
-- An integer value.
-> 42
= 42 :: Int
--
-- Data Structures: Lists
--
-> [1, 2, 3, 4, 5]
= [1, 2, 3, 4, 5] :: [Int]
-- Lists support range syntax.
-> [1 .. 5]
= [1, 2, 3, 4, 5] :: [Int]
-> [1 .. 5]
= [1, 2, 3, 4, 5] :: [Int]
-- Lists also support pattern matching.
-> [head, tail...] = [1 .. 5]
= 1 :: Int
= [2, 3, 4, 5] :: [Int]
--
-- Data Structures: Tuples
--
-- Tuples are heteogenic fixed-size data containers.
-> (1, 'a', "hello", [1 .. 10])
= (1, 'a', "hello", [1 .. 10]) :: (int, char, string, [int])
-- Pattern matching is used for variable bindings.
-> a = (2.3, 'λ')
= (2.3, 'λ') :: (float, char)
-> a, [head, rest...] = ("Свобода", [1, 2, 3, 4])
= "Свобода" :: string
= 1 :: Int
= [2, 3, 4] :: [Int]
-- Type annotations can be used anywhere in the expressions.
-> ("Hello " :: string) + "World!"
= "Hello World!" :: string
--
-- Data Structures: Records.
--
-- A record is just a tuple with labeled values.
-> a = {x = 2, y = 3}
= {x = 2, y = 3} :: {x :: int, y :: int}
-- The previous record was an example of an anonymous record.
-- Although it was bound to a variable `a`, the record type was not
-- previously declared.
-> type point = {x :: int, y :: int}
= type {x :: int, y :: int}
-> p = {x = 2, y = 3}
= {x = 2, y = 3} :: point
-- Record update syntax.
-> {p | x = 100, y = y + 50}
--
-- Functions
--
-- Function application.
-> sum 2 (1 + 1)
= 4
-- Function application has precedence over operators.
-> sum 1 1 * 2 -- The precendence is as in `(sum 1 1) * 2`.
= 4 :: int
-- Lambda functions.
-> \n -> n * n
= λ :: Int -> Int
-> map
= map :: (a -> b) -> [a] -> [b]
-> map (1 +) [1 .. 5]
-- Pattern matching lambda.
-> hello = \ None -> "Hello World" | Some name -> "Hello " + name
= hello :: String? -> String
-- String interpolation operator `%` with `{}` for formating.
-> function hello name lang
~ print % "{greeting lang}, {String.capitalize name}."
~ where greeting = case lang:
~ | "en" -> "Hello"
~ | "pt" -> "Olá"
~ | "ru" -> "Привет"
~ | _ -> error "Unsuported language."
~ end
= hello :: String -> String -> unit
-> alice, lang = "Maria Alice", "ru"
= "Maria Alice" :: string
= "ru" :: string
-- Regular positional application.
-> hello "Alice" "en"
= () :: unit
"Hello, Alice."
-- Named keyword application.
-> hello name: "Alice" lang: "en"
= () :: unit
"Hello, Alice."
-- The order of the keyword arguments does not have to be the same as in
-- the definition. The remaining positional arguments will be applied by
-- the provided order.
-> map (hello lang: "pt") ["João" "Maria" "André"]
= ["Hello, João!" "Hello, Maria!" "Hello, André!"]
-- Named keyword application with scoped variable.
-> hello ~lang name: "Alice"
= () :: unit
-- The previous application is equivalent to:
-> hello lang: lang name: "Alice"
= () :: unit
-- Recursive factorial function implementation.
-> factorial = \ 0 -> 1
> | n -> n * factorial (n - 1)
= factorial :: Int -> Int
-- Function composition and reverse application.
-> [1 .. 10] => filter even >> reverse >> take 3
= [6 4 2]
-> iterate (+ "a") "" => take 5 >> tail >> filter (\s -> length s < 4)
= ["a", "aa", "aaa"] :: string list
-- Operators are functions.
-> (+)
= (+) :: {Number a} -> a -> a -> a
-> help (+)
= (+) :: {Number a} -> a -> a -> a
Produces a sum of two numerical values.
The parameters of the sum function must implement the Number interface.
-> help help
= help :: a -> a
Help function.
Acts as an identity function and prints expression docstring.
-- Sum all numbers in a list:
-> reduce (+) [1 .. 5]
= 15 :: Int
-- Function definition.
-- Finds the maximum number in a list.
-> max list = reduce (\a b -> if (a > b) then: a else: b) list
= max :: [Int] -> Int
-> max [2, 10, 3, 6, 9, 9]
= 10
-- `for` macro.
-> for i <- [1 .. 3]:
> print ("Number: " + (i + 2)::String)
Number: 3
Number: 4
Number: 5
-> last list =
> case list:
> | [] -> None
> | [x] -> Some x
> | [x, rest...] -> last rest
= last :: [a] -> a?
-- Some HTML
-> div class: "menu-container":
ul id: "menu" class: "default-menu":
map (li class: "menu-item") ["Home" "Products" "Contacts"]
-- `:` is a right associative function application operator, similar to Haskell's `$`.
--
-- Modules
--
-> interface Comparable {a}
> type Ordering = LT | EQ | GT
> compare :: a -> a -> Ordering
> end
-> module Comparable {int}
> compare x y =
> if | x == y -> EQ
> | x > y -> GT
> | x < y -> LT
> end
-- Function definition with docstring.
-> "Quick-sort sorting algorithm."
> quicksort L (<) = match L:
> | [] => []
> | [x, xs...] => head + [x] + tail
> where head = quicksort (filter (\e -> e < x) xs) (<)
> tail = quicksort (filter (\e -> not (e < x)) xs) (<)
= quicksort :: {Ord a} -> [a] -> (a -> a -> Ordering)
-- Print function definition.
-> print :: {Show a} -> [a] -> end: String -> sep: String -> Unit
-> print args... (end = "\n") (sep = " ") =
IO.write ((String.join (map show args) with: sep) + end) to: IO.stdout
-> print "Hello" "World!" sep: ", "
Hello, World!
-- Function definition with meta-data.
{doc: "Produces a list of integers given the `start` and the `end`."
added: 1.0, author: "Rizo Isrof"}
function range (from start = 0) (to stop) (by step = 1) -> [Int]
if | start == stop -> []
| else -> [start & (range (start + 1) stop step)]
end
:: range :: from: Int? -> to: Int -> by: Int? -> [Int]
-> range from: 10 to: 20 by: 5
:: [Int] = [10, 15, 20]
let rec filter pred =
await >>= fun a ->
if pred a then yield a >> lazy (filter pred)
else filter pred
filter pred = do
a <- await
if | pred a -> yield a; filter pred
| else -> filter pred
end