This is such an excellent talk. I think this principle of "data structures first" can apply to all kinds of languages/frameworks. I tend to work this way a lot in TypeScript and ReasonML, but I haven't really fleshed out my philosophy on workflow until this point. This talk gives me some tools for describing it.
In languages like Java people often see types as obstacles, and talk about the "freedom" JS, Python, ... gives. I get that Java's type system isn't nearly as nice, but you still can get the same benefits with a little persistence and discipline, and then types become the safety gear you can rely on. It's a shame that not more OO programmers understand this, just because the benefits are not so easy to grasp as in languages like Elm.
This talk resonated with me so much. What an incredible thing to explain to people, I do think though that you kind of have to experience the pain of doing it with components though to really get it. Spot on though. Thanks for posting the conf online for free.
Using opaque types feels like doing OO and I thought I was “not doing proper FP” because of it. But there’s no denying the need for cohesion. So I’m very glad I watched this video. But I’m also interested in learning other ways of getting cohesion in other ways if there are any.
(Just doc, Just problem) was no disallowed state, it was what the 'Failure Problem Doc' constructor was encapsulating.. It is interesting to see this example as I was thinking about this a lot, having seen the RemoteData/WedData module, missing the loaded doc + problem state... to me, it turned out that it depends... how much the logic of loading spinner, displaying a the problem, displaying the doc, is disjoint... it felt right to expand all the states, but I ended up writing ugly similar case statements, where branches got repeated, different subsets each time. It helped to split out the concerns (LoadingState, Maybe Doc, Maybe Fail) and the code was suddendly much more natural...
At 34:54, it looks like Richard has built a finite state machine but missing vectors. Why not just create a state machine with proper transitions? I'm not being critical; I am genuinely ignorant and curious. It's possible to do in Elm, yes?
For the benefit of a newbie: why mapTitle (String->String) -> Doc -> Doc, rather than setTitle String -> Doc -> Doc ? Seems you would have to do doc2 = mapTitle (\_ -> "New title") doc1
I'm not sure if this is the answer, but I'll give it a shot nonetheless. From what I've been reading lately, in functional programming there's a concept called Functors (the name's not important, but it might help you find more info about it if you want to), which, roughly speaking, is like a "data structure" (like trees, lists, etc). Functors have a function named "map" that convert the values from one thing to another. For instance, let's say you have a list of integers and a function that, given one single integer, it tells whether it's even or not. Well, the you can "map" your list of integers to a new list of booleans by applying the "even" function to each element of your list. You're basically "mapping" one list to another. So here comes the answer: "setTitle" conveys the idea that you have a Doc instance and you're mutating it. "mapTitle", on the other hand, takes a doc and a new title, and it maps it all into a new Doc in which the title has been changed. The "new title" is probably a function because "maps" always take a function... and perhaps there some machinery that makes use of this? I don't know 😂 If someone with more expertise on the subject could corroborate my explanation, it'd be great. But that's what I think it's happening here 😇
@@DavidAguileraMoncusi - I don't think so: that's what setTitle takes. mapTitle takes a doc and a function which maps a string (old title) to a string (new title). mapTitle internally extracts the old title and passes it as an argument to the function. I guess if you had a list of articles and you wanted to capitalize all the titles, it would be useful. However, if the function were (Doc->string) I can see that being more useful than (string->string). More powerfully, you could just map (Doc->Doc), in which case the function you pass could use setTitle.
I am new too. My assumption is that "map" is mapping a function. A function can utilize conditionals such as filters, etc. This means some values in the list can be skipped entirely or altered conditionally. Whereas "set" is simply setting the value at each index no matter what.
The life of a File: th-cam.com/video/XpDsk374LDE/w-d-xo.html Scaling Elm Apps: th-cam.com/video/DoA4Txr4GUs/w-d-xo.html Making Impossible States Impossible: th-cam.com/video/IcgmSRJHu_8/w-d-xo.html
Am I wrong to be bothered by the multiple-sources-of-truth in the "words" example? In calculating the value of words (the word count), you are duplicating information that is available (albeit with effort) purely from "chapters". Any duplicate data can get out of sync, and that's not even getting to your caching mechanism. For this stuff I have a rule to never "create information" that is purely derivative... even at the cost of performance. Then again, I'm used to the lazy-by-default language Haskell, where it can remember the value it last computed. Is this too stingy of a principle to follow for Elm, or should I keep it up?
If I remember correctly, in one of the other talks it was said that caching is the only reason to allow multiple sources of truth. So here you could start with not caching wordcount, and if in practice you notice that counting it all the time is too slow (which I guess it is), then you just have to cache it to make application work quickly enough.
For so long a time I haven't watch a video so carefully and closely. Thank you!
This is such an excellent talk. I think this principle of "data structures first" can apply to all kinds of languages/frameworks. I tend to work this way a lot in TypeScript and ReasonML, but I haven't really fleshed out my philosophy on workflow until this point. This talk gives me some tools for describing it.
Fabulous talk. Thanks Richard.
Thanks! I definitely going to look into opaque types more and start using them.
In languages like Java people often see types as obstacles, and talk about the "freedom" JS, Python, ... gives. I get that Java's type system isn't nearly as nice, but you still can get the same benefits with a little persistence and discipline, and then types become the safety gear you can rely on. It's a shame that not more OO programmers understand this, just because the benefits are not so easy to grasp as in languages like Elm.
Really cool talk. I wish more people watched it - hopefully our software would be less crappy.
This talk resonated with me so much. What an incredible thing to explain to people, I do think though that you kind of have to experience the pain of doing it with components though to really get it. Spot on though. Thanks for posting the conf online for free.
I think TDD fills the role of “building your model first” in OO languages.
A TDD cycle would be Discover -> Build -> Refactor -> Discover ...
Using opaque types feels like doing OO and I thought I was “not doing proper FP” because of it. But there’s no denying the need for cohesion. So I’m very glad I watched this video. But I’m also interested in learning other ways of getting cohesion in other ways if there are any.
say "doc dot docId" 5 times very fast. If you fail you have to drink a shot.
They were nice people. They invited me to go up in their tree house when I was in tge 6th grade
(Just doc, Just problem) was no disallowed state, it was what the 'Failure Problem Doc' constructor was encapsulating.. It is interesting to see this example as I was thinking about this a lot, having seen the RemoteData/WedData module, missing the loaded doc + problem state... to me, it turned out that it depends... how much the logic of loading spinner, displaying a the problem, displaying the doc, is disjoint... it felt right to expand all the states, but I ended up writing ugly similar case statements, where branches got repeated, different subsets each time. It helped to split out the concerns (LoadingState, Maybe Doc, Maybe Fail) and the code was suddendly much more natural...
Great talk :D
At 34:54, it looks like Richard has built a finite state machine but missing vectors. Why not just create a state machine with proper transitions? I'm not being critical; I am genuinely ignorant and curious. It's possible to do in Elm, yes?
For the benefit of a newbie: why mapTitle (String->String) -> Doc -> Doc, rather than setTitle String -> Doc -> Doc ? Seems you would have to do doc2 = mapTitle (\_ -> "New title") doc1
I'd like to know that too.
I'm not sure if this is the answer, but I'll give it a shot nonetheless. From what I've been reading lately, in functional programming there's a concept called Functors (the name's not important, but it might help you find more info about it if you want to), which, roughly speaking, is like a "data structure" (like trees, lists, etc).
Functors have a function named "map" that convert the values from one thing to another. For instance, let's say you have a list of integers and a function that, given one single integer, it tells whether it's even or not. Well, the you can "map" your list of integers to a new list of booleans by applying the "even" function to each element of your list. You're basically "mapping" one list to another.
So here comes the answer: "setTitle" conveys the idea that you have a Doc instance and you're mutating it. "mapTitle", on the other hand, takes a doc and a new title, and it maps it all into a new Doc in which the title has been changed. The "new title" is probably a function because "maps" always take a function... and perhaps there some machinery that makes use of this? I don't know 😂
If someone with more expertise on the subject could corroborate my explanation, it'd be great. But that's what I think it's happening here 😇
@@DavidAguileraMoncusi - I don't think so: that's what setTitle takes. mapTitle takes a doc and a function which maps a string (old title) to a string (new title). mapTitle internally extracts the old title and passes it as an argument to the function. I guess if you had a list of articles and you wanted to capitalize all the titles, it would be useful. However, if the function were (Doc->string) I can see that being more useful than (string->string). More powerfully, you could just map (Doc->Doc), in which case the function you pass could use setTitle.
@@briancandler4024 you're right! Then I have no clue 😅
I am new too.
My assumption is that "map" is mapping a function. A function can utilize conditionals such as filters, etc. This means some values in the list can be skipped entirely or altered conditionally.
Whereas "set" is simply setting the value at each index no matter what.
The life of a File: th-cam.com/video/XpDsk374LDE/w-d-xo.html
Scaling Elm Apps: th-cam.com/video/DoA4Txr4GUs/w-d-xo.html
Making Impossible States Impossible: th-cam.com/video/IcgmSRJHu_8/w-d-xo.html
20 bucks or the dope.
Tom Arnold is not a child mokester
I don't think Richard feldman owns a dog named Lincoln
Am I wrong to be bothered by the multiple-sources-of-truth in the "words" example? In calculating the value of words (the word count), you are duplicating information that is available (albeit with effort) purely from "chapters". Any duplicate data can get out of sync, and that's not even getting to your caching mechanism. For this stuff I have a rule to never "create information" that is purely derivative... even at the cost of performance. Then again, I'm used to the lazy-by-default language Haskell, where it can remember the value it last computed.
Is this too stingy of a principle to follow for Elm, or should I keep it up?
If I remember correctly, in one of the other talks it was said that caching is the only reason to allow multiple sources of truth.
So here you could start with not caching wordcount, and if in practice you notice that counting it all the time is too slow (which I guess it is), then you just have to cache it to make application work quickly enough.
@@MarkusLaire Any chance you know which talk that was? Or something on recommended ways of caching?
@@parodoxis I found it, but it's just quite short comment: th-cam.com/video/28OdemxhfbU/w-d-xo.html