Kind2/README.md

315 lines
8.4 KiB
Markdown
Raw Normal View History

2021-02-20 02:11:49 +03:00
# Kind
2021-06-03 17:38:08 +03:00
A minimal, efficient and practical proof and programming language. Under the hoods, it is basically Haskell, except purer and with dependent types. That means it can handle mathematical theorems just like Coq, Idris, Lean and Agda. On the surface, it aims to be more practical and looks more like TypeScript. Compared to other proof assistants, Kind has:
2021-05-16 03:05:34 +03:00
2021-08-11 16:41:40 +03:00
1. The smallest core. Check [FormCore.js](https://github.com/moonad/FormCoreJS/blob/master/FormCore.js) or [Core.kind](https://github.com/uwu-tech/Kind/blob/master/base/Kind/Core.kind). Both are `< 1000-LOC` complete implementations!
2021-05-16 03:05:34 +03:00
2021-06-03 17:38:08 +03:00
2. Novel type-level features. Check [this article](https://github.com/uwu-tech/Kind/blob/master/blog/1-beyond-inductive-datatypes.md) on super-inductive datatypes.
2021-05-16 03:05:34 +03:00
2021-06-03 17:38:08 +03:00
3. An accessible syntax that makes it less scary. Check [SYNTAX.md](https://github.com/uwu-tech/Kind/blob/master/SYNTAX.md).
2021-05-16 03:05:34 +03:00
2021-06-03 17:38:08 +03:00
4. A complete bootstrap: the language is implemented in itself. Check it [here](https://github.com/uwu-tech/Kind/tree/master/base/Kind).
2021-05-16 03:09:52 +03:00
2021-06-03 17:12:27 +03:00
5. Efficient real-world compilers. Check [http://uwu.tech/](http://uwu.tech) for a list of apps. (WIP)
2021-05-16 03:05:34 +03:00
2021-02-20 02:11:49 +03:00
Usage
-----
2021-06-03 19:29:24 +03:00
![npm](https://img.shields.io/npm/v/kind-lang) [![telegram](https://img.shields.io/badge/chat-on%20telegram-blue)](https://t.me/formality_lang)
2021-02-20 02:11:49 +03:00
2021-07-02 22:08:47 +03:00
0. Choose a release. We'll use JavaScript here but ChezScheme is also [available](/INSTALL.md).
1. Install Kind using `npm`:
2021-06-03 17:38:08 +03:00
2021-02-20 04:06:17 +03:00
```bash
2021-06-03 17:38:08 +03:00
npm i -g kind-lang
```
2. Save the file below as `Main.kind`:
2021-08-12 15:47:02 +03:00
```javascript
2021-06-03 17:38:08 +03:00
Main: IO(Unit)
IO {
IO.print("Hello, world!")
}
```
3. Type-check it:
2021-08-12 15:47:02 +03:00
```bash
2021-06-03 17:38:08 +03:00
kind Main
```
4. Run it:
2021-08-12 15:47:02 +03:00
```bash
2021-06-03 17:38:08 +03:00
kind Main --run
```
5. Have fun!
Things you can do with Kind:
2021-06-03 17:39:40 +03:00
----------------------------
2021-06-03 17:38:08 +03:00
2021-06-03 17:50:45 +03:00
### Compile programs and modules to several targets.
2021-06-03 17:38:08 +03:00
2021-08-12 00:51:12 +03:00
Kind has an universal compiler that targets several back-ends. Just find what you need on Kind, and compile it with `kind Main --lang`. For example, to generate a QuickSort function in JavaScript, just type `kind List.quicksort --js`. You may never write code in any other language! Available targets: `--js`, `--scm`. Several more will be available eventually.
2021-02-20 02:11:49 +03:00
2021-06-03 17:50:45 +03:00
### Create live applications.
2021-02-20 02:11:49 +03:00
2021-06-03 17:50:45 +03:00
Kind has an interconnected back-end that allows you to create rich, interactive applications without ever touching databases, TCP packets or messing with apis. Just add a file to `base/App` and it will be available on [http://uwu.tech/](http://uwu.tech). You can fork entire applications - not just the front-end, but all of it, back-end, database, and networking - in seconds.
2021-06-03 17:38:08 +03:00
2021-06-03 17:50:45 +03:00
### Prove theorems.
2021-06-03 17:38:08 +03:00
2021-08-11 18:32:14 +03:00
No, theorems are not scary things mathematicians do. For programmers, they're more like unit tests, except they can involve symbols, allowing you to cover infinitely many test cases. If you like unit tests, you'll love theorems. To learn more, check [THEOREMS.md](THEOREMS.md). You can also compile Kind programs and proofs to a minuscle core language with the `--fmc` flag (example: `kind Nat.add.assoc --fmc`). Try it!
2021-06-03 17:38:08 +03:00
2021-06-03 17:50:45 +03:00
### Deploy Smart-Contracts.
2021-06-03 17:38:08 +03:00
2021-08-11 19:58:37 +03:00
(Soon.)
2021-05-16 04:39:58 +03:00
2021-02-20 02:11:49 +03:00
Examples
--------
2021-05-16 05:51:37 +03:00
### Some programs
2021-02-20 02:11:49 +03:00
2021-05-16 04:52:12 +03:00
```javascript
2021-05-16 05:51:37 +03:00
// A 'Hello, world!"
2021-02-20 02:11:49 +03:00
Main: IO(Unit)
IO {
2021-02-20 02:11:49 +03:00
IO.print("Hello, world!")
}
```
2021-05-16 04:52:12 +03:00
```javascript
2021-05-16 05:51:37 +03:00
// Quicksort (using recursion)
2021-05-16 04:47:09 +03:00
quicksort(list: List<Nat>): List<Nat>
2021-05-16 04:45:32 +03:00
case list {
nil:
[]
cons:
2021-05-16 04:54:43 +03:00
fst = list.head
min = filter!((x) x <? list.head, list.tail)
2021-08-11 20:38:45 +03:00
max = filter!((x) x >=? list.head, list.tail)
2021-05-16 04:47:09 +03:00
quicksort(min) ++ [fst] ++ quicksort(max)
2021-05-16 04:45:32 +03:00
}
2021-05-16 04:50:25 +03:00
```
2021-05-16 04:45:32 +03:00
2021-05-16 04:52:12 +03:00
```javascript
2021-05-16 05:51:37 +03:00
// List iteration (using folds)
some_text: String
2021-05-16 05:49:35 +03:00
List.foldl!!("",
(str, result)
str = String.to_upper(str)
str = String.reverse(str)
result | str,
["cba","fed","ihg"])
2021-05-16 04:50:25 +03:00
```
2021-02-20 02:11:49 +03:00
2021-05-16 04:52:12 +03:00
```javascript
2021-05-16 05:51:37 +03:00
// List iteration (using fors)
some_text: String
2021-05-16 05:49:35 +03:00
result = ""
for str in ["cba","fed","ihg"] with result:
str = String.to_upper(str)
str = String.reverse(str)
result | str
result
2021-05-16 04:50:25 +03:00
```
2021-05-16 04:49:28 +03:00
2021-05-16 04:50:25 +03:00
```c
2021-05-16 05:49:35 +03:00
// Map, Maybe, String and Nat sugars
2021-05-16 05:51:37 +03:00
sugars: Nat
2021-05-16 04:49:28 +03:00
key = "toe"
map = {"tic": 1, "tac": 2, key: 3} // Map.from_list!([{"tic",1}, ...])
map = map{"tic"} <- 100 // Map.set!("tic", 100, map)
map = map{"tac"} <- 200 // Map.set!("tac", 200, map)
map = map{ key } <- 300 // Map.set!(key, 300, map)
val0 = map{"tic"} <> 0 // Maybe.default!(Map.get!("tic",map), 0)
val1 = map{"tac"} <> 0 // Maybe.default!(Map.get!("tac",map), 0)
val2 = map{ key } <> 0 // Maybe.default!(Map.get!(key, map), 0)
2021-05-16 04:53:41 +03:00
val0 + val1 + val2 // Nat.add(val0, Nat.add(val1, val2))
2021-02-20 02:11:49 +03:00
```
2021-07-06 22:35:11 +03:00
```c
// List monadic block: returns [{1,4},{1,5},{1,6},{2,4},...,{3,6}]
my_list: List<Pair<Nat,Nat>>
List {
get x = [1, 2, 3]
get y = [4, 5, 6]
return {x, y}
}
```
2021-05-16 04:47:09 +03:00
Check many List algorithms on [base/List](https://github.com/uwu-tech/Kind/tree/master/base/List)!
2021-02-20 02:11:49 +03:00
### Some types
2021-05-16 04:52:12 +03:00
```javascript
2021-05-16 05:58:59 +03:00
// A boolean
type Bool {
true
false
}
```
```javascript
// A natural number
type Nat {
zero
succ(pred: Nat)
2021-02-20 02:11:49 +03:00
}
2021-05-16 05:52:23 +03:00
```
2021-02-20 02:11:49 +03:00
2021-05-16 05:52:23 +03:00
```javascript
2021-05-16 06:10:04 +03:00
// A polymorphic list
type List <A: Type> {
nil
2021-05-16 06:12:33 +03:00
cons(head: A, tail: List<A>)
2021-02-20 02:11:49 +03:00
}
2021-05-16 05:52:23 +03:00
```
2021-02-20 02:11:49 +03:00
2021-05-16 05:52:23 +03:00
```javascript
2021-05-16 06:10:04 +03:00
// A polymorphic pair
type Pair <A: Type, B: Type> {
new(fst: A, snd: B)
2021-02-20 02:11:49 +03:00
}
2021-05-16 05:52:23 +03:00
```
2021-02-20 02:11:49 +03:00
2021-05-16 05:52:23 +03:00
```javascript
2021-05-16 06:10:04 +03:00
// A polymorphic dependent pair
type Sigma <A: Type, B: A -> Type> {
new(fst: A, snd: B(fst))
2021-02-20 02:11:49 +03:00
}
2021-05-16 05:52:23 +03:00
```
2021-02-20 02:11:49 +03:00
2021-05-16 05:52:23 +03:00
```javascript
2021-05-16 06:10:04 +03:00
// A polymorphic list with a statically known size
2021-02-20 02:11:49 +03:00
type Vector <A: Type> ~ (size: Nat) {
2021-02-20 04:22:31 +03:00
nil ~ (size = 0)
2021-05-16 06:12:33 +03:00
cons(size: Nat, head: Nat, tail: Vector<A,size>) ~ (size = 1 + size)
2021-02-20 02:11:49 +03:00
}
2021-05-16 05:52:23 +03:00
```
2021-02-20 02:11:49 +03:00
2021-05-16 05:58:59 +03:00
```javascript
// A bounded natural number
type Fin ~ <lim: Nat> {
2021-05-16 06:12:33 +03:00
zero<N: Nat> ~ (lim = Nat.succ(N))
succ<N: Nat>(pred: Fin<N>) ~ (lim = Nat.succ(N))
2021-05-16 05:58:59 +03:00
}
```
2021-05-16 05:52:23 +03:00
```javascript
2021-05-16 06:03:02 +03:00
// The type used in equality proofs
2021-05-16 04:54:15 +03:00
type Equal <A: Type, a: A> ~ (b: A) {
2021-02-20 04:22:31 +03:00
refl ~ (b = a)
2021-02-20 02:11:49 +03:00
}
```
2021-05-16 06:03:02 +03:00
```javascript
// A burrito
type Monad <M: Type -> Type> {
new(
2021-05-16 06:12:33 +03:00
bind: <A: Type, B: Type> M<A> -> (A -> M<B>) -> M<B>
pure: <A: Type> A -> M<A>
2021-05-16 06:03:02 +03:00
)
}
2021-05-16 05:58:59 +03:00
```
2021-05-16 06:03:02 +03:00
```javascript
// Some game entity
2021-05-16 05:58:59 +03:00
type Entity {
player(
name: String
pos: V3
health: Nat
2021-05-16 06:12:33 +03:00
items: List<Item>
2021-05-16 05:58:59 +03:00
sprite: Image
)
wall(
2021-05-16 06:12:33 +03:00
hitbox: Pair<V3, V3>
2021-05-16 05:58:59 +03:00
collision: Entity -> Entity
sprite: Image
)
}
```
2021-05-16 04:49:28 +03:00
Check all core types on [base](https://github.com/uwu-tech/Kind/tree/master/base)!
2021-02-20 02:11:49 +03:00
### Some proofs
2021-05-16 04:52:12 +03:00
```javascript
2021-02-20 03:57:38 +03:00
// Proof that `a == a + 0`
Nat.add.zero(a: Nat): a == Nat.add(a, 0)
case a {
zero: refl
succ: apply(Nat.succ, Nat.add.zero(a.pred))
}!
2021-05-16 05:52:23 +03:00
```
2021-02-20 03:57:38 +03:00
2021-05-16 05:52:23 +03:00
```javascript
2021-02-20 04:06:17 +03:00
// Proof that `1 + (a + b) == a + (1 + b)`
2021-02-20 03:57:38 +03:00
Nat.add.succ(a: Nat, b: Nat): Nat.succ(a + b) == (a + Nat.succ(b))
case a {
zero: refl
succ: apply(Nat.succ, Nat.add.succ(a.pred, b))
}!
2021-05-16 05:52:23 +03:00
```
2021-02-20 03:57:38 +03:00
2021-05-16 05:52:23 +03:00
```javascript
2021-02-20 03:57:38 +03:00
// Proof that addition is commutative
Nat.add.comm(a: Nat, b: Nat): (a + b) == (b + a)
case a {
zero:
Nat.add.zero(b)
succ:
2021-05-16 04:54:43 +03:00
p0 = Nat.add.succ(b, a.pred)
p1 = Nat.add.comm(b, a.pred)
2021-02-20 03:57:38 +03:00
p0 :: rewrite X in Nat.succ(X) == _ with p1
}!
2021-02-20 02:11:49 +03:00
```
2021-05-16 04:47:09 +03:00
Check some Nat proofs on [base/Nat/add](https://github.com/uwu-tech/Kind/tree/master/base/Nat/add)!
2021-05-16 04:09:37 +03:00
### A web app
2021-05-16 04:04:05 +03:00
```javascript
// Render function
App.Hello.draw: App.Draw<App.Hello.State>
(state)
2021-07-11 19:21:38 +03:00
<div style={"border": "1px solid black"}>
<div style={"font-weight": "bold"}>"Hello, world!"</div>
<div>"Clicks: " | Nat.show(state@local)</div>
<div>"Visits: " | Nat.show(state@global)</div>
</div>
2021-05-16 04:04:05 +03:00
// Event handler
App.Hello.when: App.When<App.Hello.State>
(event, state)
case event {
init: IO {
App.watch!(App.room_zero)
App.new_post!(App.room_zero, App.empty_post)
}
mouse_down: IO {
App.set_local!(state@local + 1)
}
} default App.pass!
```
2021-05-16 05:00:42 +03:00
Source: [base/App/Hello.kind](https://github.com/uwu-tech/Kind/blob/master/base/App/Hello.kind)
2021-05-16 04:04:05 +03:00
2021-05-23 21:19:51 +03:00
Live: [http://uwu.tech/App.Hello](http://uwu.tech/App.Hello)
2021-08-11 19:58:37 +03:00
In order to run this or any other app you should follow this steps:
- The app should be in `base/App` folder
- Install necessary packages in web folder with `npm i --prefix web/`
- Install `js-beautify` using `sudo npm i -g js-beautify`
- Run our local server with `node web/server`
- Build the app you want with `node web/build App.[name of app]` (in this example would be `node web/build App.Hello`)
- Open `localhost` in your favorite browser and see your app working
2021-08-11 19:58:37 +03:00
Future work
-----------
There are so many things we want to do and improve. Would like to contribute? Check [CONTRIBUTE.md](https://github.com/uwu-tech/Kind/blob/master/CONTRIBUTE.md). Also reach us on [Telegram](https://t.me/formality_lang). We're friendly!