Open5

flixで遊ぶ

kazup0nkazup0n

Flixとは

https://doc.flix.dev/introduction/

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.

kazup0nkazup0n

代数的データ構造とパターンマッチングの例

https://play.flix.dev/?q=PQgEEEDtQQwGwOYFMBGAnGBLAxqAJjAC4yiECeADkqAGYD2aoAzgBYxVMB0AUEpAK4BbUAGU2VUAG9uoWaGwwm1AMKY02OEgAUASUiEAlABo5p0GGxqN1DHkz8mMuQqWiAjvxhptewybOyYEyYeNSakAiELE6yLtQASkjYxBGauvomvgbmwKAsSJgILISwkHigAO4hUdwAvtzcILnKdIIU-IRITKT5sN4kdDQ91AiYAG58zOLUDpgRjWAURJ1o0IJE2CxzCKXlKIo4fZhRgkiEODyhQ15IMFpMAFyi0wZPvqAAvKDrhJvMUjF5IoVFY0mhsgEPgA+UAAZlAACpQFpGEjwYC4u5PN4tBUIWZoZVEZUMcDQIlkjBUtoWCY8Z8YSxiRU6g0wC02h0usM+rdQINYKAAEygFBkUAAFkuSCG6zmWgA+l4EI8IGgMGQANoiQhobYAXVeoF8sJFADJjZzvJ9QICbncKSkEGkhSYJQZsgAfGEUPX6OCQADcgIADEA

/// 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
kazup0nkazup0n

多相レコード型の例なんだけどコンパイルできない

/// 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
kazup0nkazup0n

Function

https://doc.flix.dev/functions/

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