Last active
August 29, 2015 14:25
-
-
Save svanellewee/8d443a64551e2675a2fd to your computer and use it in GitHub Desktop.
Functors just take stuff out of "type-boxes" apply a function and put them back into the same "type-boxes".
This file contains hidden or 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
/* | |
* | |
* Functor : | |
* fmap : (a -> b) -> fa -> fb | |
* | |
*/ | |
function array_fmap1(fn, typeA) { | |
var typeB = [] | |
typeA.forEach(function(aVal) { | |
typeB.push(fn(aVal)) | |
}); | |
return typeB; | |
} | |
function plus1(x) { | |
return x+1; | |
} | |
function times10(x) { | |
return x*10; | |
} | |
function compose(f,g){ | |
return function(val) { | |
return f(g(val)); | |
}; | |
} | |
var val1 = array_fmap1(times10, array_fmap1(plus1, [1,2,3,40])); | |
console.log(val1); | |
var val2 = array_fmap1(compose(times10, plus1), [1,2,3,40]); | |
console.log(val2); | |
function string_fmap(fn, string) { | |
var retstring = ""; | |
Array.prototype.forEach.call(string,function(e) { | |
retstring += fn(e); | |
}); | |
return retstring; | |
} | |
function makeUpperCase(e) { | |
return e.toUpperCase(); | |
} | |
var val3 = string_fmap(makeUpperCase,'hello world '); | |
console.log(val3); | |
function Maybe(val) { | |
if ( !(this instanceof Maybe) ){ | |
return new Maybe(val); | |
} | |
this.val = val; | |
} | |
Maybe.prototype.fmap = function(fn) { | |
if (this.val === null) { | |
return new Maybe(null); | |
} | |
if (typeof this.val === "undefined") { | |
return new Maybe(null) | |
} | |
return new Maybe(fn(this.val)) | |
} | |
var m12 = Maybe(12); | |
var mnull = Maybe(null); | |
console.log(m12.fmap(plus1).fmap(plus1)); | |
console.log(mnull.fmap(plus1).fmap(plus1)); | |
function Either(valleft, valright){ | |
if (!(this instanceof Either)) { | |
return new Either(valleft, valright); | |
} | |
this.valleft = valleft; | |
this.valright = valright; | |
} | |
Either.prototype.fmap = function(fn) { | |
if ((this.valright !== null) && | |
(typeof this.valright !== 'undefined')) { | |
return new Either(this.valleft, fn(this.valright)); | |
} | |
if ((this.valleft !== null) && | |
(typeof this.valleft !== 'undefined')) { | |
return new Either(fn(this.valleft), this.valright); | |
} | |
return new Either(this.valleft, this.valright); | |
} | |
var res4 = new Either(12,null) | |
.fmap(plus1) | |
.fmap(times10); | |
console.log(res4); | |
function wasNullResult(x) { | |
return null; | |
} | |
console.log(new Either(12,2) | |
.fmap(plus1) | |
.fmap(wasNullResult) | |
.fmap(plus1)); | |
var addressBla ; | |
//var addressBla = "Something"; | |
var either = new Either( { address : "Bla"}, addressBla) | |
.fmap(updateField); | |
function updateField(x) { | |
console.log("GETTING ",x); | |
return x; | |
} | |
console.log(addressBla, either); | |
function Reeks() { // Afrikaans for "array"... see what I did there? | |
this.value = Array.prototype.slice.call(arguments, 0); | |
} | |
Reeks.prototype.fmap = function(fn) { | |
var vals = []; | |
this.value.forEach(function(elem) { | |
//console.log(".",elem); | |
vals.push(fn(elem)); | |
}); | |
var result = (function apply_args_to_constructor() { | |
function NewReeks(values) { | |
return Reeks.apply(this, values); | |
} | |
NewReeks.prototype = Reeks.prototype; | |
return new NewReeks(vals); | |
})(); | |
return result; | |
} | |
var reeks = new Reeks(1,2,3,4); | |
var result12 = reeks.fmap(plus1); | |
console.log(reeks); | |
console.log(result12); | |
//--- monads ? | |
var just12 = new Maybe(12); | |
// a -> M a | |
function half(x) { | |
if ( x % 2 === 0 ){ | |
return new Maybe (x / 2); // Just (x/2) | |
} | |
return new Maybe (null); // Nothing | |
} | |
Maybe.prototype.Bind = function(fn) { | |
return this.val ? fn(this.val) : Maybe(); | |
} | |
// class Monad m where | |
// (>>=) :: m a -> (a -> m b) -> m b | |
// instance Monad Maybe where | |
// Nothing >>= func = Nothing | |
// Just val >>= func = func val | |
var m3 = new Maybe(3); | |
console.log(m3.Bind(half)); | |
var m4 = new Maybe(4); | |
console.log(m4.Bind(half)); | |
var mnull2 = new Maybe(null); | |
console.log(mnull2.Bind(half)); | |
console.log((new Maybe(20)).Bind(half)); | |
console.log((new Maybe(20)).Bind(half).Bind(half)); | |
//console.log((new Maybe(20)).Bind(half)); | |
// What about promises.. functors ? | |
// then === fmap ? | |
//------- | |
// | |
// a -> b | |
function length(x) { | |
return new Maybe(x.length); | |
} | |
function log(x){ | |
console.log("..!!",x); | |
return new Maybe(x); | |
} | |
var result = (new Maybe("hello")) | |
.Bind(length) | |
.Bind(log); | |
var result2 = (new Maybe(null)) | |
.Bind(length) | |
.Bind(log); | |
var result = (new Maybe("hello world")) | |
.fmap(length) | |
.fmap(log); | |
var result2 = (new Maybe(null)) | |
.fmap(length) | |
.fmap(log); | |
console.log("..."); | |
// string -> Maybe string | |
function getName(name) { | |
var lookup = { "stephan" : 12, | |
"rose" : 100, | |
"sammy" : 50, | |
"bella" : 2 | |
}; | |
return new Maybe(lookup[name]); | |
} | |
function Sub10(x) { | |
return new Maybe(x-10); | |
} | |
function FilterLessThan10(x) { | |
var retval = x > 10 ? x : null; | |
return new Maybe(retval); | |
} | |
function Mult2(x) { | |
return new Maybe(x*2); | |
} | |
[ "stephan" , "boris", "bella" ].forEach(function(name) { | |
var maybeval = getName(name); | |
maybeval | |
.Bind(Mult2) | |
.Bind(Sub10) | |
.Bind(FilterLessThan10) | |
.Bind(function(y) { | |
console.log("val * 2 - 10 = ", y); | |
return new Maybe(y); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment