Last active
June 3, 2019 18:33
-
-
Save ryyppy/a63fd2ad65619bd87b064622e269da41 to your computer and use it in GitHub Desktop.
Reason Functor Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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 | |
*/ | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"Handled a component!" | |
"Hello World" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment