Scott Wlaschin is the "Uncle Bob" we truly deserved. I believe that functional patterns drastically simplify all the duct tape we call object oriented programming. I think there _are_ useful concepts from OO but those are essentially just the idea of domain-driven design like entities and events that match the expert humans who are describing the spec of the system. The other would be message passing to enforce decoupling but that's technically the "actor model" rather than OO. I love the concept of algebraic data types because "and" and "or" are such ubiquitous parts of natural language, their usage is lent so well to defining the what of your system's model: product types are for simultaneously existing parts that share the same label whereas sum types are for the exclusive variation of possible things that share the same label. By nesting them in various ways you can describe your domain stuff in terms of their parts that will exist or may exist. And using a recursive definition allows for even more power. What's interesting is that functions are like "implication" in language: if you have A, then you will have B. You could think of describing all the possible values you want using a sum type and then pushing an implication onto a stack so that if you get the A value then the stack frame collapses down to the appropriate B value. So you can work backwards from all the end results you could want and push a required precursor onto your code stack and keep doing that until your left with the sum type for your possible input.
yeah when i was 5 i picked up a NES controller and understood how mario jumped, didn't need a physics lesson on acceleration. when i picked up c# and learnt .SelectMany or .HasValue on nullable structs i learned about monads, didn't need a mathematics lesson on category theory.
03:19 FP Design Patterns 06:13 Core FP Principles 06:50 Functions are things 11:45 Types are sets 20:50 Functions as Parameters 29:30 *Every function is one parameter 16:58 Exceptions in Functional Land 40:47 Chaining functions instead of if-else 43:07 Monad 44:06 Bind mis-match functions 49:40 Map (*Mappable types r functors) 53:06 Monoids (Things with 3 rules)
This is really excellent. As an out of practice math nerd who has made a living slinging code for decades this was a breath of fresh air. Despite the disclaimers of don't expect to understand everything on first listen it all made perfect sense. A fine job of teaching this stuff piece by piece.
FP Design Patterns [3:10] OO pattern/principle [3:20] FP equivalent: Functions FP patterns are different Outline [4:16] (Some) Core Principles of Functional Programming [6:12] Core Principle: Functions are things [6:50] Core Principle: Composition everywhere [9:23] Designing with composition: Functions all the way down [10:22] Core Principle: Types are not classes [11:45] Types can be composed too [12:54] "AND" / "OR" "AND" types [13:46] Example: paris, tuples, records "OR" types [14:22] Real world example of type composition [15:05] Design principle: Strive for totality [16:57] Design principle: Use static types for domain modeling and documentation [20:13] Functions ad Parameters [20:50] Parameterize all the things [20:54] Tip: Function types are "interfaces" [25:10] Example: Strategy pattern [26:40] Example: Decorator pattern [27:30] 1 parameter function [29:15] Pattern: Partial application [32:08] Pattern: Use partial application to do dependency injection [34:37] Pattern: Chaining callbacks with continuations [40:53] Monads [43:07] how to combining switches "Bind" is the answer! Bind all the thing! [44:30] Pattern: Use bind to chain tasks [46:30] a.k.a "promise" "future" Pattern: Use bind to chain error handlers [47:19] Maps [49:40] Guideline: Most wrapped generic types have a "map". Use It! [52:38] Guideline: If you create your own generic type, create a "map" for it. Terminology: Mappable types are "functors" Monoids[53:05] Pattern: Convert non-monoids to monoids [1:00:17] Pattern: Seeing monoids everywhere [1:02:22] Metrics guideline: Use counters rather than rates / make sure your metrics are monoids Monads vs. monoids [1:03:54] "monad laws" are just the monoid definitions
Scott is a brilliant teacher. It’s common for FP to be explained in a confusing way, but this talk is succinct and clearly explains the value of using a FP approach!
I still love coming back to this talk, as it's one of the bests in succinctly explaining many very fundamental advantages of functional programming languages and the functional mindset itself
My thoughts exactly. I’ve heard all the basic principles/benefits of FP before, like why purity is good, but this really gave me the realistic paradigm of how we should be thinking about solving our everyday problems with FP. Definitely need to revisit.
@@digitalspecter I wouldn't, but if you take functional programming seriously, then that is exactly what happens. I mean, you can do a little better and just pass around a pointer to a structure on the heap, but that has its own problems. Either way, functional programming is horrible at handling state.
A brilliant talk. It is plainspoken, direct, but conveys the real essence of the topic at hand. The slides are clear and fresh. Scott is a remarkable educator.
Excellent - once I got past the dinosaurs it really gave me a really excellent insight into this paradigm. I did computer science in 1982 and I really struggled with OOP and actually gave up eventually - focused instead on Machine programming and PLC's - just too different from the way I think. This on the other hand is exactly how I think. Its like Asperger programming! And I am one of those!
🎯 Key Takeaways for quick navigation: 00:24 🎙️ Functional design patterns and principles are demonstrated using F# but are applicable to various programming languages. 01:36 🤖 Scott Wlaschin, the presenter, introduces himself as an object-oriented programmer turned functional programmer with a background in Smalltalk and other languages. 03:15 🛠️ The talk will cover core principles of functional programming, including functions as parameters, composition, and the role of types. 06:31 🧩 Core principles of functional programming include treating functions as standalone entities, using composition extensively, and distinguishing types from classes. 08:48 🔄 Functions can be used as inputs and outputs, leading to powerful and flexible composability in functional programming. 11:55 🧑🔬 Types in functional programming act as sets of data, allowing for flexible composition using "and" and "or" operations. 16:51 🏗️ Functional programming excels in domain modeling, where types can be composed using "and" and "or" to create powerful and expressive structures. 17:07 🚧 Designing for totality involves ensuring functions are total (never throw errors) by either constraining inputs or using types like "Maybe" to handle potentially undefined outputs. 20:09 📚 Using static types for domain modeling provides clear documentation, compile-time checks, and helps design total functions. 21:58 🔄 Parameterizing functions, including the looping action and list type, enhances flexibility and decouples behavior, a key principle in functional programming. 22:13 🔄 Generic List Iteration in F#: F# makes list iteration easy, allowing for generic list iteration with parameters like action and initial value. 23:11 🔄 Common Code Extraction in F#: In F#, the fold function helps eliminate duplicate code by extracting common elements, parameterizing the initial value and action, emphasizing the importance of functional collection functions. 25:34 📦 Functions as Interfaces in F#: In functional programming, functions serve as interfaces, aligning with principles like the Single Responsibility Principle and Interface Segregation Principle. Functions compatible with an interface don't require inheritance. 26:42 🔄 Functional Approach to Strategy Pattern: In functional languages, the Strategy pattern is implemented by passing the strategy (function) as a parameter, avoiding the need for class interfaces. 27:52 🔄 Decorator Pattern in Functional Style: Rather than classic decoration with wrappers, functional languages use composition, combining functions to create new ones. The example showcases logging without explicit wrappers. 29:24 🔄 Single Input, Single Output Principle: While multi-parameter functions exist, every function in functional programming can be conceptualized as a series of one-parameter functions, offering simplicity and consistency. 32:11 🔄 Partial Application and Flexibility: Partial application allows flexibility by transforming a multi-parameter function into a series of one-parameter functions, demonstrating its usefulness in various scenarios. 34:52 🧩 Dependency Injection with Partial Application: Dependency injection in functional programming can be achieved using partial application, providing flexibility without relying on specialized frameworks. 38:27 🔄 Parameterizing Behavior: By parameterizing behavior, functions gain flexibility, enabling the caller to decide the next steps, illustrating the power of parameterization in controlling program flow. 41:13 🔄 Monad Simplified: The concept of a monad, often viewed as complex, can be simplified as chaining continuations together. The example demonstrates this with a helper function for handling optional values. 43:20 🚂 Gluing functions together involves using a branching railway analogy, where functions can either return something or nothing. 44:29 🔄 Switch functions with one input and two outputs pose a challenge in composition. The solution is to use "bind," a functional programming concept that transforms one kind of function into another. 45:52 🔄 Bind is the core of a monad, simplifying the gluing of functions and transforming one function type into another. 46:20 🌐 Using the example of handling errors in a web service, the talk introduces the concept of monads to simplify code, making it look similar before and after error handling. 48:59 🔄 The talk discusses how the mapping pattern, using functions like "map" on different types, is a common and powerful approach in functional programming. 52:58 🔤 Functors, or mapable types, are discussed, emphasizing the importance of the "map" function in functional programming. 56:41 ➕ The talk delves into the concept of monoids, which are sets equipped with a binary operation, associativity, and an identity element, providing a generalized structure for combining elements. 01:02:52 🔄 Functions and function composition are explored as monoids, where combining functions of the same input-output type produces another function of the same kind. 01:04:12 ⚖️ Monads are discussed as monoids in the category of endofunctors, connecting the concepts of monoids and monads in functional programming. Made with HARPA AI
If you're interested, the name of that concept is "currying", named after Haskell Curry, the same person the Haskell programming language is named after.
This man is mad genius, my brain is just exploded, a couple of shopping-list-like lines of code can be compiled into the exact same thing. As if I am talking to the machine and it is talking back.
It probably doesn't take "int" or "bool", but "some type such that there is a known show function for it". This is known as a type class. For C++/Java people, it's a bit like an interface and a template function. So a type such as "Show a" guarantees there exists a "show :: a -> String", and thus log can call it to get something to work with. (This example uses Haskell syntax, but I expect it's similar in F#. I imagine this "log" is like Haskell "traceShowId".)
I love that quote "A monad is a monoid in the category of endofunctors", because it's a great example of jargon, but also, it just boils down to (in the context of functional programming) `M` is a monad when you can write `pure : a -> M a` and `join : M (M a) -> M a` for it, so it's not really difficult to understand, you just have to hand-wave through a couple of Wikipedia pages :p
You must be one of those who understood and can't explain it anymore :p There's one of those "Hitler meme" videos on FP if you haven't seen it, it's hilarious
@@bigstones84 I'll have to look that up. It depends on what you mean by "explain". I've always been one for actual definitions over partial intuition, so, for me, that quote, a few examples, and enough time with Wikipedia are enough.
Yes, Option is a functor. (On Haskell, it's "data Maybe a = Just a | Nothing", so it can be "Nothing" or Just with a value "a" and its actually "fmap" on haskell because "map" is only for lists because... reasons) Instead of doing: maybePlus1 :: Maybe Int -> Maybe Int maybePlus1 Nothing = Nothing maybePlus1 (Just a) = Just (a+1) You can do: add1 :: Int -> Int add1 x = x+1 maybePlus1 :: Maybe Int -> Maybe Int maybePlus1 mappableThing = fmap add1 mappableThing Or, if you are really mad, you can write: add1 = (+1) (+1) is a function that adds 1 to the input, not the number 1. If you have a infix operator, let's write %$% for it, we can write: (%$% x) as a function that receives "y" and returns "y %$% x". This is what we call section If you really thing, you can write: maybePlus1 mappableThing = fmap (+1) mappableThing Note that I omitted the type of the function - the compiler can infer it. And it will not be exactly the same result. It will note that (+1) can only work on numbers, and fmap will work on functors, so it infers maybePlus1 :: f num -> f num "num" can be any type that is numeric(there is a 'typeclass' for that) and "f" is any type that is a functor. And now, just one more thing: you can think "fmap" receives a function and a functor, then applies the function to the functor. That's a way to think. Another is that it receives a function "a -> b" and lifts it into another realm: "f a -> f b". With that, fmap (+1) is a function from functors to functors. maybePlus1 = fmap (+1)
Arguably, the distinction between types and classes is purely aesthetic. After all, the word class in its conventional sense (from which the OOP sense is derived) refers to "a set of things" which is the same as your definition for a type. Likewise, you say that types have no behaviours, but you could think of any function that takes an input of that type as being a behaviour of that type. But, perhaps that's okay. Aesthetic differences can be worth making sometimes.
An important thing about methods though is that they're part of defining the type, so a class is just a particular way of forming types, types are more general (e.g. structs and variants)
It's far from being an aesthetic difference. Classes define the behavior of objects. Types are for type checking. They're orthogonal concepts -- you can have type-checked values which are not class-based, and many OO languages don't do type-checking before runtime. What's throwing you is that in Java and other places, the class names also get used as the types. > class in its conventional sense (from which the OOP sense is derived) refers to "a set of things" What's relevant is the technical sense in which OO languages use the word. Classes categorize behavior, and enable delegation; types are for memory allocation and compile-time safety checks. > any function that takes an input of that type as being a behaviour of that type I **think** you're saying that we can pretend that every value of type X, in a given language, is a member of a "class" where every function that takes an X is a method on that class, and the passed-in value acts as the class instance. But the analogy breaks as soon as you consider functions of more than one argument. Functions are the more general concept. It'd be more useful to relate these things by viewing instance methods as functions that take a hidden first argument, because that's more or less what they are, under the hood (but dynamic dispatch complicates things).
you can have a very limited set of functions but yet achieve an entire set of elements even from input to output (input == output) by looking at these elements as a set that can make up a group given the right function a.k.a operation.
For me, the phrase "function composition is a monoid" makes no sense to me.... What would make sense would be something like "the set of all endomorphisms under function composition form a monoid" or "the functions from a set into the same set form a monoid with respect to function composition". Is this what the author meant? If so.. I would argue then that his wording is incorrect. If this is not what he meant, can someone shed some light? Thanks
@@metaturso well, a monoid is an algebtaic structure that contains multiple elements, one of wich is the operation... i this case it is function composition. So it is not correct to say that function composition is a monoid... It's like saying addition is a group when actually the integers together with addition form a group... I hope I make sense
@@metaturso Neither do I, and that is why I'm asking. Just trying co reconcile what he says with my mental model or with what I inderstood so far.. Whenever there's a mismatch, I have to ask because eother I didn't understand or he made a mistake. In either case, it gives me more confidence in my understaning and I can move further at greater speed. Anyway, thanks for the reply. I wish you a grandious week :D
monadic bind = - takes in an Option & a Function - unboxes the Value out of the Option - passes the unboxed Value to the Function the functions passed to the monadic bind = - takes in a Value - returns an Option
Yep, but you can use any monad - with a list, for example, bind is equivalent to flat_map: - takes in a list and a function - unboxes each value out of the list - passes each unboxed value to the function and combines each list function passed to flat_map/bind: - takes in a value - returns a list
Note that in F# the 'OR'ed fields don't necessarily occupy the same memory in the way that a C/C++ union fields do. So in C# you can just get the same behaviour by having a class/struct with an enum discriminator field. It's just that the C# syntax will be hella clunky.
@@kalvino3515 Tagged unions, more specifically. Accessing using the correct variant is enforced at compile time, don't need to do it explicitly. Sum types are only a little more workable in C/C++ than in C#
It only really happens when you're using recursion, and it's not so much an issue in functional languages since they tend to include tail call optimization, removing the previous call from the stack when you call the next function.
Oof, I am fond of OCaml and F#, but the choice to write the type of `Some 5` as `int option` is really rather unfortunate. Haskell's `Maybe Int` seems much more consistent/readable.
I accept a nonzero int that can divide 12 without using any storage and can always be done *before* anyone pulls the power cord - or else can keep working even without power and through the heat-death of the universe... ... ... uhh, I'll throw an exception
You probably shouldn't make the caller responsible for how they call the function, and instead return an Option of Int. If you're being consequent with this stuff, and all your functions are well defined for the entirety of the input set, you just eliminate places where stuff goes wrong. If your functions are simply not able to return Exceptions, then you never get an exception. You need language support for this though, in most OO languages this is impractical.
but if someone pulled the power cord, the caller won't be running to see the result too, the computation would be halted anyway, so the fact doesn't matter at all
@@monad_tcp exactly, pulling the power cord is just like an exception, its caught by the universe so the universe doesn't have to halt. Every function is a declaration, the computation happens in some Monad and the reality monad includes the power-off exception *but* it also includes excess power draw triggering power off so the definition of the function is always relevant, and intentional equivalence can be found by computing the result and that equivalence is a parameterisation of the reality monad. My conclusion is that every function must be lifted to some function reader and cannot be pure unless it is. I think the reader could be a polymorphic parameter. This is very similar to category theory and could be a useful direction.
[22:30] C/C++ can do this easily. However, their standard libraries don't use to receive the action. I guess this is due to optimization. [25:30] I guess it's kind pointless to have a class without data - what is the advantage? However, I disagree about only 1 f(): if you have a "concept" in your mind, certainly it will be correctly expressed in more than 1 f(). The Single Responsibility Principle is attended by 1 concept, not 1 f(). [27:27] FP seems so clean and nice from here. However, what OO is doing at [26:50] is hiding '_strategy', which unfortunately was not expressed in that class. This makes a big difference, justifying OO. [36:36] This is why FP is so bad: every 1 puts their dirty hands on poor girl database! In OO, a class could hold that "injection" and also control who is modifying the database. [37:41] What is the awful OO language in need of special framework to do such a simple task?! Surely not C++!
This is a pretty nice talk but be warned that a lot of what it covers are things that aren't related to FP (e.g. discriminated unions). Many functional languages don't do static type-checking at all. If you're interested in the ML family of languages specifically, this covers a lot of their conventions. It mostly doesn't translate to e.g. the Lisp family though.
Python supports all of this (maybe except an option type) natively! Partial application is not inbuilt but there's the partial function in the functools builtin - that builtin has a ton of cool stuff you can use to program in a very functional way!
@@tatianabasileus I think python is one of the worse languages to do FP in for work. Simply because for day-to-day stuff you don't have the chainable functions. There are of course filter and map on iterators, but I find list comprehensions much more practical (and they too have too much syntax, and you can't chain them) (in c-likes you can usually get the function as part of the returned object, you have the F# bar, or a threading macro - something to make lifting/binding short and easy to read). On top of that I really despise writing out lambda - sure, you can write a def for it (and that's actually a good thing in many cases), but still. Python is very verbose and annoying to read for FP. Even java does a better job for your lightweight FP stuff, like working with collections, option monads. FP is still a hard sell in many companies, so writing your own monads for collections is off the table (or even using some FP library). Or do you know something I don't for python in particular?
A monoid is a binary operation whose inputs and outputs are of the same type, and which has an identity value. So, addition, multiplication, string concatenation, etc.
It's truly unfortunate how OO has presumptuously taken itself to be the 'default' frame of reference ... It bewilders me, coming from a functional background, why anyone would want their functions 'trapped' in objects and classes ... or how anyone finds it acceptable to have idiosyncratic/non-compositional abstractions.
And as a mostly procedural programmer I have to scratch my head how a functional programmer thinks he can debug a cache coherence problem in a functional language. Oh, wait... performance is not an option in functional programming. It's simply not on the menu. ;-)
Scott Wlaschin is the "Uncle Bob" we truly deserved. I believe that functional patterns drastically simplify all the duct tape we call object oriented programming. I think there _are_ useful concepts from OO but those are essentially just the idea of domain-driven design like entities and events that match the expert humans who are describing the spec of the system. The other would be message passing to enforce decoupling but that's technically the "actor model" rather than OO.
I love the concept of algebraic data types because "and" and "or" are such ubiquitous parts of natural language, their usage is lent so well to defining the what of your system's model: product types are for simultaneously existing parts that share the same label whereas sum types are for the exclusive variation of possible things that share the same label. By nesting them in various ways you can describe your domain stuff in terms of their parts that will exist or may exist. And using a recursive definition allows for even more power.
What's interesting is that functions are like "implication" in language: if you have A, then you will have B. You could think of describing all the possible values you want using a sum type and then pushing an implication onto a stack so that if you get the A value then the stack frame collapses down to the appropriate B value. So you can work backwards from all the end results you could want and push a required precursor onto your code stack and keep doing that until your left with the sum type for your possible input.
THE BEST talk that gracefully and beautifully introduces and explains monads. This should be how textbooks teach monads to programmers.
yeah when i was 5 i picked up a NES controller and understood how mario jumped, didn't need a physics lesson on acceleration. when i picked up c# and learnt .SelectMany or .HasValue on nullable structs i learned about monads, didn't need a mathematics lesson on category theory.
1:04:55 - "A monad is just a monoid in the category of endofunctors"
03:19 FP Design Patterns
06:13 Core FP Principles
06:50 Functions are things
11:45 Types are sets
20:50 Functions as Parameters
29:30 *Every function is one parameter
16:58 Exceptions in Functional Land
40:47 Chaining functions instead of if-else
43:07 Monad
44:06 Bind mis-match functions
49:40 Map (*Mappable types r functors)
53:06 Monoids (Things with 3 rules)
Thank you!
Good human.
You’re the best
감사합니다
This is really excellent. As an out of practice math nerd who has made a living slinging code for decades this was a breath of fresh air. Despite the disclaimers of don't expect to understand everything on first listen it all made perfect sense. A fine job of teaching this stuff piece by piece.
FP Design Patterns [3:10]
OO pattern/principle [3:20]
FP equivalent: Functions
FP patterns are different
Outline [4:16]
(Some) Core Principles of Functional Programming [6:12]
Core Principle: Functions are things [6:50]
Core Principle: Composition everywhere [9:23]
Designing with composition: Functions all the way down [10:22]
Core Principle: Types are not classes [11:45]
Types can be composed too [12:54]
"AND" / "OR"
"AND" types [13:46]
Example: paris, tuples, records
"OR" types [14:22]
Real world example of type composition [15:05]
Design principle: Strive for totality [16:57]
Design principle: Use static types for domain modeling and documentation [20:13]
Functions ad Parameters [20:50]
Parameterize all the things [20:54]
Tip: Function types are "interfaces" [25:10]
Example: Strategy pattern [26:40]
Example: Decorator pattern [27:30]
1 parameter function [29:15]
Pattern: Partial application [32:08]
Pattern: Use partial application to do dependency injection [34:37]
Pattern: Chaining callbacks with continuations [40:53]
Monads [43:07]
how to combining switches
"Bind" is the answer! Bind all the thing! [44:30]
Pattern: Use bind to chain tasks [46:30]
a.k.a "promise" "future"
Pattern: Use bind to chain error handlers [47:19]
Maps [49:40]
Guideline: Most wrapped generic types have a "map". Use It! [52:38]
Guideline: If you create your own generic type, create a "map" for it.
Terminology: Mappable types are "functors"
Monoids[53:05]
Pattern: Convert non-monoids to monoids [1:00:17]
Pattern: Seeing monoids everywhere [1:02:22]
Metrics guideline: Use counters rather than rates / make sure your metrics are monoids
Monads vs. monoids [1:03:54]
"monad laws" are just the monoid definitions
Scott is a brilliant teacher. It’s common for FP to be explained in a confusing way, but this talk is succinct and clearly explains the value of using a FP approach!
What is the value of dragging your state over the stack a million times a second, exactly?
one of the best programming talks i've seen
I still love coming back to this talk, as it's one of the bests in succinctly explaining many very fundamental advantages of functional programming languages and the functional mindset itself
My thoughts exactly. I’ve heard all the basic principles/benefits of FP before, like why purity is good, but this really gave me the realistic paradigm of how we should be thinking about solving our everyday problems with FP. Definitely need to revisit.
@@tsp4axl I would suggest you think about the implications of putting multiple copies of your state variables on the stack for a little bit.
@@lepidoptera9337 Why would you do that?
@@digitalspecter I wouldn't, but if you take functional programming seriously, then that is exactly what happens. I mean, you can do a little better and just pass around a pointer to a structure on the heap, but that has its own problems. Either way, functional programming is horrible at handling state.
A brilliant talk. It is plainspoken, direct, but conveys the real essence of the topic at hand. The slides are clear and fresh. Scott is a remarkable educator.
Beauty of functional programming in plain english. This talk give me the light in my head of what really is the benefit of FP!
This champion just casually drops the most intuitive explanation of the monad joke on the internet.
If more experts explained FP or any topic like this, we would all be programmers.
lol, implying imperative/oo people aren't programmers, I liked it
@@monad_tcp
Every programmer is a functional programmer.
He's just showing how to use types to reduce syntax repetition and erros.
@@dialecticalmonist3405 "Every programmer is a functional programmer". They do indeed "function" very well I guess.
Sarcasm pass you by.
The best functional programming introduction. Period!
Excellent ! Best monad step by step explanation !
A great speech that is still worth revisiting even after a long time.
A monad is a monoid in the category of endofunctors.
This is one of the many videos I found helpful and insightful which enlightens me on the way to FP. Thank you!!!
Best talk about functional programming ever. Thank you
Great talk 👍👍
Gained a lot of in-depth insights only in an hour
It's beautiful! I've looked at this for five hours now...
Excellent - once I got past the dinosaurs it really gave me a really excellent insight into this paradigm. I did computer science in 1982 and I really struggled with OOP and actually gave up eventually - focused instead on Machine programming and PLC's - just too different from the way I think.
This on the other hand is exactly how I think. Its like Asperger programming! And I am one of those!
In modern times, OOP is a weird thing. It's very popular. Yet it makes everyone's lives so much harder.
"Functional Design" "Types are not classes" meanwhile Haskell: "we have typeclasses"
Clear and understandable. You did an amazing job!
🎯 Key Takeaways for quick navigation:
00:24 🎙️ Functional design patterns and principles are demonstrated using F# but are applicable to various programming languages.
01:36 🤖 Scott Wlaschin, the presenter, introduces himself as an object-oriented programmer turned functional programmer with a background in Smalltalk and other languages.
03:15 🛠️ The talk will cover core principles of functional programming, including functions as parameters, composition, and the role of types.
06:31 🧩 Core principles of functional programming include treating functions as standalone entities, using composition extensively, and distinguishing types from classes.
08:48 🔄 Functions can be used as inputs and outputs, leading to powerful and flexible composability in functional programming.
11:55 🧑🔬 Types in functional programming act as sets of data, allowing for flexible composition using "and" and "or" operations.
16:51 🏗️ Functional programming excels in domain modeling, where types can be composed using "and" and "or" to create powerful and expressive structures.
17:07 🚧 Designing for totality involves ensuring functions are total (never throw errors) by either constraining inputs or using types like "Maybe" to handle potentially undefined outputs.
20:09 📚 Using static types for domain modeling provides clear documentation, compile-time checks, and helps design total functions.
21:58 🔄 Parameterizing functions, including the looping action and list type, enhances flexibility and decouples behavior, a key principle in functional programming.
22:13 🔄 Generic List Iteration in F#: F# makes list iteration easy, allowing for generic list iteration with parameters like action and initial value.
23:11 🔄 Common Code Extraction in F#: In F#, the fold function helps eliminate duplicate code by extracting common elements, parameterizing the initial value and action, emphasizing the importance of functional collection functions.
25:34 📦 Functions as Interfaces in F#: In functional programming, functions serve as interfaces, aligning with principles like the Single Responsibility Principle and Interface Segregation Principle. Functions compatible with an interface don't require inheritance.
26:42 🔄 Functional Approach to Strategy Pattern: In functional languages, the Strategy pattern is implemented by passing the strategy (function) as a parameter, avoiding the need for class interfaces.
27:52 🔄 Decorator Pattern in Functional Style: Rather than classic decoration with wrappers, functional languages use composition, combining functions to create new ones. The example showcases logging without explicit wrappers.
29:24 🔄 Single Input, Single Output Principle: While multi-parameter functions exist, every function in functional programming can be conceptualized as a series of one-parameter functions, offering simplicity and consistency.
32:11 🔄 Partial Application and Flexibility: Partial application allows flexibility by transforming a multi-parameter function into a series of one-parameter functions, demonstrating its usefulness in various scenarios.
34:52 🧩 Dependency Injection with Partial Application: Dependency injection in functional programming can be achieved using partial application, providing flexibility without relying on specialized frameworks.
38:27 🔄 Parameterizing Behavior: By parameterizing behavior, functions gain flexibility, enabling the caller to decide the next steps, illustrating the power of parameterization in controlling program flow.
41:13 🔄 Monad Simplified: The concept of a monad, often viewed as complex, can be simplified as chaining continuations together. The example demonstrates this with a helper function for handling optional values.
43:20 🚂 Gluing functions together involves using a branching railway analogy, where functions can either return something or nothing.
44:29 🔄 Switch functions with one input and two outputs pose a challenge in composition. The solution is to use "bind," a functional programming concept that transforms one kind of function into another.
45:52 🔄 Bind is the core of a monad, simplifying the gluing of functions and transforming one function type into another.
46:20 🌐 Using the example of handling errors in a web service, the talk introduces the concept of monads to simplify code, making it look similar before and after error handling.
48:59 🔄 The talk discusses how the mapping pattern, using functions like "map" on different types, is a common and powerful approach in functional programming.
52:58 🔤 Functors, or mapable types, are discussed, emphasizing the importance of the "map" function in functional programming.
56:41 ➕ The talk delves into the concept of monoids, which are sets equipped with a binary operation, associativity, and an identity element, providing a generalized structure for combining elements.
01:02:52 🔄 Functions and function composition are explored as monoids, where combining functions of the same input-output type produces another function of the same kind.
01:04:12 ⚖️ Monads are discussed as monoids in the category of endofunctors, connecting the concepts of monoids and monads in functional programming.
Made with HARPA AI
모나드를 간단하고 덤덤하게 설명 잘해 주시네요 . 감사합니다
Four years later and this is still awesome
amazing. best FP video I've ever seen
"An OR object is not easy to make in object oriented"
I knew my ventures into C++ would be useful.
FP diehards be like, "its so simple let me show you. This is gonna get complicated so excuse me if it's confusing"
This was not his best talk explaining the concepts for sure. He really didn’t say much of anything IMO. He’s awesome, but this talk is just mid
Well, it was more complicated that adding 1 + 2, but not that much.
That's true for any topic, if you go into enough detail.
The one parameter function concept is a game changer
If you're interested, the name of that concept is "currying", named after Haskell Curry, the same person the Haskell programming language is named after.
Also, functions like
add : (Int, Int) -> Int
add (x, y) = x + y
take only one parameter too*! They take pairs
*depends on the language tho
"It's really simple and I will show you. Now this is getting complicated." XD
Outstanding clarity! Thank you!
This man is mad genius, my brain is just exploded, a couple of shopping-list-like lines of code can be compiled into the exact same thing. As if I am talking to the machine and it is talking back.
Scott is the best teacher
Great talk on Functional programming!
This is a gem.
the doX functions in 43:01 have a type signature of: Option.Val -> Option
Good talk and very good presentation. thank your for sharing your thoughts :)
29:02 Didn't get how the same log function was taking an int (first) and a bool (second).
It probably doesn't take "int" or "bool", but "some type such that there is a known show function for it". This is known as a type class. For C++/Java people, it's a bit like an interface and a template function. So a type such as "Show a" guarantees there exists a "show :: a -> String", and thus log can call it to get something to work with. (This example uses Haskell syntax, but I expect it's similar in F#. I imagine this "log" is like Haskell "traceShowId".)
@@0LoneTech Got it. The type is parameterized, return type is the same as the input type. Makes sense. Thank you!
I am getting ready to start watching the video so peeped the comments. Sounds like this talk is going to change my life. Hitting play now!!
Just going to skim the f# wikipedia a little before
I love that quote "A monad is a monoid in the category of endofunctors", because it's a great example of jargon, but also, it just boils down to (in the context of functional programming) `M` is a monad when you can write `pure : a -> M a` and `join : M (M a) -> M a` for it, so it's not really difficult to understand, you just have to hand-wave through a couple of Wikipedia pages :p
You must be one of those who understood and can't explain it anymore :p There's one of those "Hitler meme" videos on FP if you haven't seen it, it's hilarious
@@bigstones84 I'll have to look that up.
It depends on what you mean by "explain". I've always been one for actual definitions over partial intuition, so, for me, that quote, a few examples, and enough time with Wikipedia are enough.
Wut?
Where is the FIzzBuzz example again?
Is this about interior design
Extremely digestible, thank you Scott
Great slides! Great graphics! Wonderfully subtle humour!
anti-tip: you can also 'superficially slim down' the pipe by chaining function calls within the function body
I didn't understand functional programming before, but now I do.
a functor is any type that provides a 'map' function!
Options provide a 'map' function
Yes, Option is a functor. (On Haskell, it's "data Maybe a = Just a | Nothing", so it can be "Nothing" or Just with a value "a" and its actually "fmap" on haskell because "map" is only for lists because... reasons)
Instead of doing:
maybePlus1 :: Maybe Int -> Maybe Int
maybePlus1 Nothing = Nothing
maybePlus1 (Just a) = Just (a+1)
You can do:
add1 :: Int -> Int
add1 x = x+1
maybePlus1 :: Maybe Int -> Maybe Int
maybePlus1 mappableThing = fmap add1 mappableThing
Or, if you are really mad, you can write:
add1 = (+1)
(+1) is a function that adds 1 to the input, not the number 1. If you have a infix operator, let's write %$% for it, we can write: (%$% x) as a function that receives "y" and returns "y %$% x". This is what we call section
If you really thing, you can write:
maybePlus1 mappableThing = fmap (+1) mappableThing
Note that I omitted the type of the function - the compiler can infer it. And it will not be exactly the same result. It will note that (+1) can only work on numbers, and fmap will work on functors, so it infers maybePlus1 :: f num -> f num
"num" can be any type that is numeric(there is a 'typeclass' for that) and "f" is any type that is a functor.
And now, just one more thing: you can think "fmap" receives a function and a functor, then applies the function to the functor. That's a way to think. Another is that it receives a function "a -> b" and lifts it into another realm: "f a -> f b". With that, fmap (+1) is a function from functors to functors.
maybePlus1 = fmap (+1)
Arguably, the distinction between types and classes is purely aesthetic.
After all, the word class in its conventional sense (from which the OOP sense is derived) refers to "a set of things" which is the same as your definition for a type.
Likewise, you say that types have no behaviours, but you could think of any function that takes an input of that type as being a behaviour of that type.
But, perhaps that's okay. Aesthetic differences can be worth making sometimes.
An important thing about methods though is that they're part of defining the type, so a class is just a particular way of forming types, types are more general (e.g. structs and variants)
It's far from being an aesthetic difference. Classes define the behavior of objects. Types are for type checking. They're orthogonal concepts -- you can have type-checked values which are not class-based, and many OO languages don't do type-checking before runtime.
What's throwing you is that in Java and other places, the class names also get used as the types.
> class in its conventional sense (from which the OOP sense is derived) refers to "a set of things"
What's relevant is the technical sense in which OO languages use the word. Classes categorize behavior, and enable delegation; types are for memory allocation and compile-time safety checks.
> any function that takes an input of that type as being a behaviour of that type
I **think** you're saying that we can pretend that every value of type X, in a given language, is a member of a "class" where every function that takes an X is a method on that class, and the passed-in value acts as the class instance. But the analogy breaks as soon as you consider functions of more than one argument.
Functions are the more general concept. It'd be more useful to relate these things by viewing instance methods as functions that take a hidden first argument, because that's more or less what they are, under the hood (but dynamic dispatch complicates things).
oh okay, a monoid is anything i can do a "reduce" on
This is the explanation I needed.
How to do this in typescript? Recommendations?
Does some guy next to camera start eating crisps around 45 mins in?
it sounds like the camera itself is eating chips.
maybe to recharge the battery since the speaker went overtime
It sounds like his shoes or maybe he is wearing leather trousers
this is the sound of microphone being scratched by his beard
Yes, pringles
15:00 So unions from C, then?
this is simply awesome, thanks for the talk
you can have a very limited set of functions but yet achieve an entire set of elements even from input to output (input == output) by looking at these elements as a set that can make up a group given the right function a.k.a operation.
Where in the ivory tower do the JavaScript developers live? ☺
For me, the phrase "function composition is a monoid" makes no sense to me....
What would make sense would be something like "the set of all endomorphisms under function composition form a monoid" or "the functions from a set into the same set form a monoid with respect to function composition". Is this what the author meant? If so.. I would argue then that his wording is incorrect. If this is not what he meant, can someone shed some light? Thanks
@@metaturso well, a monoid is an algebtaic structure that contains multiple elements, one of wich is the operation... i this case it is function composition. So it is not correct to say that function composition is a monoid... It's like saying addition is a group when actually the integers together with addition form a group...
I hope I make sense
@@metaturso Neither do I, and that is why I'm asking. Just trying co reconcile what he says with my mental model or with what I inderstood so far.. Whenever there's a mismatch, I have to ask because eother I didn't understand or he made a mistake. In either case, it gives me more confidence in my understaning and I can move further at greater speed. Anyway, thanks for the reply. I wish you a grandious week :D
I need to heckle the TwelveDividedBy function bit to say that most integers given won't return an integer.
I need to share this with the team.
That was mind blowing!
monadic bind =
- takes in an Option & a Function
- unboxes the Value out of the Option
- passes the unboxed Value to the Function
the functions passed to the monadic bind =
- takes in a Value
- returns an Option
Yep, but you can use any monad - with a list, for example, bind is equivalent to flat_map:
- takes in a list and a function
- unboxes each value out of the list
- passes each unboxed value to the function and combines each list
function passed to flat_map/bind:
- takes in a value
- returns a list
@@berylliosis5250 thanks so much! this is very true!
(I realized this after looking into this stuff some more lol :))
Audience is too quite, I believe that's why Scott referencing another video on his site ;)
This one railway two tracks illustration says more than a whole medium article
Incredible talk
Watching this as a C, JavaScript, and PHP holdout... Thinking WTH is an option?
give rust a shot
Aren't "Or" types just enums? Why is it so difficult to have those in c#?
Not enums, unions (C/C++)
Note that in F# the 'OR'ed fields don't necessarily occupy the same memory in the way that a C/C++ union fields do. So in C# you can just get the same behaviour by having a class/struct with an enum discriminator field. It's just that the C# syntax will be hella clunky.
@@Geert2682 Oh, didn't realize that, either way, OO languages are def not designed around Functional principles, and vice versa
@@kalvino3515 Tagged unions, more specifically. Accessing using the correct variant is enforced at compile time, don't need to do it explicitly. Sum types are only a little more workable in C/C++ than in C#
In some cases, I believe it will cause stack-overflow when it calls functions too deeply...
It only really happens when you're using recursion, and it's not so much an issue in functional languages since they tend to include tail call optimization, removing the previous call from the stack when you call the next function.
Oof, I am fond of OCaml and F#, but the choice to write the type of `Some 5` as `int option` is really rather unfortunate. Haskell's `Maybe Int` seems much more consistent/readable.
So if golang had monads, would they be gonads? I'll get my coat.
Brilliant!
Great video
Most tangible metaphor for bind I have ever seen.
Golang needs it's own "special" implementation of monads.... so, as well as 'goroutines', it could have...........
(shrugs)... I thought it was funny.:(
Great speaker.
killed it! awesome!
I accept a nonzero int that can divide 12 without using any storage and can always be done *before* anyone pulls the power cord - or else can keep working even without power and through the heat-death of the universe... ... ... uhh, I'll throw an exception
You probably shouldn't make the caller responsible for how they call the function, and instead return an Option of Int. If you're being consequent with this stuff, and all your functions are well defined for the entirety of the input set, you just eliminate places where stuff goes wrong. If your functions are simply not able to return Exceptions, then you never get an exception. You need language support for this though, in most OO languages this is impractical.
but if someone pulled the power cord, the caller won't be running to see the result too, the computation would be halted anyway, so the fact doesn't matter at all
@@monad_tcp exactly, pulling the power cord is just like an exception, its caught by the universe so the universe doesn't have to halt. Every function is a declaration, the computation happens in some Monad and the reality monad includes the power-off exception *but* it also includes excess power draw triggering power off so the definition of the function is always relevant, and intentional equivalence can be found by computing the result and that equivalence is a parameterisation of the reality monad. My conclusion is that every function must be lifted to some function reader and cannot be pure unless it is. I think the reader could be a polymorphic parameter. This is very similar to category theory and could be a useful direction.
[22:30] C/C++ can do this easily. However, their standard libraries don't use to receive the action. I guess this is due to optimization.
[25:30] I guess it's kind pointless to have a class without data - what is the advantage? However, I disagree about only 1 f(): if you have a "concept" in your mind, certainly it will be correctly expressed in more than 1 f(). The Single Responsibility Principle is attended by 1 concept, not 1 f().
[27:27] FP seems so clean and nice from here. However, what OO is doing at [26:50] is hiding '_strategy', which unfortunately was not expressed in that class. This makes a big difference, justifying OO.
[36:36] This is why FP is so bad: every 1 puts their dirty hands on poor girl database! In OO, a class could hold that "injection" and also control who is modifying the database. [37:41] What is the awful OO language in need of special framework to do such a simple task?! Surely not C++!
9:05 - This guy nodes
Category Theory is to Programming what music theory is to Music.
The infinite series mathmaticians want a word with you on that order of additions doesn't matter point.
Very well explained!
So TIL. Typescript is basically a functional language.
This is a pretty nice talk but be warned that a lot of what it covers are things that aren't related to FP (e.g. discriminated unions). Many functional languages don't do static type-checking at all.
If you're interested in the ML family of languages specifically, this covers a lot of their conventions. It mostly doesn't translate to e.g. the Lisp family though.
Not me getting jealous some people get all these dope tools from their language while I have to use python at work...
Python supports all of this (maybe except an option type) natively! Partial application is not inbuilt but there's the partial function in the functools builtin - that builtin has a ton of cool stuff you can use to program in a very functional way!
@@tatianabasileus I think python is one of the worse languages to do FP in for work. Simply because for day-to-day stuff you don't have the chainable functions. There are of course filter and map on iterators, but I find list comprehensions much more practical (and they too have too much syntax, and you can't chain them) (in c-likes you can usually get the function as part of the returned object, you have the F# bar, or a threading macro - something to make lifting/binding short and easy to read). On top of that I really despise writing out lambda - sure, you can write a def for it (and that's actually a good thing in many cases), but still. Python is very verbose and annoying to read for FP. Even java does a better job for your lightweight FP stuff, like working with collections, option monads.
FP is still a hard sell in many companies, so writing your own monads for collections is off the table (or even using some FP library). Or do you know something I don't for python in particular?
I like some of these ideas but I'd like to use them _inside_ my OO code with a language people would actually understand
Railways are a strange analogy to use here because you can't send railway track down a train tunnel unless it's smaller
01:17 test
this guy memes harder than most kids of my age
The best!
bind == ifSomeDo
great talk, now i can understand the meme
this should be taught in every computer science class so we dont end up with tragedies like stackoverflow and c++
he broke the burrito curse
so monoids are value objects?
A monoid is a binary operation whose inputs and outputs are of the same type, and which has an identity value. So, addition, multiplication, string concatenation, etc.
It's truly unfortunate how OO has presumptuously taken itself to be the 'default' frame of reference ... It bewilders me, coming from a functional background, why anyone would want their functions 'trapped' in objects and classes ... or how anyone finds it acceptable to have idiosyncratic/non-compositional abstractions.
And as a mostly procedural programmer I have to scratch my head how a functional programmer thinks he can debug a cache coherence problem in a functional language. Oh, wait... performance is not an option in functional programming. It's simply not on the menu. ;-)
"50% of your code is error handling..." Hahahaha. HAHAHAHAHAA. I wish, but people are usually more optimistic than that....
So funny how he was afraid of using word "object“. Functions are things :D
Visual Basic isn't a functional language, is that part of the joke? It doesn't quite fit into the image, I think.
As far as I can tell none of this is specific to FP.