# 自作言語 案
## 構文
### 方針
- Python に寄せた構文
- 記号はあまり使わない
- インデントはタブ
- インデントによるブロックは**必ず**その前の行の最後が `:`
- インデントは次の場合にしか使わない
- ブロック
- 一つの式を複数行にわたって記述する
- この場合改行 + それ以降の式は 1 インデント
- 記号ではなくなるべく文字を使う
- パターンマッチのパターンにできるものは大文字、それ以外は小文字
- 多相バリアント
### コメント
```=
# コメント
#-
複数行
-#
```
### ラムダ式
```=
f: Int -> Int
f = lambda(x):
x + 1
//同値
f: Int -> Int
def f(x):
x + 1
```
複数引数のラムダ式
```=
f: Int -> Int -> Int
f = lambda(x, y):
x + y
f: Int -> Int -> Int
def f(x, y):
x + y
```
自動でカリー化される
上のは下と同値
```=
f = lambda(x): lambda(y): x + y;
f: Int -> Int -> Int
def f(x):
lambda(y): x + y;
```
### let ブロック
def, lambda 式で使える
return の右の式が帰る
```=
def f(x):
y = 2
return x + y
f = lambda(x):
y = 2
return x + y
```
また、let ブロックとしても使える
```
x : Int = let:
y = 2
z = 3
return y + z
```
### Context
context 文で async await 的なことが出来る
```=
main : Context (EFF Void) Unit
main = context:
log("Hello World") # log : forall a op. Show a => a -> Context (EFF op) Unit
x <- random # random : forall op. Context (EFF op) Double
y = x + 1 # 単なる代入
log(y)
return unit
```
いわゆる Extensible Effects
### パターンマッチ
```=
x = match y:
case Just(z : Int) if w == z:
z + 1
case Nothing:
0
```
### if 式
```=
x =
if w == z:
1
else:
0
```
### 演算子
```
+, *, -, /, %
==, !=, <, >, =<, =>, &&, ||
++ # 配列、文字列の結合
|>, <| # パイプライン
```
### 型アノテーション
定義の時、引数に書ける
```=
f : Int -> Int
f = lambda(x: Int):
x + 1
```
### type 宣言
```=
type Hoge:
Fuga : Int -> Hoge
Piyo : String -> Hoge
FugaFuga : Hoge
type Maybe(t):
Nothing
Just(t)
```
### ジェネリクス、制約
```=
mp : forall t u. (t -> u) -> t -> u
def mp(f, x):
f(x)
append : forall t. Monoid t => t -> t -> t
append = ...
```
### 拡張可能バリアント
```=
type Foo(a):
Foo: forall y. Int -> Foo(x)
a
type Bar(x):
Bar: forall x. String -> Bar(x)
x
```
### クラス
```=
class Semigroup<t>:
append : t -> t -> t
class Monoid<t when Semigrop<t>>:
empty: t
instance Semigroup<String>:
append = ...
instance Monoid<String>:
empty = ""
class Reader<m when Monad<m>>:
type t: Type
read: m<t>
```
## FFI
### 外部 data 型
```=
foreign data HtmlDivElement :: Type;
```
### 値のインポート
別ファイル
```javascript=
const plusOne = (x) => x + 1
```
```=
foreign plusOne: Int -> Int;
```