Upgrade to Pro — share decks privately, control downloads, hide ads and more …

最強JVM系関数型論理プログラミング言語、その名は Flix

最強JVM系関数型論理プログラミング言語、その名は Flix

Flixの簡単な紹介です(@第五回関数型プログラミング(仮)の会)

Kenichi SUZUKI

January 26, 2024
Tweet

More Decks by Kenichi SUZUKI

Other Decks in Programming

Transcript

  1. 最強JVM系関数型
    論理プログラミング言語、
    その名は Flix
    第五関数型プログラミング(仮)の会
    2024-01-26
    The Flix Programming Language
    knih

    View full-size slide

  2. 最強JVM系関数型
    論理プログラミング言語、
    その名は Flix
    第五関数型プログラミング(仮)の会
    2024-01-26
    The Flix Programming Language
    knih
    注:個人主観

    View full-size slide

  3. 3
    The Flix Programming Language
    Next-generation reliable, safe,
    concise, and functional-first
    programming language.

    View full-size slide

  4. 4
    Flix
    ● 中心的な開発者はオーフス大学のMagnus Madsen先生
    https://cs.au.dk/~magnusm/
    開発にはOSSコミュニティや研究者らが関わっている
    ● Aarhus University(デンマーク)
    ● the University of Waterloo(カナダ)
    ● the University of Tübingen(ドイツ)
    ● the University of Copenhagen(デンマーク)

    View full-size slide

  5. 5
    Flixのなにがすごいの?

    View full-size slide

  6. バランスがすごい
    6
    代数的データ型はもちろん、拡張可能レコードや高階カインド、多相エフェクト、はたまたDatalogもサポート
    Flix aims to offer a unique combination of features that
    no other programming language
    “


    View full-size slide

  7. Flixが提供する代表機能
    7
    拡張可能レコードと多相エフェクトが!!!!!
    拡張可能レコード
    トレイト(型クラス)
    高階カインド
    JVMバイトコードへのコンパイル
    多相エフェクトシステム
    region-based local mutation
    Purity reflection
    第一級Datalog constraint
    多言語にある特徴 ユニークな機能
    これ以外にもおもしろ機能がたくさん

    View full-size slide

  8. Hello WorldからみるFlix
    8
    def main(): Unit \ IO =
    println("Hello World!")
    戻りの型 エフェクト
    def main(): String \ {} =
    "Hello World!"
    def main(): String =
    "Hello World!"
    エフェクトがないので
    Emptyになる
    エフェクトがない場合
    は省略できる

    View full-size slide

  9. もちろんある、代数的データ型
    9
    enum Shape {
    case Circle(Int32),
    case Square(Int32),
    case Rectangle(Int32, Int32)
    }
    def area(s: Shape): Int32 = match s {
    case Shape.Circle(r) => 3 * (r * r)
    case Shape.Square(w) => w * w
    case Shape.Rectangle(h, w) => h * w
    }
    def main(): Unit \ IO =
    println(area(Shape.Rectangle(2, 4)))

    View full-size slide

  10. レコード
    10
    let p1 = { x = 1, y = 2 };
    let p2 = { x = 3 | p1 };
    p1.x + p2.x
    def f(r: {x = Int32, y = Int32}): Int32 =
    r.x + r.y
    def g(r: {x = Int32, y = Int32 | s}): Int32 =
    r.x + r.y
    g({x=1,y=2,z=3})

    View full-size slide

  11. レコード
    11
    def withAccountId(r: {| a}, aid: AccountId): {id = AccountId | a} =
    {+accountId=aid | r}
    def withoutName(r: {name = String | a}): {| a} =
    {-name | r}

    View full-size slide

  12. オブジェクト指向の機能を取り入れていない
    12
    Flixでは、これまでとは違う方向性で、まっさらな
    状態から始めたいと思いました。私の経験では、
    Scalaでの関数型プログラミングは、Scalaの型推論
    の制限により、時に面倒に感じることがあります。
    さらに重要なことに、オブジェクト指向プログラミ
    ングは間違った方向に進んでいると確信することが
    多くなりました。特にオブジェクト指向の古典的な
    特徴(あるいは価値)である、オブジェクトの同一
    性、変更可能な状態、クラス継承は、プログラムを
    構成し考えるための正しい方法ではないと私は感じ
    ています。
    “

    Johan Janssen (2022). Interview with Magnus Madsen about the Flix Programming Language.
    InfoQ. https://www.infoq.com/news/2022/02/flix-programming-language/

    View full-size slide

  13. Region-based Local Mutation
    局所的に破壊的変更ができる!パフォーマンスのいいプログラムが安全に書ける!
    13
    def toString(someList: List[a]): String with ToString[a] =
    region r {
    let sb = StringBuilder.new(r);
    foreach (x <- someList) {
    StringBuilder.appendString!("${x} :: ", sb)
    };
    StringBuilder.appendString!("Nil", sb);
    StringBuilder.toString(sb)
    }

    View full-size slide

  14. 多相エフェクト
    mapのなかで副作用を起こしてしまう問題もこれで安心
    14
    def map(f: a -> b \ eff, xs: List[a]): List[b] \ eff =
    match l {
    case Nil => Nil
    case x :: xs => f(x) :: map(f, xs)
    }

    View full-size slide

  15. 型クラスの自動導出も便利
    15
    enum Month with Eq, Order, ToString {
    case January
    case February
    case March
    case April
    case May
    case June
    case July
    case August
    case September
    case October
    case November
    case December
    }

    View full-size slide

  16. 高階カインド
    16
    trait ForEach[t: Type -> Type] {
    pub def forEach(f: a -> Unit \ ef, x: t[a]): Unit \ ef
    }
    instance ForEach[List] {
    pub def forEach(f: a -> Unit \ ef, l: List[a]): Unit \ ef = match l {
    case Nil => ()
    case x :: xs => f(x); ForEach.forEach(f, xs)
    }
    }

    View full-size slide

  17. forM, forA
    17
    def validateUsername(name: String): Validation[Err, UserName] = ...
    def validateJobType(jobType: String): Validation[Err, JobType] = ...
    def createAccount(n: UserName, j: JobType): Validation[Err, Account] =
    forA (
    name <- validateUsername(n);
    jobType <- validateJobType(j)
    ) yield Account(name, jobType)

    View full-size slide

  18. 第一級 Datalog constraint
    18
    def main(): Unit \ IO =
    let facts = #{
    Interpreter("x86").
    Compiler("Scala", "x86", "MiniScala").
    Compiler("MiniScala", "C++", "C++").
    Compiler("C++", "x86", "x86").
    };
    let rules = #{
    Compiler(src1, dst1, dst2) :-
    Compiler(src1, dst1, lang1),
    Compiler(lang1, dst2, lang2),
    Interpreter(lang2).
    Compiler(src, dst, lang) :-
    Compiler(src, intermediate, lang),
    Compiler(intermediate, dst, lang),
    Interpreter(lang).
    };
    query facts, rules
    select (src, dst) from Compiler(src, _, dst) |> println

    View full-size slide

  19. 第一級 Datalog constraint
    19
    def main(): Unit \ IO =
    let facts = #{
    Interpreter("x86").
    Compiler("Scala", "x86", "MiniScala").
    Compiler("MiniScala", "C++", "C++").
    Compiler("C++", "x86", "x86").
    };
    let rules = #{
    Compiler(src1, dst1, dst2) :-
    Compiler(src1, dst1, lang1),
    Compiler(lang1, dst2, lang2),
    Interpreter(lang2).
    Compiler(src, dst, lang) :-
    Compiler(src, intermediate, lang),
    Compiler(intermediate, dst, lang),
    Interpreter(lang).
    };
    query facts, rules
    select (src, dst) from Compiler(src, _, dst) |> println
    Vector#{
    (C++, x86),
    (MiniScala, C++),
    (MiniScala, x86),
    (Scala, C++),
    (Scala, MiniScala),
    (Scala, x86)
    }

    View full-size slide

  20. 20
    Flixの思想がすごい

    View full-size slide

  21. Flixの思想(一部)
    21
    ● No NULL
    ● No reflection
    ● すべては式
    ● ヒューマンリーダブルなエラー
    ● 暗黙の強制(coercion)をしない
    ● 純粋コードと不純(impure)コードを分離
    ● コンパイル結果にWarningはない、エラーのみ
    ● 未使用の変数なし
    ● 不要な宣言は不要
    ● グローバル状態なし
    ● 構文の一貫性

    View full-size slide

  22. 22
    Flixのおもしろ機能

    View full-size slide

  23. bug?
    23
    match userAccount {
    case RegularAccount(v) =>
    doSomething(v)
    case SpecialAccount(v,tag) =>
    bug!("The value of inputValue cannot be empty. tag: " + a)
    }

    View full-size slide

  24. 24
    Flixをローカルで

    View full-size slide

  25. ローカルでflix
    25
    ~/tmp/flix via ☕ v17.0.9 took 7s
    ❯ java -jar ./flix.jar init
    Creating '/tmp/flix/src'.
    Creating '/tmp/flix/test'.
    Creating '/tmp/flix/flix.toml'.
    Creating '/tmp/flix/.gitignore'.
    Creating '/tmp/flix/LICENSE.md'.
    Creating '/tmp/flix/README.md'.
    Creating '/tmp/flix/src/Main.flix'.
    Creating '/tmp/flix/test/TestMain.flix'.
    用意するもの
    ● java 21
    ● flix.jar
    ○ https://github.com/flix/flix/releases
    ❯ java -jar ./flix.jar run
    Found `flix.toml'. Checking dependencies...
    Resolving Flix dependencies...
    Downloading Flix dependencies...
    Resolving Maven dependencies...
    Running Maven dependency resolver.
    Downloading external jar dependencies...
    Dependency resolution completed.
    Hello World!

    View full-size slide