Skip to main content

Article: Defunctionalisation

· 2 min read
Manas Jayanth
Managing Partner at Dining Philosophers, LLP.
Srijan Paul
CS and Math enthusiast

injuly proposed a talk on defunctionalisation in compilers - this rehashes his post defunctionalisation, but in OCaml. We recommend you read his post first and switch to this article to compare the OCaml implementation.

Higher order functions

let rec fold f acc = function
| [] -> acc
| x::xs -> f x (fold f acc xs)

let sum xs = fold (+) 0 xs
let add n xs = fold (fun x acc -> (x + n)::acc) [] xs

fold is the higher order function because it takes another function (possibly higher order), f.

The GADT representation of functions like function arguments

type ('env, 'params, 'return) arrow =
| FnPlus : int * int -> (unit, (int * int), int) arrow
| FnPlusCons : int * (int * int list) -> (int, (int * int list), int list) arrow

('env, 'params, 'return) arrow encodes functions that can be passed around as arguments to other functions.

fold (+) 0 xs could be expressed as fold (FnPlus (0, xs)) fold (fun x acc -> (x + n :: acc) could be expressed as fold (FnPlusCons (n, (x, acc)) where n is the free variable.

These representations can be evaluated with apply

let apply : type env params return.  (env, params, return) arrow -> return = fun arrow ->
match arrow with
| FnPlus (a, b) -> a + b
| FnPlusCons (n, (x, xs)) -> (n + x)::xs

Example output

utop[41]> apply (FnPlus (1, 2));;
- : int = 3
utop[42]> apply (FnPlusCons (10, (1, [2;3])));;
- : int args = [11; 2; 3]
utop[43]>

When is the next meetup?

Checkout Upcoming Meetups

Stay in touch with us


Twitter: https://x.com/ReasonBangalore

Discord: https://discord.com/invite/Ytr36fRC4C

Meetup 20: Parser Combinators in OCaml

· One min read
Manas Jayanth
Managing Partner at Dining Philosophers, LLP.

injuly live coded mini-angstrom drawing inspiration from both Angstrom and the Graham Hutton paper.

The agenda was

  1. Short intro to parser combinators and Monads.
  2. Re-implement angstrom from scratch – a popular parser combinator library.
  3. Go through angstrom's source, and compare differences from our implementation.
  4. Cover some popular Haskell parsing libraries (parsec, megaparsec, etc.)

After the meetup, @theteachr even raised a pull request to implement (WIP) a BenCode parser.

When is the next meetup?

Checkout Upcoming Meetups

Stay in touch with us


Twitter: https://x.com/ReasonBangalore

Discord: https://discord.com/invite/Ytr36fRC4C

Meetup 19: Bootstrapping OCaml projects without package manager

· One min read
Manas Jayanth
Managing Partner at Dining Philosophers, LLP.

We discussed what's needed by the package manager to make it's project bootstrap without itself.

Notably,

  1. Trace the complete transitive closure of the dependencies - so package manager must build such dependencies in isolation to catching missing dependencies.

  2. Trace the complete build environment variables

  3. A parser for .install files that ocaml build systems create to install built artifacts

A PoC with esy package manager can be found here

Checkout Upcoming Meetups

Stay in touch with us


Twitter: https://x.com/ReasonBangalore

Discord: https://discord.com/invite/Ytr36fRC4C

Meetup 7: Building a Monopoly Deal Clone

· One min read
Nick
YouTuber
Manas Jayanth
Managing Partner at Dining Philosophers, LLP.

We discussed encoding the rules of the popular card game Monopoly Deal in OCaml's type system with @theteachr.

Highlights

  • Briefly discussed the gameplay.
  • Incrementally built modules around relevant data structures.
  • Explored whether constructors could clash.
    • Initially, the general understanding was that it wouldn't work. Either the compilation would fail, or one of them would not be usable. But found out that it will just need some extra [type] hinting on some occasions to get the correct type.
  • Focussed on the principal of making invalid states impossible to represent.
  • Created an incomplete game state just to start getting some feedback.

You can find the code on Github


Once again, the discussion after lasted an hour. Srijan Paul shared how dithering in images can improve GIF color depths.

Next Meetup

We will be continue last week's Canvas tutorial, lead by AC Sreedhar in a meetup. More details here

Stay in touch with us


Twitter: https://twitter.com/ReasonBangalore

Discord: https://discord.com/invite/RamP7SCKcU

Meetup 16: Tree sitter for Reason and OCaml

· One min read
Manas Jayanth
Managing Partner at Dining Philosophers, LLP.

@Korven led the session explaining Tree sitter, how to write a grammar, debug tree-sitter-ocaml issies on helix. We even explored extending the Reason tree sitter grammar with a class definition. Here's the WIP snippet.

diff --git a/grammar.js b/grammar.js
index 9f587a4..7bc6748 100644
--- a/grammar.js
+++ b/grammar.js
@@ -56,6 +56,7 @@ module.exports = grammar(require("./embedded/ocaml"), {
$.expression_statement,
$.open_statement,
$.module_definition,
+ $.class_definition,
$.mutable_record_update,
),

@@ -71,6 +72,22 @@ module.exports = grammar(require("./embedded/ocaml"), {
$._semicolon,
),

+ class_definition: ($) =>
+ seq(
+ "class",
+ // TODO optional($._attribute),
+ $.class_binding,
+ $._semicolon,
+ ),
+
+ class_binding: ($) =>
+ seq(
+ field("name", choice($._class_name, alias("_", $.class_name))),
+ // optional($._module_typed),
+ seq("=", field("body", $._module_expression)),
+ // repeat($.item_attribute),
+ ),
+
module_binding: ($) =>
seq(
field("name", choice($._module_name, alias("_", $.module_name))),

Next Meetup

Checkout Upcoming Meetups

Stay in touch with us


Twitter: https://x.com/ReasonBangalore

Discord: https://discord.com/invite/Ytr36fRC4C

Meetup 15: Monopoly in OCaml continued - part 4

· One min read
Manas Jayanth
Managing Partner at Dining Philosophers, LLP.

@theteachr showed us the new game loop using Seq.of_dispenser making the game loop look like this.

let () =
let game =
[ "ocaml"; "reason"; "melange"; "dune" ]
|> List.map Player.make
|> Game.start
in
read_command
|> Seq.of_dispenser
|> Seq.filter_map Command.parse
|> Seq.scan Command.exec game
|> Seq.take_while Game.is_not_over
|> Seq.iter Tui.draw

Highlights

We discussed,

  1. Possible use of GADTs for handling propert card transformations. You can find the git branch here
  2. use of Seq.unfold. Code
  3. Modular card transformations. Code

Next Meetup

Checkout Upcoming Meetups

Stay in touch with us


Twitter: https://x.com/ReasonBangalore

Discord: https://discord.com/invite/Ytr36fRC4C

Meetup 14: Monopoly in OCaml continued - part 3

· One min read
Manas Jayanth
Managing Partner at Dining Philosophers, LLP.

@theteachr showed us the minimal TUI he wrote for the game and explained the game loop.

Highlights

  1. We discussed how game loop had to be kept a pure function of game state and player moves
  2. Possible improvements with a Seq modules

Next Meetup

Checkout Upcoming Meetups

Stay in touch with us


Twitter: https://x.com/ReasonBangalore

Discord: https://discord.com/invite/Ytr36fRC4C

Meetup 13: Final: Dream webserver tutorial

· One min read
Manas Jayanth
Managing Partner at Dining Philosophers, LLP.

We discussed the last pieces essential for a web framework - routers. Last session, we had written a router that worked only in the client. We ported for server side rendering.

Highlights

  1. We discussed CSS rendering that occurs on the server on different routes
  2. We discussed the possibility of writing static site generators with the knowledge so far

Next Meetup

Checkout Upcoming Meetups

Stay in touch with us


Twitter: https://x.com/ReasonBangalore

Discord: https://discord.com/invite/Ytr36fRC4C