Skip to content

Instantly share code, notes, and snippets.

@ryyppy
Last active June 3, 2019 18:33
Show Gist options
  • Save ryyppy/a63fd2ad65619bd87b064622e269da41 to your computer and use it in GitHub Desktop.
Save ryyppy/a63fd2ad65619bd87b064622e269da41 to your computer and use it in GitHub Desktop.
Reason Functor Example
/*
Let's Assume we want to have a Functor which creates a new Module from
a specific Component Model
The Functor recieves another Module named `Component`, which needs to satisfy certain constraints:
- Component requires an abstract type t (no matter what concrete type)
- It also needs to implement a `render` function which gets said type t and returns a `string`
Also, the newly created module will then contain a function `doSomething`, which will handle any
instance of `Component.t`. So our `Component` also will need a function to create an instance for that,
similarly what a `new MyConstructor()` would do in Object Oriented languages.
*/
module Make =
(
Component: {
type t;
let render: t => string;
}
) => {
let handleComponent = (something: Component.t): string => {
Js.log("Handled a component!");
Component.render(something);
};
};
/*
Here we are creating a module which is constraint to the rules of our Functor parameter `Component`.
- StringComponent defines a `type t`, this time we are concrete and define `t` as a `string`.
- It defines a `render(t): string` function to satisfy the Functor interface
- We also define a `make()` function, which will create us a new instance of `StringComponent.t`
This is a great way for encapsulation btw :-)
*/
module StringComponent = {
type t = string;
let make = () => {
"Hello World";
};
let render = (test: string): string => test;
};
/*
Now with everything in place, let's create a new module called `ComponentHandler) with our `Make` functor
by providing our StringComponent module as a parameter.
It looks like a function call, in fact that's all there is. It is a function which
creates a new module in build time!
*/
module ComponentHandler = Make(StringComponent);
/*
Time to play around with our newly created module!
When running our program, we create a new `StringComponent` instance of type `t`, which
secretly is a `string` type and pass it in the `handleComponent` function, which will
log `"Handled a component!"` and later own return the result of the `StringComponent.render`
function.
*/
StringComponent.make() |> ComponentHandler.handleComponent |> Js.log;
/*
It's very interesting to see how BuckleScript compiles Functors into JavaScript code.
`Make` is now factory function, which will return as a new module, which is represented
as a linked list / nested arrays, a similar way on how BS handles immutable records.
That's it. Have fun with functors, y'all!
Link to Reason Try example:
https://bit.ly/2wrU1e6
*/
*/
// Generated by BUCKLESCRIPT VERSION 5.0.4, PLEASE EDIT WITH CARE
'use strict';
var Curry = require("./stdlib/curry.js");
function Make(Component) {
var handleComponent = function (something) {
console.log("Handled a component!");
return Curry._1(Component[/* render */0], something);
};
return /* module */[/* handleComponent */handleComponent];
}
function make(param) {
return "Hello World";
}
function render(test) {
return test;
}
var StringComponent = /* module */[
/* make */make,
/* render */render
];
function handleComponent(something) {
console.log("Handled a component!");
return something;
}
var ComponentHandler = /* module */[/* handleComponent */handleComponent];
console.log(handleComponent("Hello World"));
exports.Make = Make;
exports.StringComponent = StringComponent;
exports.ComponentHandler = ComponentHandler;
/* Not a pure module */
"Handled a component!"
"Hello World"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment