Gotta say, Sankel feels so much more restricted when he's not able to walk around the stage while presenting. He's really good at that pacing combined to the presentation based on having seen his other talks. I really enjoy his talks in general, he always has something important and useful to say. This was a weird and different way to visualize the talk but it was funny and effective. But I feel a bit discouraged how Sankel's small kids are much smarter on this than I. Recently I've been trying to expand my views by getting into functional programming and this just hits the spot perfectly. In my opinion monoids and functors and monads don't seem like complicated concepts per se, but there's all this vocabulary abstraction and mathematical "jargon" describing accurately what they do that it becomes just repeating unfamiliar words many times in a sentence, which completely obscures the ability to interpret the concept. Like when showing an example piece of code (preferrably without templating and being general because that messes people up even more) it looks like a familiar action that only had an unfamiliar name and list of rules/specifications you never thought about. Like I swear almost all of us have written a monoid, used a functor, perhaps monadic too. I swear nobody has ever read a formal mathematical description and applied it like that. You write the mathematical description after you've figured out a pattern of sorts and then everybody reads it and you show what you mean and then they start to understand and apply.
Came back at it after a year with some haskell attempts. With haskell syntax , I was sliding off of monad with some level of understanding of map and applicative functor. To me , monoid and applicative functor in C++ looked reasonably good . Though verbose in C++ but still grasping the concepts seemed easier . Here I'm only taking in the concepts whereas in the case of haskell the problem is both the syntax and concepts are new . So definately it was helpful for me.
The getStrings(.) example at 20:05 did not work for me this way. I had to replace the 'auto' keywords to exact type declarations then it worked. Like "std::function" for f1. Is there a way to still use those 'auto' keywords anyway? It'd be nicer and more compact and flexible.
I wonder if FP is promoted by those who are predominantly programmers by occupation or whether it's mathematicians being bored. Using Haskell is torturous and it seems like I'm fighting the language more often than addressing the programming issue at hand. Moreover, something like std::vector entertained in this talk is cache-unfriendly because Ts will be interspersed by the flags that indicate whether the std::optional contains a value. I fear that following FP principles incurs runtime costs, where instances are coupled with extraneous state for tab-keeping (more specifically, it's encouraged to keep tab-keeping local to each individual instance), which calls for extraneous state checks and branching.
FP in general does not map great to HW and this is, I believe, one of the reasons it is not the predominate paradigm. Still the value in it is undeniable and we should take all the good we can.
At 19:20 when you talk about how std::function is a functor, i'm confused about the type of the first parameter. Shouldnt the type of the first parameter be a std::function with one parameter (a std::function) that returns another std::function, rather than just a std::function that accepts the return type of the second parameter?
So, P is fixed (think of it like literally 'int') and then: type function from P (int) to T is a functor with parameter T because if I have a function `a` (name like in example) of this type, and can provide function from T to U and get function from ... I think this is pointless now, anyone gotta se it for himself. This talk is quite nice to intuitively understand functors: ua-cam.com/video/e6tWJD5q8uw/v-deo.html (skip to 12:52 for Functors, also there are notations at 5:55, though it's just pseudo-haskell, and it doesn't matter much anyway to understand the concept - there are pictures!). It has a bit different style to this great video I am commenting on rn. More pictures and thinking about functional stuff in a slightly different way. It is nice to see things from a bit different point of view too, so I recommend it for people that would like to deepen their understanding. So, to say that type F is a functor with param T is to say that it has function map (or fmap) with the following signature (in haskell notation with cpp's template sprinkled in): (T -> U) -> (F -> F). For example whe treating vector as functor, provided a function from int to float (as parameter) we get (return) function "map" from vector to vector. In this video however, we see slight change in currying: we write map as a function with signature ((T -> U), F) -> F. This (using same example situation of vector, int and float) reads: given a function from int to float and a vector of int as parameters, return vector of float. Signature in C++ is F(std::function, F) - if the functor F is now std::function (P is, as mentioned, some fixed type), than this function has signature std::function(std::function, std::function) which is exactly that of the function presented (19:25). We don't consider more abstract map function that given a function T -> U returns a function (F -> F) but rather want to provide function T -> U and the vector right away to get the other vector immediately. What I think absolutely got me for a moment is this change from thinking (T -> U) -> (F T -> F U) (very haskellian and what I got out of the talk I mentioned) to thinking in terms of (T -> U, F T) -> F U - very confusing when F is also a function type and everything is mixed together.
So, P is fixed (think of it like literally 'int') and then: type function from P (int) to T is a functor with parameter T because if I have a function `a` (name like in example) of this type, and can provide function from T to U and get function from ... I think this is getting pointless, everyone gotta see it for himself. This talk is quite nice to intuitively understand functors: ua-cam.com/video/e6tWJD5q8uw/v-deo.html (skip to 12:52 for Functors, also there are notations at 5:55, though it's all just pseudo-haskell, and it doesn't matter much anyway to understand the concept - there are pictures!). It has a bit different style to this great video I am commenting on rn. More pictures and thinking about functional stuff in a slightly different way. It is nice to see things from a bit different point of view too, so I recommend it for people that would like to deepen their understanding. There, the definition is: to say that type F is a functor with param T is to say that it has function map with the following signature (in haskell notation with cpp's template sprinkled in): (T -> U) -> (F -> F). For example whe treating vector as functor, provided a function from int to float (as parameter) we get (return) function "map" from vector to vector. In this video however, we see slight change in currying: we write map as a function with signature ((T -> U), F) -> F. This (using same example situation of vector, int and float) reads: given a function from int to float and a vector of int as parameters, return vector of float. Signature in C++ is F(std::function, F) - if for the functor F we substitute now std::function (P is, as mentioned, some fixed type), than this function has signature std::function(std::function, std::function) which is exactly that of the function presented (19:25). In summary, we don't consider more abstract map function that given a function T -> U returns a function (F -> F) that can later be used to map any vector, but rather provide both: the mapping function T -> U and the mapped vector right away to get the other resulting vector immediately. So this is, I think, what absolutely got me - this change from thinking (T -> U) -> (F T -> F U) (very haskellian and what I got out of the talk I mentioned) to thinking in terms of (T -> U, F T) -> F U - very confusing when F is also a function type, everything is mixed together, and I don't know which type is the parameter.
I am not an expert, but I think you just pass them through functions. Kind of like append("a", append("b", append("c", ""))) - where is this stored? (Basically, on the stack as function arguments, if you get right down to it). In general, functional programming doesn't appear to store anything until you get the final results.
Functional programming in general is really awkward - it has its use in specific applications, but for general programs it is very verbose and hard to reason about.
@@ABaumstumpf in haskell, fp looks less intimidating, and you could make a generalization really simple. It just that Cpp define fp in a really verbose way, since it wasn't build specifically for fp
Great talk! My token of appreciation is focusing on the one thing where you're wrong (EDIT: in part). 😉 Fat interfaces are bad. Please, do not write fat interfaces… fat interfaces are, by definition, interfaces with low cohesion, which is bad. Fat interface = god object (or rather "an object with a god complex"…) The solution is to a) segregate interfaces and b) use free functions (e.g. in C++) where possible. Then you - and you may laugh now - educate your users accordingly. Ok, what if you tried but your users can't or don't want to be educated? Then you can still use e.g. the Facade design pattern to separate the user interface from the implementation interfaces! In C++ e.g., you can similarly use the NVI (non-virtual interface) pattern where the (here: fat) public interface consists of non-virtual methods that use a restricted set of protected (or private) virtual methods. In short, there's no real reason to punish implementers by forcing a fat interface on them.
Really clever way to handle a remote presentation
This guy presents on whole new level
Excellent. Sound, presentation, delivery. Very impressive and even entertaining... talking about monads... would never expected. Thank you.
This was so awesome I want all category theory to be introduced like this.
Thank you so much David, CppCon and the crew.
Best talk of CppCon 2020!
With this presentation style you'll go far
This video is great. It has category theory and kids answering questions about category theory.
Haha, awesome use of your family! Wonder if they'd be able to sat there through the whole talk. The talk is good too :)
This guy absolutely killed it
Best talk this year by far!
I'm glad to see ideas from cat. theory getting more widespread :) A well prepared presentation, thank you!
Those kids are serious about their computer science knowledge! :)
Gotta say, Sankel feels so much more restricted when he's not able to walk around the stage while presenting. He's really good at that pacing combined to the presentation based on having seen his other talks. I really enjoy his talks in general, he always has something important and useful to say. This was a weird and different way to visualize the talk but it was funny and effective. But I feel a bit discouraged how Sankel's small kids are much smarter on this than I.
Recently I've been trying to expand my views by getting into functional programming and this just hits the spot perfectly.
In my opinion monoids and functors and monads don't seem like complicated concepts per se, but there's all this vocabulary abstraction and mathematical "jargon" describing accurately what they do that it becomes just repeating unfamiliar words many times in a sentence, which completely obscures the ability to interpret the concept. Like when showing an example piece of code (preferrably without templating and being general because that messes people up even more) it looks like a familiar action that only had an unfamiliar name and list of rules/specifications you never thought about. Like I swear almost all of us have written a monoid, used a functor, perhaps monadic too. I swear nobody has ever read a formal mathematical description and applied it like that. You write the mathematical description after you've figured out a pattern of sorts and then everybody reads it and you show what you mean and then they start to understand and apply.
Such a good idea for talks like this!
Came back at it after a year with some haskell attempts. With haskell syntax , I was sliding off of monad with some level of understanding of map and applicative functor. To me , monoid and applicative functor in C++ looked reasonably good . Though verbose in C++ but still grasping the concepts seemed easier . Here I'm only taking in the concepts whereas in the case of haskell the problem is both the syntax and concepts are new . So definately it was helpful for me.
This is so amazing lol the peanut gallery is adorable!
Seems most fun and prepared talk :)
It's a mix of too simple and too complicated. Too easy and it's obvious. Too complicated and it feels messy and unclear.
Smart cookies in the audience :)
This is soooo good! Love those kids
The parser from example is effectful. It should take string as an input, or better - const char*.
This is simply amazing. Love it!
So valuable video. Thank you.
this is like abstract algebra's I used to study these in pure mathematics fun
The getStrings(.) example at 20:05 did not work for me this way. I had to replace the 'auto' keywords to exact type declarations then it worked. Like "std::function" for f1. Is there a way to still use those 'auto' keywords anyway? It'd be nicer and more compact and flexible.
I wonder if FP is promoted by those who are predominantly programmers by occupation or whether it's mathematicians being bored. Using Haskell is torturous and it seems like I'm fighting the language more often than addressing the programming issue at hand. Moreover, something like std::vector entertained in this talk is cache-unfriendly because Ts will be interspersed by the flags that indicate whether the std::optional contains a value. I fear that following FP principles incurs runtime costs, where instances are coupled with extraneous state for tab-keeping (more specifically, it's encouraged to keep tab-keeping local to each individual instance), which calls for extraneous state checks and branching.
FP in general does not map great to HW and this is, I believe, one of the reasons it is not the predominate paradigm. Still the value in it is undeniable and we should take all the good we can.
Very very good presenter!
Thank you very much for this comment.
How do those kids understand all of this?
At 19:20 when you talk about how std::function is a functor, i'm confused about the type of the first parameter. Shouldnt the type of the first parameter be a std::function with one parameter (a std::function) that returns another std::function, rather than just a std::function that accepts the return type of the second parameter?
nevermind, I just realized that an element of a vector is analogous to a return type of a std::function
So, P is fixed (think of it like literally 'int') and then: type function from P (int) to T is a functor with parameter T because if I have a function `a` (name like in example) of this type, and can provide function from T to U and get function from ... I think this is pointless now, anyone gotta se it for himself.
This talk is quite nice to intuitively understand functors: ua-cam.com/video/e6tWJD5q8uw/v-deo.html (skip to 12:52 for Functors, also there are notations at 5:55, though it's just pseudo-haskell, and it doesn't matter much anyway to understand the concept - there are pictures!). It has a bit different style to this great video I am commenting on rn. More pictures and thinking about functional stuff in a slightly different way. It is nice to see things from a bit different point of view too, so I recommend it for people that would like to deepen their understanding.
So, to say that type F is a functor with param T is to say that it has function map (or fmap) with the following signature (in haskell notation with cpp's template sprinkled in):
(T -> U) -> (F -> F). For example whe treating vector as functor, provided a function from int to float (as parameter) we get (return) function "map" from vector to vector.
In this video however, we see slight change in currying: we write map as a function with signature
((T -> U), F) -> F. This (using same example situation of vector, int and float) reads: given a function from int to float and a vector of int as parameters, return vector of float. Signature in C++ is F(std::function, F) - if the functor F is now std::function (P is, as mentioned, some fixed type), than this function has signature
std::function(std::function, std::function) which is exactly that of the function presented (19:25).
We don't consider more abstract map function that given a function T -> U returns a function (F -> F) but rather want to provide function T -> U and the vector right away to get the other vector immediately.
What I think absolutely got me for a moment is this change from thinking (T -> U) -> (F T -> F U) (very haskellian and what I got out of the talk I mentioned) to thinking in terms of (T -> U, F T) -> F U - very confusing when F is also a function type and everything is mixed together.
So, P is fixed (think of it like literally 'int') and then: type function from P (int) to T is a functor with parameter T because if I have a function `a` (name like in example) of this type, and can provide function from T to U and get function from ... I think this is getting pointless, everyone gotta see it for himself.
This talk is quite nice to intuitively understand functors: ua-cam.com/video/e6tWJD5q8uw/v-deo.html (skip to 12:52 for Functors, also there are notations at 5:55, though it's all just pseudo-haskell, and it doesn't matter much anyway to understand the concept - there are pictures!). It has a bit different style to this great video I am commenting on rn. More pictures and thinking about functional stuff in a slightly different way. It is nice to see things from a bit different point of view too, so I recommend it for people that would like to deepen their understanding.
There, the definition is: to say that type F is a functor with param T is to say that it has function map with the following signature (in haskell notation with cpp's template sprinkled in):
(T -> U) -> (F -> F). For example whe treating vector as functor, provided a function from int to float (as parameter) we get (return) function "map" from vector to vector.
In this video however, we see slight change in currying: we write map as a function with signature
((T -> U), F) -> F. This (using same example situation of vector, int and float) reads: given a function from int to float and a vector of int as parameters, return vector of float. Signature in C++ is F(std::function, F) - if for the functor F we substitute now std::function (P is, as mentioned, some fixed type), than this function has signature
std::function(std::function, std::function) which is exactly that of the function presented (19:25).
In summary, we don't consider more abstract map function that given a function T -> U returns a function (F -> F) that can later be used to map any vector, but rather provide both: the mapping function T -> U and the mapped vector right away to get the other resulting vector immediately.
So this is, I think, what absolutely got me - this change from thinking (T -> U) -> (F T -> F U) (very haskellian and what I got out of the talk I mentioned) to thinking in terms of (T -> U, F T) -> F U - very confusing when F is also a function type, everything is mixed together, and I don't know which type is the parameter.
32:42 so how does one pass the list of digits to convert them into a number when the characters are not even stored anywhere?
I am not an expert, but I think you just pass them through functions. Kind of like append("a", append("b", append("c", ""))) - where is this stored? (Basically, on the stack as function arguments, if you get right down to it). In general, functional programming doesn't appear to store anything until you get the final results.
Those kids are adorable!
Functional programming in C++ looks really awkward
Functional programming in general is really awkward - it has its use in specific applications, but for general programs it is very verbose and hard to reason about.
@@ABaumstumpf in haskell, fp looks less intimidating, and you could make a generalization really simple. It just that Cpp define fp in a really verbose way, since it wasn't build specifically for fp
lol love the kids
Great talk! My token of appreciation is focusing on the one thing where you're wrong (EDIT: in part). 😉
Fat interfaces are bad. Please, do not write fat interfaces… fat interfaces are, by definition, interfaces with low cohesion, which is bad. Fat interface = god object (or rather "an object with a god complex"…)
The solution is to a) segregate interfaces and b) use free functions (e.g. in C++) where possible. Then you - and you may laugh now - educate your users accordingly.
Ok, what if you tried but your users can't or don't want to be educated? Then you can still use e.g. the Facade design pattern to separate the user interface from the implementation interfaces!
In C++ e.g., you can similarly use the NVI (non-virtual interface) pattern where the (here: fat) public interface consists of non-virtual methods that use a restricted set of protected (or private) virtual methods.
In short, there's no real reason to punish implementers by forcing a fat interface on them.
Slow clap. Legit eli5