The following code is written in javascript.
This question involves an attempt to dive into some category theory, maybe a haskeller or someone more familiar with the mathematical aspects of this question can help me out?
I'm trying to wrap my head around the idea that a functor is a mapping between categories that preserves structure. More specifically - according to my understanding - a functor in a programming language is an endofunctor. By this it is meant that functors in programming languages are morphisms that map types and functions to a sub-category within the broader category of types and functions as defined generally within the programming language.
According to my knowledge, functors (or endofunctors) must also adhere to certain laws that afford preservation of structure via the facilitation of composition and identity.
I'm finding it almost impossible to create a functor that I feel preserves structure, and adheres to the functor laws. This is compounded by the fact that I've only really programmed seriously in javascript, so type theory is something I've never really thought about (JS is untyped after all).
I made this simple example that lifts integers into a minimal context where mappings won't work on even numbers. In other words, you can map away with your composition but as soon as you hit an even number the show is over.
This looks sort of like a Maybe:
class noEvens {
constructor(x) {
this._val = x;
}
static of(x) {
return new noEvens(x);
}
isEven() {
return this._val % 2 === 0;
}
map(projF) {
return this.isEven() ? noEvens.of(null) : noEvens.of(projF(this._val));
}
}
But it's evident that this won't commute with compositions applied to integers in the normal JS category under certain situations. Consider a projection function that simply adds one to an integer.
If I lift an even number into this noEvens context and then add one it will give me a noEvens of null. But, if I first add one to an even number, then lift the result, it will result in a noEvens of an odd Number.
According to my understanding, both of these pathways should commute under functor laws. They clearly don't because the same mappings through each context don't result in the same resultant "noEvens.of(value)" after being lifted.
So I guess my question is, does this mean that this is not a functor? What is it about this type of situation (type-wise or whatever) that makes it act strangely?
I guess I'm just confused because it seems to be that all "noEvens" does is lift values into a new context (sub-category, whatever) where even numbers don't exist, but it is obvious that certain pathways won't commute.
I find the idea of "lifting a value" into a new mapping context quite intuitive, and it affords you a lot of opportunities to deal with conditions without having to implement tonnes of redundant code. But I don't want to do so in the false pretense that I'm adhering to some formalized system of "functor laws".
What is it about type-systems and functor laws that I'm missing in my analysis of this situation?
In addition to my comment...
You may notice that your almost-functor class also doesn't satisfy the identity law.
const id = x => x;
new noEvens(2).map(id) // != new noEvens(2)
My first thought was that the mistake was allowing a noEvens object containing an even number to be constructed in the first place. If the isEven check was instead done in the constructor, then you could satisfy the ID law.
class noEvens {
constructor(x) {
if (x % 2 === 0) {
this._val = null;
} else {
this._val = x;
}
}
static of(x) {
return new noEvens(x);
}
map(projF) {
if (this._val === null) {
return noEvens.of(null);
}
return noEvens.of(projF(this._val));
}
}
const id = x => x;
new noEvens(1).map(id)._val // ok: 1
new noEvens(2).map(id)._val // ok: null
But, it turns out this solution still doesn't satisfy the composition law.
const plusOne = x => x + 1;
// fmap f . fmap g == fmap (f . g) ?
new noEvens(1).map(plusOne).map(plusOne)._val // null
new noEvens(1).map(x => plusOne(plusOne(x)))._val // 3
So ultimately I think the fatal flaw is that noEvens limits what kind of data it can hold. As Bergi also said, "A usual functor would be capable of containing any arbitrary data." So noEvens, at its core, as a concept, cannot be a functor that obeys the composition law.
Related
1) Make an object and give it a simple method, e.g.,
let R = {
f: (x) => Math.sqrt(x)
}
2) Benchmark its performance, e.g., call f(x) a few million times
3) Now add a getter, e.g.,
let R = {
f: (x) => Math.sqrt(x),
get h() {return 0}
}
4) Benchmark f(x) again. Performance in chrome/node (V8 engine) drops significantly.
Any explanations for this weirdness?
Here's a codepen snippet for this: https://codepen.io/iiroullin/pen/XWbwoVQ
A work-around:
It seems that defining the getters/setters the old (ES5) way does not break V8 optimization. So, while they are ironing out all kinks in ES6, instead of (3) one can use this:
Object.defineProperty(R, 'h', {get: () => 0})
and such for all getters/setters.
Another fix:
Use classes, see the answer below
I've filed a bug for this: crbug.com/v8/10429
Can you describe in what scenario (other than microbenchmarks) this comes up, in particular compared to defining getters on classes? The following seems to be fast:
class C {
f(x) { return Math.sqrt(x); }
get h() { return 0; }
}
let R = new C();
for (...) {
R.f(...);
}
I suppose using classes for defining non-trivial objects is currently considered a "best practice"; if there are cases where classes don't fit the bill then that would be good to know so that engines can optimize for such patterns.
Side note #JaredSmith: The term "deopt" refers specifically to the situation of having to throw away optimized code when an assumption made at its compile time later on doesn't hold. That's not what's going on here.
I am new to JS and was learning functional programming and came across the term "referential transparency". Also, I found this statement "Referential transparency says it's safe to replace a pure function with its value". Does it mean that the use of RT makes it easy for JIT compiler to replace function with its return value as long as function gets hot? Is that true?
Here's an example:
This is a pure function: it will always return the same output for the same input
const even = x => x % 2 === 0;
And let's create isTenEven() which will check wether 10 is an even number or not:
const isTenEven = () => even(10);
Since we're guaranteed that even(10) === true will always be true then we can indeed replace a function call with a value:
const isTenEven = () => true;
And your program would still work.™
However you wouldn't be able to do so if even wasn't pure!
Here's a silly example: once per month 10 won't be an even number anymore:
const even = x => (new Date()).getDate() === 15 ? false : x % 2 === 0;
Perhaps your program is excepting isTenEven() to return either true or false, so forcing it to always assume that it will return true could lead to unexpected consequences.
Of course in this particular case I'm not sure what those consequences would be but you never know... which is exactly the point.
Yes, that is exactly an advantage of RT. The compiler can not only inline a function but replace its invocations with the corresponding return value, that is it can eliminate common sub-expressions and rewrite code according to specific rules like you can rewrite formulas in math. This way of reasoning about a program is called equational reasoning and is also very helpful for the programmer.
But RT allows other optimization techniques as well, like lazy evaluation. If you want to automatically delay the evaluation of an arbitrary expression up to the point where its result is actually needed, you need the guarantee that this expression yields the same result no matter when you actually evaluate it. RT gives this guarantee.
I'm building a WebGL game and I've come so far that I've started to investigate performance bottlenecks. I can see there are a lot of small dips in FPS when there are GC going on. Hence, I created a small memory pool handler. I still see a lot of GC after I've started to use it and I might suspect that I've got something wrong.
My memory pool code looks like this:
function Memory(Class) {
this.Class = Class;
this.pool = [];
Memory.prototype.size = function() {
return this.pool.length;
};
Memory.prototype.allocate = function() {
if (this.pool.length === 0) {
var x = new this.Class();
if(typeof(x) == "object") {
x.size = 0;
x.push = function(v) { this[this.size++] = v; };
x.pop = function() { return this[--this.size]; };
}
return x;
} else {
return this.pool.pop();
}
};
Memory.prototype.free = function(object) {
if(typeof(object) == "object") {
object.size = 0;
}
this.pool.push(object);
};
Memory.prototype.gc = function() {
this.pool = [];
};
}
I then use this class like this:
game.mInt = new Memory(Number);
game.mArray = new Memory(Array); // this will have a new push() and size property.
// Allocate an number
var x = game.mInt.allocate();
<do something with it, for loop etc>
// Free variable and push into mInt pool to be reused.
game.mInt.free(x);
My memory handling for an array is based on using myArray.size instead of length, which keeps track of the actual current array size in an overdimensioned array (that has been reused).
So to my actual question:
Using this approach to avoid GC and keep memory during play-time. Will my variables I declare with "var" inside functions still be GC even though they are returned as new Class() from my Memory function?
Example:
var x = game.mInt.allocate();
for(x = 0; x < 100; x++) {
...
}
x = game.mInt.free(x);
Will this still cause memory garbage collection of the "var" due to some memcopy behind the scenes? (which would make my memory handler useless)
Is my approach good/meaningful in my case with a game that I'm trying to get high FPS in?
So you let JS instantiate a new Object
var x = new this.Class();
then add anonymous methods to this object and therefore make it a one of a kind
x.push = function...
x.pop = function...
so that now every place you're using this object is harder to optimize by the JS engine, because they have now distinct interfaces/hidden classes (equal ain't identical)
Additionally, every place you use these objects, will have to implement additional typecasts, to convert the Number Object back into a primitive, and typecasts ain't for free either. Like, in every iteration of a loop? maybe even multiple times?
And all this overhead just to store a 64bit float?
game.mInt = new Memory(Number);
And since you cannot change the internal State and therefore the value of a Number object, these values are basically static, like their primitive counterpart.
TL;DR:
Don't pool native types, especially not primitives. These days, JS is pretty good at optimizing the code if it doesn't have to deal with surprizes. Surprizes like distinct objects with distinct interfaces that first have to be cast to a primitive value, before they can be used.
Array resizing ain't for free either. Although JS optimizes this and usually pre-allocates more memory than the Array may need, you may still hit that limit, and therefore enforce the engine to allocate new memory, move all the values to that new memory and free the old one.
I usually use Linked lists for pools.
Don't try to pool everything. Think about wich objects can really be reused, and wich you are bending to fit them into this narrative of "reusability".
I'd say: If you have to do as little as adding a single new property to an object (after it has been constructed), and therefore you'd need to delete this property for clean up, this object should not be pooled.
Hidden Classes: When talking about optimizations in JS you should know this topic at least at a very basic level
summary:
don't add new properties after an object has been constructed.
and to extend this first point, no deletes!
the order in wich you add properties matters
changing the value of a property (even its type) doesn't matter! Except when we talk about properties that contain functions (aka. methods). The optimizer may be a bit picky here, when we're talking about functions attached to objects, so avoid it.
And last but not least: Distinct between optimized and "dictionary" objects. First in your concepts, then in your code.
There's no benefit in trying to fit everything into a pattern with static interfaces (this is JS, not Java). But static types make the life easier for the optimizer. So compose the two.
I'm currently looking into Haskell and i'm fascinated by some of its features, for example the end-recursive functions using an accumulator.
Questions:
Is there a construct in javascript similar to that? Or does it even
make sense regarding efficiency since javascript is not as
functional as Haskell?
Is there any library like ramda, lodash, ... that supports this way
of programming
And if so, how would you write this for example in javascript:
power_acc :: Double -> Int -> Double
power_acc x y = power_acc_h x y 1
power_acc_h :: Double -> Int -> Double -> Double
power_acc_h x 0 acc = acc
power_acc_h x y acc = power_acc_h x (y-1) (acc*x)
Is there a construct in javascript similar to that?
Yes, you can literally translate this to JS:
function power_acc(x, y) { // Double -> Int -> Double
y = y>>>0; // cast to positive int (avoiding nontermination)
return power_acc_h(x, y, 1);
}
function power_acc_h(x, y, acc) { // Double -> Int -> Double -> Double
return y == 0
? acc
: power_acc_h(x, y-1, acc*x);
}
Or does it even make sense regarding efficiency since javascript is not as functional as Haskell?
With ES6, tail recursion is fully supported in JS, and you'll get the same efficiency as with a loop (and possibly even better than haskell, as you don't create lazy multiplications).
Is there any library like ramda, lodash, ... that supports this way of programming
No library required. Although I'm sure there are libs that simplify type checking or offer nicer notation for pattern matching.
How would you write this for example in javascript?
You'd use a while loop. All accumulation functions in haskell are written this way because they can be directly optimised into a loop, and that's the notation you should use for this construct in JS (as most programmers are familiar with it):
function power_acc(x, y) { // Double -> Int -> Double
y = y>>>0; // cast to positive int (avoiding nontermination)
var acc = 1;
while (y != 0) {
acc *= x;
y -= 1;
}
return acc;
}
Mutating local variables is no harm, your function is still pure. If you're looking for an even shorter notation, use a for loop.
This is a direct translation of the Haskell code in javascript :
function power_acc(x, y) {
return aux(x,y,1);
function aux(x, y, acc) {
if (y == 0)
return acc;
else
return aux(x, y-1, acc*x);
}
}
Is there any library like ramda, lodash, ... that supports this
way of programming?
You don't need lodash or ramda for that. You can do that with your
plain javascript just as I have shown above. Also note that lodash is
an utility library providing a consistent API for operating with
collections in a functional way. It won't help you in these scenarios.
In addition to Sibi's answer, I'd like to point out that javascript (at least nodejs) actually allocates stack space. It works fine and fast up to exponents of about 13,000, then you'll get RangeError: Maximum call stack size exceeded. To carry out this experimant you need to set the base to a number close to 1 (e.g. 1.0001) or you'll get Infinity.
Haskell does not suffer from this problem. An exponent 1000 times as big (namely 13,000,000) still does not cause any space problems, though it does take a few seconds to run. This is because the recursion is a tail call, and these run in constant space in haskell.
So in a way Sibi's answer mimicks haskells expressiveness, but it still exhibits a different runtime behavior. I don't think there is anythining you can do about this.
I agree with all the answers in that a library is neither required nor particularly helpful. (I'm one of the authors of Ramda, BTW.)
Bergi's translation into JS is fine, although I think it's more idiomatic at least in browser-side JS, to embed the helper function inside a local closure, something a little closer to Sibi's answer.
The reason for the performance problem that Martin Drautzburg points out is that, although tail-call optimization is specified, it's barely implemented anywhere. One exception is Babel's support for direct recursion, so a Babel-transpiled version should get the expected performance benefit.
So if you want to do this because of the elegance and because you believe TCO will come along soon enough, and if you're not worried about current possible performance problems, then these responses are useful, and I'll even throw one more ES6 technique into the mix:
// Double -> Int -> Double -> Double
function powerAcc(x, y, acc = 1) {
return y == 0 ? acc : powerAcc(x, y - 1, acc * x);
}
powerAcc(2, 5); //=> 32
Default function parameters help replace some simple forms of pattern matching in this language, which doesn't have true pattern matching. This still relies on TCO, but makes for somewhat cleaner code. It should also run performantly in Babel.
I am learning more advanced OO tactics for javascript coming from a C# background and am wondering about how to or if its even a good idea to implement prototype based validation. For instance when an object or function requires one of its parameters to satisfy a certain interface, you could check its interface like so,
var Interface = function Interface(i) {
var satisfied = function (t, i) {
for (var key in i) {
if (typeof t !== 'object') {
return false;
}
if (!(key in t && typeof t[key] == i[key])) {
return false;
}
}
return true;
}
this.satisfiedBy = function (t) { return satisfied(t, i); }
}
// the interface
var interfacePoint2D = new Interface({
x: 'number',
y: 'number'
});
// see if it satisfies
var satisfied = interfacePoint2D.satisfiedBy(someObject);
I came up with this strategy to validate an object by its interface only, ignoring the internal implementation of the object.
Alternatively say you are using prototype-based inheritance, should you or should not validate parameters based on their prototype functions? I understand that you'd use a prototype to implement default functionality whereas an interface doesn't specify any default functionality. Sometimes the object you are passing into a function might need certain default functionality in order for that function to work. Is it better to only validate against an interface, or should you ever validate against a prototype, and if so, whats the best way to do it?
EDIT -- I am providing some more context as to why I am asking this,
Say for instance in online game design (games written mostly in javascript). There are 2 main reasons I am interested in validation within this context,
1) Providing a strong public API for modding the game if desired
2) Preventing (or atleast discouraging greatly) potential cheaters
Which requires a balance between customizability and abuse. Specifically one situation would be in designing physics engine where objects in the game react to gravity. In a realistic system, users shouldn't be able to add objects to the system that do not react to gravity. The system has a function that expresses the global effect of gravity at any given point:
function getGravityAt(x, y) {
// return acceleration due to gravity at this point
}
And objects which react have a method that uses this to update their acceleration:
function update() {
this.acceleration = getGravity(this.position);
}
The minimum thing to do might be to ensure that any object added to the system has an 'update' method, but you still aren't ensuring that the update() method really is intended to react to gravity. If only objects that inherit from a prototypical update() method are allowed, then you know at least to some degree everything in the system reacts realistically.
This is a pretty subjective question. I'll pass on the question of whether it's a good idea to do interface-based validation in Javascript at all (there may well be good use-cases for it, but it's not a standard approach in the language). But I will say that it's probably not a good idea to validate objects based on their prototypes.
If you're validating by interface at all, you're probably working with objects created by other programmers. There are lots of ways to create objects - some rely on prototypes, some do not, and while they each have their proponents, they're all valid and likely approaches. For example:
var Point = function(x,y) {
return {
x: function() { return x },
y: function() { return y }
};
};
var p = new Point(1,1);
The object p conforms to an interface similar to yours above, except that x and y are functions. But there's no way to validate that p satisfies this interface by inspecting its constructor (which is Object()) or Point.prototype. All you can do is test that p has attributes called x and y and that they are of type "function" - what you're doing above.
You could potentially insist that p has a specific ancestor in its prototype chain, e.g. AbstractPoint, which would include the x and y functions - you can use instanceof to check this. But you can't be sure that x and y haven't been redefined in p:
var AbstractPoint = function() {};
AbstractPoint.prototype.x = function() {};
AbstractPoint.prototype.y = function() {};
var Point = function(x,y) {
var p = new AbstractPoint(x,y);
p.x = "foo";
return p;
}
var p = new Point(1,1);
p instanceof AbstractPoint; // true
p.x; // "foo"
And perhaps more importantly, this makes it harder to drop in custom objects that also satisfy the interface but don't inherit from your classes.
So I think what you're currently doing is probably the best you can hope for. In my experience, Javascript programmers are much more likely to use on-the-fly duck-typing than to try to mimic the capabilities of statically typed languages:
function doSomethingWithUntrustedPoint(point) {
if (!(point.x && point.y)) return false; // evasive action!
// etc.
}
I'll reiterate, type checking is not idiomatic javascript.
If you still want type checking, Google's closure compiler is the implementation I recommend. Type checking is done statically :) It has conventions for interfaces as well as (proto)type checking.