 Thank you So I'm not going to talk a whole lot about what this is Except to say it's a way that you can write web front-ends in the house and How awesome is that? It uses a library called reflex, which is an FRP or functional reactive programming library And I'll just leave it at that Hopefully you'll I'm gonna pretty much just live code something here so we can inject As much as much requests as you want and we can go as long or as little as you want So the interesting thing about this is it is using a little web app that I wrote called H snippet and Is currently being hosted by obsidian systems? I should give them a shout out because the guys who founded obsidian systems are the guys who wrote reflex and And so they're they're a big a big contributor to the reflex ecosystem And they they're paying for the hosting for a sniffer right now Anyone can create an account So it's very low no friction. I Also sort of intended a snippet to be like a nice web app template that uses snap and reflex and love sockets and servants But I haven't gotten it to that point yet It's on the way. So if you are interested in looking at the code to a snippet you can find it on github at my github page and See how to see some of the code there but so Let's be creed the phone size. Yes, I can We're trying to build a web page. So what's the simplest possible thing we can build? What just happened? We a snippet took this Concatenated in it with like some import statements and a main Into a Haskell file it compiled that Haskell file with GHC JS GHC JS resulted in a JavaScript file as an output Let's send the jazz file back Injected it right here in In the browser and if we want to look at the build messages, we can see them here If we want to have like a little a little error We can see an error Not scope TX So the documentation so reflex is an FRP library This is reflex documentation right here and then a reflex dash DOM is the name of the library that is the like web interface That's based on a reflex So most of the stuff that I'm doing here in this presentation is going to be coming from the reflex DOM library and I'll try to Actually make it seem like I don't know what functions to use and we can look them up here for the fun of it in in the API So okay, we have we have a simple text hello world We run that again. We can see it. What's the next thing we want to do? Well, let's just add like an h1 around it and make it a title How do we do that? Well, if we go back here to reflex DOM documentation Here's the reflex DOM page If we go to reflex DOM widget basic It's where most of these Sorry, we're most of these functions live and if we just scroll through here here We can see the text function. We just used it's basically a function string whoops String to an L And if we keep on looking down here further We'll pass some miscellaneous stuff. Aha for an element This takes a string and it takes another M thing So what we can do is we can say l h1 dollar sign Does that make sense? Or instead of using the dollar sign I could use parentheses But I'm going to use the dollar sign for purposes that we'll be telling you later Hello world in h1 tag Okay, that's Now we now we can see how to start building up a top. You can basically You do this we could say L Diff text by so GACJS is Bit slow But it well and more than makes up for as slow as with things you can do with it Okay, so okay, so now we can see here that this monad that we're in the do notation is basically Equivalent to ordering stuff in your dog This is what like your writing html Now let's do something a little bit more interesting Let's create This is a button. We have to give the string and it gives us back an M event Let's just try this Let's say button You can click it, but it doesn't do anything The reason it doesn't do anything is because we're not doing anything with the event that came back from the button So let's capture this event and Then let's go to Over here to reflex There's a nice little function called Over you can I was I was hoping for a nice hot here we go Count is is a it takes an event of anything and Returns us a dynamic B where B is enough. So now let's say Count E. What does this do? We gave it an event and it gives us a dynamic Now we need to display it. We need to say We need to look for something that takes a dynamic Dine text it takes a dynamic and it doesn't do anything which kind of means it probably displays it in the dog But it takes a dynamic string So we're gonna have to do Dine text this isn't quite right Because it needs a dynamic string and count gives us a dynamic. No So we have to call a function Actually The count function is also romantic So we need to blind this to map dying Very good question that is a super frequently asked question dynamic is not an applicative functor right now for performance reasons because it does some sharing of results going on and and Right is very very concerned about making sure that Everything is is performant enough to be usable in production applications. So he knows That it should be it should be feasible to make it an applicative functor But he just hasn't had the time to actually do it yet. So at some point something like the graph-refined library. I don't know The underlying implementation for reflex is really airy. So I would guess maybe no, but I'm not sure Okay, our error here we couldn't do show. Oh, right because it was a type of no so if we add show int Just for a really simple way of getting getting ourselves a type type invitation if this should And now it can't start clicks. Does this make sense to everybody? So that time is kind of the key thing here. There are events are funters And there's another thing called behaviors, which are also funters a dynamic is really basically a combination of an event and a behavior Behavior is something that you can look at at any point in time And you can say what is this thing and it will it will tell you what what this current value is Event is something that happens at some like discrete point in time or a stream of things that happen at discrete points in time so events kind of are push-driven and behaviors are kind of pull-driven a dynamic is You can think of it as kind of a combination of an event and a behavior it is Pull-driven because I have that behavior in there So you can look at its value anytime you want, but it also contains an event Which tells you whatever the dynamic gets updated. It's like a sample Right if you are provided with the ability to get an event of all its updates and you are provided with the ability to get its current value at any time If you wanted to write count yourself you would take the integral of the form of which Increases by one and then you can sample it by the underlying Let's let's write it. Let's do that right now instead of count let's say Let's see we're gonna do a full dive. So let's go look here fold died it has this type signature It takes an accumulator function an initial value and an event of a's which are the updates So we'll say full time plus one Zero BV plus one is a function BV Yes So this is probably exactly what that is under the hood Interesting Yeah, yeah, I wonder if there's a reason he's using this particular implementation instead of the one we just did I don't know But we can we can see how this thing is implemented Here he's So hold died there's kind of two combinators that let you construct dynamics hold dying and fold die hold dying takes an initial value and then a stream of events of new values Hold dying is what we just looked at Yeah, well, it's implemented with these lower level terms But let's just get back to something a little bit more more interesting here Let's do a text input So over here, there's another module reflex dog widget input which contains most of the input elements And here we have text input and it takes a config and it gives us back a text input So Ti what do you know we have a text input? Okay, that's um now. Let's do this Well, the dime text Now let's go back to this text input It has something called text input value, which is a type dynamic string so this is kind of the definitive value of whatever is in the text input and I I also happen to know that we can Use just the simple a list value To get at it Every time We update anything in the text area It's immediately reflected in that text, but now so my rough outline for this talk is to create a little Twitter time Right, so we can we can change this to be tweet And we can call this h Twitter Now We want whatever the button is we don't want this dynamic text to be updated all the time We want it to be updated only when the button is clicked Now if we go back and look In this file There's a function that does exactly that and it's called tag die It takes a dynamic in the event of B and it gives you back an event a which is whatever the dynamic was At the time that this be event fire. So the be is just completely discarded So we can say instead of value. This is a dynamic Value ti is a dynamic. We can say tag die It's not a monadic function. It's pure Oh Right no tweet yet. That's our initial value. Well, what happens if we want to not just oh, let's let's do something again So now we're always getting the last the last thing What happens if we want to have a whole list of all of our past, okay Oh Well, we'll take the cheesy way out Let's do that with me there We're simply wrapping it now we have to so this is gonna be a dying text because we're calling Matt dying and So the the argument to Matt dying. Let's go look at it It's like that map, right So it's a to be So this thing is a dynamic list Let's let's go to types in the chair on it just so it's clear We may have to take that off. I don't know scope type variable But we'll just leave it there for now. So when we're Matt dying over tweet, it's gonna take a function. Let's let's do list of string to question mark, right You have type post there Yeah I know yes, so he's Thoughtfully picked a trickier thing to do and it's tricky because this thing needs at least the way that the way that I am To worry was solving it in a reflex. You're gonna use a higher order FRP Which is something that not all FRP systems have L by belief is a particularly Like popular today FRP system that does not have a higher order FRP Matt dying Expects a pure value, but we're gonna give it a dynamic, right? Or we're gonna give it a monadic value because we're gonna take text is an M a unit and L also is an M unit So we're we're map dining and we're gonna get back an M unit The way to handle this is with a function called Well, actually there's two there's there's this function called dying and this function called widget hold Dying is more like the type signature. We need it takes a dynamic MA and just gives us back an M with the event Let's try using let's try using time because it's a little bit more straightforward So this is a list of a list of strings so for every string in here we want to map This function over it This will give us a list and then we're gonna need to can cap the list So let's go here to dynamic and search for what do you know and we can cat dying Let's see if this does what we want. We have a list of dynamics and it gives us just a dynamic back Assuming that they form a monoid. Yes Oh Right Dying operator is actually not the one that I usually use I usually use widget hold and The reason the widget hold is kind of nice because it's structured very similarly to hold dying Hold dying takes an initial value and an event and gives you back a dynamic and this thing takes an initial widget and an event of new widgets and Gives you back a dynamic of the value that the widget returns So this is the pattern that I usually find myself using in applications But they're both here and they're both usable Any questions I don't know about canvas SVG. I know is I believe there is There may be For SVG support you need namespaces, so so there is namespace support I know that we we recently got the ability to do SVG. Oh, I'll show you just a little eye candy Example and familiar with the Haskell diagrams package We can build the diagrams all of diagrams diagrams if you don't know is a pretty substantial package for doing Doing diagrams and kind of graphics and it lets you do some really cool things with a really small amount of code And it's got a whole bunch of high-level math going on under the hood and We're compiling all of that into JavaScript in order to render this picture right here, and then we've made it dynamic And attached a little slider that can change the order of the Hilbert diagram so the reason this is slow is because It's JavaScript code redrawing this whole entire Hilbert curve And it's okay when it's fat or when it's a small order But when you get up here to the end it takes a little bit longer But this is just I think a really a really nice cool example of So some ways you can pull together different pieces and create create some really cool things so It is Pretty much the fastest way that you can start playing with reflex today Actually building your own reflex applications. It's a little bit a little bit more work. Ryan has a repository called reflex platform that has a really nice getting started Thing and the read me here goes through a lot of things basically you clone it You see me and you run this try reflex script, and it will install everything that needs to be installed it may take a little while because it it uses the mix package manager to get all the dependencies and Most of the time they're cached. So it's just a download that it had typically And this this is a nice little on-ramp to getting started with your own project But that takes more more than just five minutes Each snippet you can play around with reflex right now any other questions