+Andy Brice you've just invented the most succinct explanation of it I've ever heard. The only thing I would add is that it returns a functor of the same TYPE.
funfunfunction Ahh, I guess so that you can chain a bunch of functions together in whatever order, secure in the knowledge that they'll all be operating on the same type of object.
Same type? You had an array of dragons and then an array of string and last an array of int. They are not the same type. The structure are isomorph, that is, it looks like the original in structure. Where each element is transfered to another type by the function sent to map. Ok, in Java script I belive you are allowed to store mixed types in arrays. And yes, @Andy made a very short and good explanation of a Functor.
***** well, actually it isn't. The content type is part of the type. And yes, I know some languages are not that particular about type checking. That they treat Arrays as a generic datatype, where you can store objects of any type. Same with lists. Doesn't change that an array of int and array of char are different types though.
You got it really wrong in the previous video haha, even though it help a lot to understand the reason for functors to exist. Thanks for the rectification, its a while I am trying to understand functors and monads and your videos are a big help. Keep on the good work!
Thanks for sharing. I like your videos. It makes my day happier. =) One small suggestion, maybe, you can accompany the video with downloadable notes that is easy to understand for anyone (children etc.), i.e: PDF format. For example, in this video, I learned that functors have three characteristics; 1. Transformation of content 2. Maintain the structure of content 3. Returns a new functor Something like that. Again, thank you very much. I learned a lot from you. =)
In short, a functor is an assignment of, for any type T, a type FT, and for any transformation f : T ---> U a transformation Ff : FT ---> FU subject to certain niceness conditions. Write FT as T[] and Ff as map(f) and you're in business.
Functors are 1-morphism of Objects(A,B...) eg. A -> B in 2-category where objects are categories (1-cat). How come morphism become an object (that implements map), shouldn't the functor be the function that's passed into the map?
The simplest definition of a functor is an object which acts as a container for a value, which then allows to you APPLY one or more functions to that value, and returns a new functor containing the transformed value. It's not about having a map method per se, it's just the idea of wrapping a simple value in an object that then allows you to "decorate" it with functionality to be evaluated either eagerly, or lazily.
I think functors must also preserve composition so map (f . g) == map f . map g , which i think means ---> [1,2,3].map(x => double(x)).map(x => square(x)) == [1,2,3].map(x => square(double(x))).
What about strings in Haskell where they are defined as a list of characters? You can very well map a function that does, let's say return True if the character is 'a' and False else. In this sense the structure is conserved because you give it a list of Chars and returns a list of any other things (in the example booleans). So doing: let as = map isA "abc" is the same as doing: let as = map isA ['a','b','c'] and as will have the value of [True, False,False] ______________________________ Code example mapFunction :: (a -> b) -> [a] -> [b] mapFunction _ [] = [] mapFunction f (x:xs) = f x : mapFunction f xs isA :: Char -> Bool isA 'a' = True isA _ = False ghci: mapFunction isA "abc" [True, False, False] ______________________________________ So if I am getting this right, strings in Haskell (since they are just a type synonym for [Char]) are functors. Am I right? Could you please help me shine some light on this issue? Btw. Very nice channel and video. I am subscribing. :)
So, the Functor is just an object, that has a "map" function (where "map function" is a function, that returns new object of the same type and shape)? If that is correct, then the only one required operation of functor is a "map" operation, right?
Oh if you come in the c++ land. Functor is basically a class with bunch of operator overloading which makes it seem like a function that can handle multiple arguments.
The Kate Beaton pony shirt again. Yay! Also, although there was lots of interesting content regarding functors, the strange dancing Santa hat alone made this video worth watching
Can't make the 'bluebird' example work as listed. Get "Unhandled rejection TypeError:expecting an array or an iterable object but got [object Null]...." (node v10.4.1, bluebird 3.5.2). Adding a reject method to promise only delayed the error! ?....but learnt something in trying so thanks!
I understood where you come from. Personnally I will still call the map function a Functor rather than the "high order function". I certainly hope that the functor denomination will stick.
Doesn't filter function transform the content, Maintain structure and can be chained? So does that mean an object containing a filters are functors as well?
+Nipuna Gunathillake Map and filter reminds about each other, but they are actually very different. map and filter seem more similar than they are. Filter changes the array structure, not the contents, while map does the opposite. This might be hard to grasp if you are thinking of an array as bunch of items - instead, in your mind, try to separate the concepts of the items and the structure that is the array. Let me explain: Imagine array as a container that looks like this: img1.etsystatic.com/000/0/6248605/il_340x270.329955061.jpg The balls are the array items, and the steel frame that the balls lie in is the array. I know that it's easy to think of array as just a set of items because you can add and remove items from an array in JavaScript, but instead try to separate the items and the structure in your mind. Think of an array not as a set of items, but as a tray that contains the items. The tray is a functor, so it provides a slot on the side, labeled map, into which you can insert a transformation function. If you do, a new tray of the *exact same size* is created, but with all items transformed through the transformation function. The structure, the tray, has NOT been changed, but all items have been changed. There is also a slot for filter, but filter does almost the exact opposite, it passes every item through the filter function, and if the filter function returns true, that items is deemed to make the cut to be in the new tray, which is created. The individual items are NOT transformed (some are thrown away though), but the tray has been changed into a smaller tray.
Got it! Thanks for the awesome explanation. Filters change the array(container) not just it's container. It's a bit difficult getting my head around all the functional programming concepts but your videos have definitely made it far more fun! Thanks for all the videos.
Yo mpj (or anyone really). Just a question: if i chain maps (sometimes ppl do for the sake of composing), will it traverse the collection multiple times? Like: square_list.map(square => square.base).map(size => Math.pow(size, 2)) (and later i could perform a reduce or whatever for exemple). I mean, it probably should but compilers have cool tricks and all... so i'd sleep better at night if it wouldnt (in the case that the execution of those statements wouldnt produce colateral effects).
+47beethoven it will. There is no way for the compiler to optimize this for you in JavaScript, but you can compose the two functions into one before passing it to map and thereby have only a single map. See compose function in the rambda library, for example.
+ladrillopendejo Glad you asked. It's Pony, one of the characters that the amazing Kate Beaton draws. It's in her store here: www.topatoco.com/merchant.mvc?Screen=CTGY&Store_Code=TO&Category_Code=BEAT She is a comic book author that I'm a very big fan of. Check her out: www.harkavagrant.com/index.php?id=131
Is that a painting of Yoshi in a go cart from Mario Kart in the background? if so, I love it and love your videos, very interesting and relevant subjects, even when they are wrong!
+funfunfunction, I don't think you need to do any transformation to be qualified as a functor. Functor - as mentioned in this video - is a sort of a Container object which has map (for chaining) and flatMap (to unfold the final value when chaining is finished) methods on it. That's it. Check out my own quick functor: const Container = x => ({ map: f => Containter( f ( x ) ), flatMap: f => f( x ) }); But as far as I understand it 'map' method is there just to run a function in the given context. That's it!!! For example, Container( 7 ).map(num => num). I don't modify anything here, I just return the same thing back into my Container. But it's still a functor, because my Container is a functor no matter what function I choose to run in the given context (i.e. whatever function I choose to map).
Hello everyone, I've been having some trouble with some of the code in the video for some time let Promise = require('bluebird') const whenPkmnIsLoaded = new Promise((resolve, reject) => { setTimeout(() => resolve({ { name: 'Pikachu', type: 'electric' } }, 2000) }); const thing = whenPkmnIsLoaded .map(pkmn => pkmn.name) .then(name => console.log(name)) // Also, I installed bluebird like so: // npm install bluebird --save Where am I screwing up? Thanks
Hello! I think his example was wrong too, because he gave timeout value to the resolve, instead of setTimeout, also you cant put an object inside of an object like that, that will cause a javascript error, so i've corrected your code and this should work nicely: let Promise = require('bluebird') const whenPkmnIsLoaded = new Promise((resolve, reject) => { setTimeout(() => resolve([ { name: 'Pikachu', type: 'electric' } ]), 2000) }) const thing = whenPkmnIsLoaded .map(pkmn => pkmn.name) .then(names => console.log(names))
It should be like this, since bluebird's map method expects an iterable. setTimeout(() => resolve([{ name: "Fluffykins"}]), 2000); from what I understood it works just like Array.prototype.map, except that it waits until the promise resolves and you can use it directly So basically this whenDragonLoaded .map(dragon => dragon.name) .then(console.log); Is equivalent to this whenDragonLoaded .then(dragons => dragons.map(dragon => dragon.name)) .then(console.log);
I really enjoyed the video (as well as any previous one) but I am paranoid (JSX thaught me that). You have Syntax Error in second example, resolve function missing closing ). You also returning there {{name: 'Fluffykins', health: 70}} which is another syntax error and then call on this value .map() which would throw one more error. As a punishment I sentence you to do this great videos until the universe ends! :)
+p4chw1n I accept your punishment! :) Great catch, btw. I actually knew about the first one but ignored it in the edit in favor to get the episode out on time, but the second one completely passed me by.
One insignificant hint from me. I like your videos, but think to use another sounds from this YT defaults. I think, that I hear them in almost every YT video. :-D Great video. You are making good work! :-)
4 years later, it's not just you. Map is not a function declared on Promise prototype object. As you can see on the video, at the very top of the example is using Bluebird (external library) Promise which has a map defined.
+Chris Kwong in a real life situation, you'd chain array.filter().map() if the array was very large and the map was very expensive. But it would have to be very large for that to matter - a modern JS engine on a smartphone is very fast - I just tried and my phone maps over 22 million items per second. I'm not a fan of discussing performance on a line by line level because I don't think that is how performance works (see my elaboration on the topic here ruclips.net/video/PhUb7y9WZGs/видео.html).
I enjoy ur videos ... Just one thing that I would like to tell u is please correct that example where u r using promise from bluebird ... One should pass an array of dragon in to resolve function and not single dragon object ...othetwise ur map will fail ... Try it :)
That was really interesting. So what is a Monad? Because I thought that a Monad was like a composable thing that takes in a function, but then I realized that the thing I thought was a Monad was basically the same as what you are describing.
+John Michael Lafayette You will be able to watch that in the upcoming video about monads, and the undoubtedly subsequent video about how I was wrong about monads. :)
+mpjme Oh. So the Monad isn't the thing that is doing the propagating. It's the thing that is being propagated (the specific behavior that is being propagated). Monad encapsulates behavior.
+John Michael Lafayette here is the great mostly adequate guide to functionnal programing from Dr. Boolean, which explains very well what it is => drboolean.gitbooks.io/mostly-adequate-guide/content/ch9.html Basically it's just a wrapper like a functor, with a "join" method on it.
If `String` + `map` is not a functor because the `map` only works for string-returning transformations, then JS's Typed Arrays must not be functors either: let x = new UInt8Array([1,2,3,4]); x.map(x => false) // [0, 0, 0, 0] I'm not saying that this distinction is wrong, but that the distinction has to be implementation-specific or the definition is useless. If Typed Arrays are functors (and they must be, to my thinking) then `String+map` must be as well. Just a thought.
+Andrew Adamson its not string specifically, it must maintain form. The .map of a Widget must return another Widget, or it is not a functor. If UInt8Array.map would have returned say, a normal array, instead of a UInt8Array then it would violate the functor contact. This is bad because then chainability has been compromised and we would not be able to do: myByteArray.map(someTransformationFunc).buffer()
Apart from the great content let me give a shout out to the awesome t-shirts! :-P Also, do a video on prototypes! It might not be functional programming in itself but it's a concept that even the best books (like Learning Ecmascript 6) get confused.
I think in the parts of this video where you pop up in the back of the room you're out of focus a bit. Other than that great video! Keep up the good work!
It's pretty simple. A functor is the following: - a type constructor F, which takes one type and returns another (that is, for a type a we have another type F a); - for which we also need some function fmap :: (a -> b) -> (F a -> F b) for all types a and b. That's all it is. But we do require the following two axioms: - if id is the identity map id :: a -> a on the type a (that is, id x = x) then fmap id is the identity map on F a - if f :: a -> b and g :: b -> c, as usual we can compose them to g . f :: a -> c. Then we require that fmap (g . f) = (fmap g) . (fmap f). I come at this more from mathematics, so I think having the axioms is important. But programmers are likely going to be more interested in just _implementing_ functors, so defining the type constructor F and the fmap. It turns out that if you can define a type constructor F and implement the fmap as above, then you only need to check the first axiom to get the second, seemingly more complicated one, for free (I could be wrong about that, but I think this is a so-called "theorem for free". It comes from the restriction of having to define fmap parametrically, so strictly speaking I'm restricting to certain kinds of languages here, like Haskell). The list functor is an example. Given a type a, we can define the type [] a, more commonly written [a], which is the type of lists of elements in a. For example, x = [1,15,-2,3] is an element of [Int]. If you have a map f :: a -> b, then you get in an obvious way a map which takes lists of a's and returns lists of b's: just apply f to each element in the list. For example, if f :: Int -> Int is the times two map, then fmap f x = [2,30,-4,6]. Now applying the identity map to each element of a list gives back the same list, so fmap id is the identity. And if you have two composable functions, f and g, then mapping each element of a list by g after f is the same thing as first applying f to each element of the list, and then applying g to each element of that list. That is, fmap (g . f) = (fmap g) . (fmap f). So the functor axioms are satisfied. Whenever you have a type constructor as above with some parametric fmap implemented, the chances are that it will be a functor.
That is who the channel is targeted to. Or rather, programmers that are about 1 year into their first job - that is who I imagine when I make the videos.
6:58 According to Brian Lonsdorf (Dr Boolean)'s book, you're making a number one rookie mistake here. Should be: then(console.log) not: then(name => console.log(name)) wrapping stuff like this is redundant.
The two are not equivalent because .log is property on the console object and depending on the implementation of console in the runtime environment, I've had what you're suggesting sometimes break, which is why I've adopted the habit to just always wrap the console.log calls in a wrapper.
I've started learning Haskell recently. And perhaps the reason for this confusion in the community is that in pure functional programming, the boundaries between objects and functions get a bit blurry. They seem to be both referred to more vaguely as a "computational context" which I think is something slightly esoteric stemming from category theory.
I bet that pooch runs away next time you whip out your wood. (cause you really screw the pooch!) BUT mistakes often provide more opportunity for learning than slick perfection. I got a LOT out of this.
4:20 The `dragon => dragon.name` is the functor. Functors are basically stateful functions which maintain the state themselves. stackoverflow.com/questions/356950/c-functors-and-their-uses
I now have no idea what a functor is... I wanted to simplify it to a function that operates on a collection and takes another function as a argument. But now I have to clean my brain off the floor because it exploded.
hi, love your videos, but i won't watch this one or the previous one. As a beginner, listening to wrong information, and then listening to a correction, and then attempting to make sense of it all, will just CONFUSE me. Omg, plz don't tell me i "need" to watch a video that has wrong info in it. i hope you will make one Functor video which is all correct, which isn't littered with "the wrong thing i said in the last video was ..." (GAH, I'M PLUGGING MY EARS!), and is designed to be a complete Intro to Functors which stands on it's own. Hope you understand!
hey Johny. Happy that you are learning programming! I understand that you have a need for cohesion and predictability at this point, where everything seems confusing, that must be very stressful. However, other people, me included, also exist and have needs and limitations. :) I did these two videos a weekend on my spare time about five years ago, and while I am pretty proud of this series it's also the very first videos I ever made on programming, and there were some mistakes made. The mistakes are done and there is nothing to be done about it, and mistakes will always be done - I think correcting it was the right way to go. An advice I can give as a programmer is to accept that the world is an inelegant messy place and that it is in fact our job as engineers build systems that give the illusion of elegance to other people. Fundamentally the world is a mess and it's important to remember that a CPU is just a stone that we have managed to somehow flatten an put lightning inside of it.
The definition is still not correct. A functor is any type (NOT object) with a map method. It must obey the law that preserves function composition while mapping. map() doesn't return anther functor but transforming elements in the same functor.
+CtrlAlt Debug that article is talking about functor in the sense of function object in C++. That is not at all the same thing as what we are talking about here, but unfortunately they are using the same name.
So… In short, a functor is a collection that can be passed a function and apply it nondestructively to all of its elements, returning another functor?
+Andy Brice you've just invented the most succinct explanation of it I've ever heard. The only thing I would add is that it returns a functor of the same TYPE.
funfunfunction Ahh, I guess so that you can chain a bunch of functions together in whatever order, secure in the knowledge that they'll all be operating on the same type of object.
+Andy Brice precisely.
Same type?
You had an array of dragons and then an array of string and last an array of int. They are not the same type.
The structure are isomorph, that is, it looks like the original in structure. Where each element is transfered to another type by the function sent to map.
Ok, in Java script I belive you are allowed to store mixed types in arrays.
And yes, @Andy made a very short and good explanation of a Functor.
***** well, actually it isn't. The content type is part of the type. And yes, I know some languages are not that particular about type checking. That they treat Arrays as a generic datatype, where you can store objects of any type. Same with lists.
Doesn't change that an array of int and array of char are different types though.
You got it really wrong in the previous video haha, even though it help a lot to understand the reason for functors to exist. Thanks for the rectification, its a while I am trying to understand functors and monads and your videos are a big help. Keep on the good work!
Admitting you were wrong... you'd make a terrible politician. :P
Hahahaha!
wish more politicians would be like that :(
@@Yetipfote let's vote for those ones then ;)
On a more positive note, admitting you're wrong enables you to learn and makes you more trustworthy to others trying to learn!
Thanks for sharing. I like your videos. It makes my day happier. =)
One small suggestion, maybe, you can accompany the video with downloadable notes that is easy to understand for anyone (children etc.), i.e: PDF format. For example, in this video, I learned that functors have three characteristics;
1. Transformation of content
2. Maintain the structure of content
3. Returns a new functor
Something like that. Again, thank you very much. I learned a lot from you. =)
In short, a functor is an assignment of, for any type T, a type FT, and for any transformation f : T ---> U a transformation Ff : FT ---> FU subject to certain niceness conditions. Write FT as T[] and Ff as map(f) and you're in business.
You are simply the best I have watched in a while!! You made me get more serious on functional!!!
Excellent vid! Hilarious as usual and very interesting as well! Function composition FTW! Also very brave to shout to the world that you were wrong :)
I absolutely love this guy
Functors are 1-morphism of Objects(A,B...) eg. A -> B in 2-category where objects are categories (1-cat). How come morphism become an object (that implements map), shouldn't the functor be the function that's passed into the map?
The simplest definition of a functor is an object which acts as a container for a value, which then allows to you APPLY one or more functions to that value, and returns a new functor containing the transformed value.
It's not about having a map method per se, it's just the idea of wrapping a simple value in an object that then allows you to "decorate" it with functionality to be evaluated either eagerly, or lazily.
I think functors must also preserve composition so map (f . g) == map f . map g , which i think means ---> [1,2,3].map(x => double(x)).map(x => square(x)) == [1,2,3].map(x => square(double(x))).
The last two videos were the best in a while.
There is so much confusion around functors and monads and your forthrightness is appreciated.
Awesome! Thanks for the clarification. Way to handle being "wrong" like a G! You're a developer's developer.
Thank you very much for fixing the mistakes. I respect that.
What about strings in Haskell where they are defined as a list of characters?
You can very well map a function that does, let's say return True if the character is 'a' and False else. In this sense the structure is conserved because you give it a list of Chars and returns a list of any other things (in the example booleans).
So doing:
let as = map isA "abc"
is the same as doing:
let as = map isA ['a','b','c']
and as will have the value of
[True, False,False]
______________________________
Code example
mapFunction :: (a -> b) -> [a] -> [b]
mapFunction _ [] = []
mapFunction f (x:xs) = f x : mapFunction f xs
isA :: Char -> Bool
isA 'a' = True
isA _ = False
ghci: mapFunction isA "abc"
[True, False, False]
______________________________________
So if I am getting this right, strings in Haskell (since they are just a type synonym for [Char]) are functors.
Am I right? Could you please help me shine some light on this issue?
Btw. Very nice channel and video. I am subscribing. :)
That was great. I eeally enjoyed your explanation of what a functor is and why your prior video was wrong.
I am glad to be getting to things I dont understand. seriously, thank you!
So, the Functor is just an object, that has a "map" function (where "map function" is a function, that returns new object of the same type and shape)? If that is correct, then the only one required operation of functor is a "map" operation, right?
Oh if you come in the c++ land. Functor is basically a class with bunch of operator overloading which makes it seem like a function that can handle multiple arguments.
any value on which "map" can be implemented is a functor?
The Kate Beaton pony shirt again. Yay!
Also, although there was lots of interesting content regarding functors, the strange dancing Santa hat alone made this video worth watching
Can't make the 'bluebird' example work as listed. Get "Unhandled rejection TypeError:expecting an array or an iterable object but got [object Null]...." (node v10.4.1, bluebird 3.5.2). Adding a reject method to promise only delayed the error! ?....but learnt something in trying so thanks!
The hat!!! Thanks for another fantastic video.
If it maintains structure doesn't it follow that it returns a functor? What's the difference between 2 & 3?
doesnt the map function take three parameters? the last one being the array itself... or does that not count as a 3rd parameter for some reason?
in angular 2, is this also considered a functor:
this.http.get('....json?auth='+ token)
.map(...)
"Secret club became so secret that it has no members"
:D
I understood where you come from. Personnally I will still call the map function a Functor rather than the "high order function". I certainly hope that the functor denomination will stick.
Am I the only one that thinks the host should experiment with wigs?
Possibly. LOL
@3:25 Dat Face hahaha. You are awesome man! Keep it up!
Doesn't filter function transform the content, Maintain structure and can be chained?
So does that mean an object containing a filters are functors as well?
+Nipuna Gunathillake Map and filter reminds about each other, but they are actually very different. map and filter seem more similar than they are. Filter changes the array structure, not the contents, while map does the opposite. This might be hard to grasp if you are thinking of an array as bunch of items - instead, in your mind, try to separate the concepts of the items and the structure that is the array. Let me explain:
Imagine array as a container that looks like this:
img1.etsystatic.com/000/0/6248605/il_340x270.329955061.jpg
The balls are the array items, and the steel frame that the balls lie in is the array. I know that it's easy to think of array as just a set of items because you can add and remove items from an array in JavaScript, but instead try to separate the items and the structure in your mind. Think of an array not as a set of items, but as a tray that contains the items.
The tray is a functor, so it provides a slot on the side, labeled map, into which you can insert a transformation function. If you do, a new tray of the *exact same size* is created, but with all items transformed through the transformation function. The structure, the tray, has NOT been changed, but all items have been changed.
There is also a slot for filter, but filter does almost the exact opposite, it passes every item through the filter function, and if the filter function returns true, that items is deemed to make the cut to be in the new tray, which is created. The individual items are NOT transformed (some are thrown away though), but the tray has been changed into a smaller tray.
Got it! Thanks for the awesome explanation. Filters change the array(container) not just it's container.
It's a bit difficult getting my head around all the functional programming concepts but your videos have definitely made it far more fun! Thanks for all the videos.
what are the things that make up your media station ( mic, camera, software for editing )? please respond
Standard RUclips stuff all of it. Midrange DSLR, cheap soft lights, blue yeti, FCPX
Yo mpj (or anyone really). Just a question: if i chain maps (sometimes ppl do for the sake of composing), will it traverse the collection multiple times? Like: square_list.map(square => square.base).map(size => Math.pow(size, 2)) (and later i could perform a reduce or whatever for exemple). I mean, it probably should but compilers have cool tricks and all... so i'd sleep better at night if it wouldnt (in the case that the execution of those statements wouldnt produce colateral effects).
+47beethoven it will. There is no way for the compiler to optimize this for you in JavaScript, but you can compose the two functions into one before passing it to map and thereby have only a single map. See compose function in the rambda library, for example.
Cool, i will check it out. Nice that you answer questions on year's old videos.
Hi Matt, I was just wondering but did you get that horse shirt online? If so can you tell us all where you got it!!!
+ladrillopendejo Glad you asked. It's Pony, one of the characters that the amazing Kate Beaton draws. It's in her store here: www.topatoco.com/merchant.mvc?Screen=CTGY&Store_Code=TO&Category_Code=BEAT She is a comic book author that I'm a very big fan of. Check her out: www.harkavagrant.com/index.php?id=131
Is that a painting of Yoshi in a go cart from Mario Kart in the background? if so, I love it and love your videos, very interesting and relevant subjects, even when they are wrong!
It's actually a yoshi made with fuse beads glued to an vintage cross-stitch. It's made by @pappasparlor on Instagram, they are amazing.
It is amazing! just started following him on Insta, and thanks for all the videos, been binge watching them
+funfunfunction,
I don't think you need to do any transformation to be qualified as a functor. Functor - as mentioned in this video - is a sort of a Container object which has map (for chaining) and flatMap (to unfold the final value when chaining is finished) methods on it. That's it. Check out my own quick functor:
const Container = x => ({
map: f => Containter( f ( x ) ),
flatMap: f => f( x )
});
But as far as I understand it 'map' method is there just to run a function in the given context. That's it!!! For example, Container( 7 ).map(num => num). I don't modify anything here, I just return the same thing back into my Container. But it's still a functor, because my Container is a functor no matter what function I choose to run in the given context (i.e. whatever function I choose to map).
Hello everyone, I've been having some trouble with some of the code in the video for some time
let Promise = require('bluebird')
const whenPkmnIsLoaded = new Promise((resolve, reject) => {
setTimeout(() => resolve({
{ name: 'Pikachu', type: 'electric' }
}, 2000)
});
const thing =
whenPkmnIsLoaded
.map(pkmn => pkmn.name)
.then(name => console.log(name))
// Also, I installed bluebird like so:
// npm install bluebird --save
Where am I screwing up?
Thanks
Hello!
I think his example was wrong too, because he gave timeout value to the resolve, instead of setTimeout, also you cant put an object inside of an object like that, that will cause a javascript error, so i've corrected your code and this should work nicely:
let Promise = require('bluebird')
const whenPkmnIsLoaded = new Promise((resolve, reject) => {
setTimeout(() => resolve([
{ name: 'Pikachu', type: 'electric' }
]), 2000)
})
const thing =
whenPkmnIsLoaded
.map(pkmn => pkmn.name)
.then(names => console.log(names))
Goofy8907 I think it may because he’s using ES6
It should be like this, since bluebird's map method expects an iterable.
setTimeout(() => resolve([{ name: "Fluffykins"}]), 2000);
from what I understood it works just like Array.prototype.map, except that it waits until the promise resolves and you can use it directly
So basically this
whenDragonLoaded
.map(dragon => dragon.name)
.then(console.log);
Is equivalent to this
whenDragonLoaded
.then(dragons => dragons.map(dragon => dragon.name))
.then(console.log);
This was a great video! Thank you
I love your humor !!:D
I like watching those videos on 1.5x.
I really enjoyed the video (as well as any previous one) but I am paranoid (JSX thaught me that). You have Syntax Error in second example, resolve function missing closing ). You also returning there {{name: 'Fluffykins', health: 70}} which is another syntax error and then call on this value .map() which would throw one more error.
As a punishment I sentence you to do this great videos until the universe ends! :)
+p4chw1n I accept your punishment! :) Great catch, btw. I actually knew about the first one but ignored it in the edit in favor to get the episode out on time, but the second one completely passed me by.
One insignificant hint from me. I like your videos, but think to use another sounds from this YT defaults. I think, that I hear them in almost every YT video. :-D
Great video. You are making good work! :-)
+Bartłomiej Smykla Not from the RUclips defaults. :)
+mpjme Oh, then apologise. But still I hear that so many times a day, so I just thought it's YT defaults. :-D
Thanks for the series! It's awesome!
Fun and educational, what else you need.
MPJ, can you please bring back the "fluhluhluhluh!" at 2:57? It's the best.
EDIT:
Actually, "Blehelele!" at 3:28 is best.
Great channel. I love it.
Is it me, or the code for the second example does not work?
Just you buddy!
4 years later, it's not just you. Map is not a function declared on Promise prototype object. As you can see on the video, at the very top of the example is using Bluebird (external library) Promise which has a map defined.
Wouldn't chaining on map be non-optimal since it will loop over the array again? (Imagine a very BIG array)
+Chris Kwong in a real life situation, you'd chain array.filter().map() if the array was very large and the map was very expensive. But it would have to be very large for that to matter - a modern JS engine on a smartphone is very fast - I just tried and my phone maps over 22 million items per second. I'm not a fan of discussing performance on a line by line level because I don't think that is how performance works (see my elaboration on the topic here ruclips.net/video/PhUb7y9WZGs/видео.html).
I enjoy ur videos ... Just one thing that I would like to tell u is please correct that example where u r using promise from bluebird ... One should pass an array of dragon in to resolve function and not single dragon object ...othetwise ur map will fail ... Try it :)
That was really interesting. So what is a Monad? Because I thought that a Monad was like a composable thing that takes in a function, but then I realized that the thing I thought was a Monad was basically the same as what you are describing.
+John Michael Lafayette You will be able to watch that in the upcoming video about monads, and the undoubtedly subsequent video about how I was wrong about monads. :)
+mpjme A monad is Functor with some specific behaviour, by the way. That is why I'm explaining functors at all, it's a stepping stone to monad.
+mpjme Oh. So the Monad isn't the thing that is doing the propagating. It's the thing that is being propagated (the specific behavior that is being propagated). Monad encapsulates behavior.
+mpjme Too soon.
+John Michael Lafayette here is the great mostly adequate guide to functionnal programing from Dr. Boolean, which explains very well what it is => drboolean.gitbooks.io/mostly-adequate-guide/content/ch9.html
Basically it's just a wrapper like a functor, with a "join" method on it.
Great video as always
If `String` + `map` is not a functor because the `map` only works for string-returning transformations, then JS's Typed Arrays must not be functors either:
let x = new UInt8Array([1,2,3,4]);
x.map(x => false) // [0, 0, 0, 0]
I'm not saying that this distinction is wrong, but that the distinction has to be implementation-specific or the definition is useless. If Typed Arrays are functors (and they must be, to my thinking) then `String+map` must be as well. Just a thought.
+Andrew Adamson its not string specifically, it must maintain form. The .map of a Widget must return another Widget, or it is not a functor. If UInt8Array.map would have returned say, a normal array, instead of a UInt8Array then it would violate the functor contact. This is bad because then chainability has been compromised and we would not be able to do:
myByteArray.map(someTransformationFunc).buffer()
hahahah that sigh, on watching Beard... @3:32
where do you get all these cats shirts..gear
I'm no zoologist, but I'm pretty sure those are horses.
hah yeh im not sure where the cat came from
Laws are must have when writing Your own Functor. Braking laws means composition will be broken.
Great episode. Thanks 😜
Your videos rock sir! Thank you
It makes sense that you used to work in the theatre industry.
Apart from the great content let me give a shout out to the awesome t-shirts! :-P Also, do a video on prototypes! It might not be functional programming in itself but it's a concept that even the best books (like Learning Ecmascript 6) get confused.
+Anders Rapp I have made a video about that already. ;)
+funfunfunction I'll go check that out then. Thanks and keep up the good work! :)
I think in the parts of this video where you pop up in the back of the room you're out of focus a bit.
Other than that great video! Keep up the good work!
It's pretty simple. A functor is the following:
- a type constructor F, which takes one type and returns another (that is, for a type a we have another type F a);
- for which we also need some function fmap :: (a -> b) -> (F a -> F b) for all types a and b.
That's all it is. But we do require the following two axioms:
- if id is the identity map id :: a -> a on the type a (that is, id x = x) then fmap id is the identity map on F a
- if f :: a -> b and g :: b -> c, as usual we can compose them to g . f :: a -> c. Then we require that
fmap (g . f) = (fmap g) . (fmap f).
I come at this more from mathematics, so I think having the axioms is important. But programmers are likely going to be more interested in just _implementing_ functors, so defining the type constructor F and the fmap. It turns out that if you can define a type constructor F and implement the fmap as above, then you only need to check the first axiom to get the second, seemingly more complicated one, for free (I could be wrong about that, but I think this is a so-called "theorem for free". It comes from the restriction of having to define fmap parametrically, so strictly speaking I'm restricting to certain kinds of languages here, like Haskell).
The list functor is an example. Given a type a, we can define the type [] a, more commonly written [a], which is the type of lists of elements in a. For example, x = [1,15,-2,3] is an element of [Int]. If you have a map f :: a -> b, then you get in an obvious way a map which takes lists of a's and returns lists of b's: just apply f to each element in the list. For example, if f :: Int -> Int is the times two map, then fmap f x = [2,30,-4,6].
Now applying the identity map to each element of a list gives back the same list, so fmap id is the identity. And if you have two composable functions, f and g, then mapping each element of a list by g after f is the same thing as first applying f to each element of the list, and then applying g to each element of that list. That is, fmap (g . f) = (fmap g) . (fmap f). So the functor axioms are satisfied.
Whenever you have a type constructor as above with some parametric fmap implemented, the chances are that it will be a functor.
So if I understood it right, you Christmas hat is a Monad.
+Carlos Baraza Well, it certainly encapsulates some messed up behavior.
could a POJO be a functor?
+minispecs123 It could if it implemented map.
I adore your videos
"if I had a bigger beard... " LOL
I LOVE this!
+1 for correcting yourself.
I GET IT NOW!! thank you
I like your clips very much and the way how you marry fun and function ;) ever thought about teaching yound "want-to-be"-programmers?!
That is who the channel is targeted to. Or rather, programmers that are about 1 year into their first job - that is who I imagine when I make the videos.
I tried to scroll down to see the rest of the t-shirt :)
that drag at 5:41 tho
6:58
According to Brian Lonsdorf (Dr Boolean)'s book, you're making a number one rookie mistake here. Should be:
then(console.log)
not:
then(name => console.log(name))
wrapping stuff like this is redundant.
The two are not equivalent because .log is property on the console object and depending on the implementation of console in the runtime environment, I've had what you're suggesting sometimes break, which is why I've adopted the habit to just always wrap the console.log calls in a wrapper.
I like how you say functor!!!
Actually, callback to Array.prototype.map() takes three arguments. *Flies away to do homework*
I've started learning Haskell recently. And perhaps the reason for this confusion in the community is that in pure functional programming, the boundaries between objects and functions get a bit blurry. They seem to be both referred to more vaguely as a "computational context" which I think is something slightly esoteric stemming from category theory.
I bet that pooch runs away next time you whip out your wood. (cause you really screw the pooch!)
BUT mistakes often provide more opportunity for learning than slick perfection. I got a LOT out of this.
Fantastic! :)
Dr. Boolean is just amazing, great recommendation, follow him!
Hahaha, you're crazy!
Awesome video!
Thanks!
4:20 The `dragon => dragon.name` is the functor. Functors are basically stateful functions which maintain the state themselves.
stackoverflow.com/questions/356950/c-functors-and-their-uses
I approve the dragon objects!
I now have no idea what a functor is... I wanted to simplify it to a function that operates on a collection and takes another function as a argument. But now I have to clean my brain off the floor because it exploded.
You might want to look at my functor/monad talk if you're still confused:
ruclips.net/video/2jp8N6Ha7tY/видео.html
Haha love ya brother!
I laughed so hard in the hat part that I cried xDD
I need to sleep on this
Idk. Functors are objects that have methods? Sounds a lot like OOP for me not FP where state and operations are separate.
I need that shirt! xD
HAHA I LOVE THIS GUY!
hi, love your videos, but i won't watch this one or the previous one. As a beginner, listening to wrong information, and then listening to a correction, and then attempting to make sense of it all, will just CONFUSE me. Omg, plz don't tell me i "need" to watch a video that has wrong info in it.
i hope you will make one Functor video which is all correct, which isn't littered with "the wrong thing i said in the last video was ..." (GAH, I'M PLUGGING MY EARS!), and is designed to be a complete Intro to Functors which stands on it's own.
Hope you understand!
hey Johny. Happy that you are learning programming! I understand that you have a need for cohesion and predictability at this point, where everything seems confusing, that must be very stressful. However, other people, me included, also exist and have needs and limitations. :) I did these two videos a weekend on my spare time about five years ago, and while I am pretty proud of this series it's also the very first videos I ever made on programming, and there were some mistakes made. The mistakes are done and there is nothing to be done about it, and mistakes will always be done - I think correcting it was the right way to go.
An advice I can give as a programmer is to accept that the world is an inelegant messy place and that it is in fact our job as engineers build systems that give the illusion of elegance to other people. Fundamentally the world is a mess and it's important to remember that a CPU is just a stone that we have managed to somehow flatten an put lightning inside of it.
To the monad-mobile!
Fun Fun Functors.
Fun fun functor
magic
It's a generic type not an object.
That hat though
Ok lets skip this video
The definition is still not correct. A functor is any type (NOT object) with a map method. It must obey the law that preserves function composition while mapping.
map() doesn't return anther functor but transforming elements in the same functor.
Still wrong. A Functor is an object that acts as a function. web.stanford.edu/class/cs106l/course-reader/Ch13_Functors.pdf
+CtrlAlt Debug that article is talking about functor in the sense of function object in C++. That is not at all the same thing as what we are talking about here, but unfortunately they are using the same name.