flixで遊ぶ
Flixとは
Flix is a principled functional, logic, and imperative programming language developed at Aarhus University, at the University of Waterloo, and by a community of open source contributors.
Flix is inspired by OCaml and Haskell with ideas from Rust and Scala. Flix looks like Scala, but its type system is based on Hindley-Milner. Two unique features of Flix are its polymorphic effect system and its support for first-class Datalog constraints. Flix compiles to efficient JVM bytecode, runs on the Java Virtual Machine, and supports full tail call elimination.
Playground https://play.flix.dev/
代数的データ構造とパターンマッチングの例
/// An algebraic data type for shapes.
enum Shape {
case Circle(Int), // circle radius
case Square(Int), // side length
case Rectangle(Int, Int) // height and width
}
/// Computes the area of the given shape using
/// pattern matching and basic arithmetic.
def area(s: Shape): Int = match s {
case Circle(r) => 3 * (r * r)
case Square(w) => w * w
case Rectangle(h, w) => h * w
}
// Computes the area of a 2 by 4.
def main(_args: Array[String]): Int32 & Impure =
area(Rectangle(2, 4)) |> println;
0
多相レコード型の例なんだけどコンパイルできない
/// Returns the area of the polymorphic record `r`.
/// Note that the use of the type variable `a` permits the record `r`
/// to have labels other than `x` and `y`.
def polyArea[a : Record](r: {x: Int, y: Int | a}): Int = r.x * r.y
/// Computes the area of various rectangle records.
/// Note that some records have additional fields.
def polyAreas(): List[Int] =
polyArea({x = 1, y = 2}) ::
polyArea({x = 2, y = 3, z = 4}) :: Nil
def main(_args: Array[String]): Int32 & Impure =
polyAreas() |> println;
0
Function
def add(x: Int32, y: Int32): Int32 = x + y + 1
def main(_args: Array[String]): Int32 & Impure =
add(1, 2) |> println;
0
高階関数とラムダ式
def twice(f: Int32 -> Int32, x: Int32): Int32 = f(f(x))
def main(_args: Array[String]): Int32 & Impure =
twice(x -> x + 1, 2) |> println;
0
関数合成
def main(_args: Array[String]): Int32 & Impure =
let f = x -> x + 1;
let g = x -> x * 2;
let h = f >> g; // equivalent to x -> g(f(x))
h(5) |> println;
(f >> g)(2) |> println;
0
パイプライン
List.range(1, 100) |>
List.filter(x -> x % 2 == 0) |>
List.map(x -> x * x) |>
println;
Here x |> f is equivalent to the function application f(x).
これは関数適用にも使える
h(5) |> println;
2 |> (f >> g) |> println;
カリー化
def sum(x: Int32, y: Int32): Int32 = x + y
def main(_args: Array[String]): Int32 & Impure =
let inc = sum(1);
inc(42) |> println;
0
mapにリストを与えて関数だけをとる関数に変換する
def main(_args: Array[String]): Int32 & Impure =
List.range(1, 100) |>
List.map(x -> x + 1) |>
println;
0
Pure, Impure, and Effect Polymorphic Functions
全ての関数は暗黙的にPureとして定義される
def add(x: Int32, y: Int32): Int32 = x + y
def add(x: Int32, y: Int32): Int32 & Pure = x + y
コンソール出力するやつはImpure
def addAndPrint(x: Int32, y: Int32): Int32 & Impure =
let r = x + y;
println(r);
r
高階関数のPurityは引数に取る関数に応じて決まる
def map(f: a -> b & e, l: List[a]): List[b] & e = ...
List.map(x -> x + 123, l) // pure
List.map(x -> println(x), l) // impure