Skip to content

Commit a3f182c

Browse files
author
Jonas Juselius
committed
Add pre-generated html
1 parent 038b01b commit a3f182c

File tree

2 files changed

+678
-0
lines changed

2 files changed

+678
-0
lines changed

slides/elmish.html

+374
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,374 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>F#</title>
5+
<meta charset="utf-8">
6+
<style>
7+
@import url(https://fonts.googleapis.com/css?family=Yanone+Kaffeesatz);
8+
@import url(https://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic);
9+
@import url(https://fonts.googleapis.com/css?family=Ubuntu+Mono:400,700,400italic);
10+
11+
body { font-family: 'Droid Serif'; }
12+
h1, h2, h3 {
13+
font-family: 'Yanone Kaffeesatz';
14+
font-weight: normal;
15+
}
16+
.remark-code, .remark-inline-code { font-family: 'Ubuntu Mono'; }
17+
.remark-slide-content h1 { font-size: 3em; }
18+
.remark-slide-content h2 { font-size: 2em; }
19+
.remark-slide-content h3 { font-size: 1.6em; }
20+
.remark-slide-content { background-size: cover; }
21+
.footnote {
22+
position: absolute;
23+
bottom: 3em;
24+
}
25+
li p { line-height: 1.25em; }
26+
.red { color: #fa0000; }
27+
.large { font-size: 2em; }
28+
a, a > code {
29+
color: rgb(249, 38, 114);
30+
text-decoration: none;
31+
}
32+
code {
33+
background: #e7e8e2;
34+
border-radius: 5px;
35+
}
36+
.remark-code, .remark-inline-code { font-family: 'Ubuntu Mono'; }
37+
.remark-code-line-highlighted { background-color: #373832; }
38+
.pull-left {
39+
float: left;
40+
width: 47%;
41+
}
42+
.pull-right {
43+
float: right;
44+
width: 47%;
45+
}
46+
.pull-right ~ p {
47+
clear: both;
48+
}
49+
#slideshow .slide .content code {
50+
font-size: 0.8em;
51+
}
52+
#slideshow .slide .content pre code {
53+
font-size: 0.9em;
54+
padding: 15px;
55+
}
56+
.inverse {
57+
background: #272822;
58+
color: #777872;
59+
text-shadow: 0 0 20px #333;
60+
}
61+
.inverse h1, .inverse h2 {
62+
color: #f3f3f3;
63+
line-height: 0.8em;
64+
}
65+
/* Slide-specific styling */
66+
#slide-inverse .footnote {
67+
bottom: 12px;
68+
left: 20px;
69+
}
70+
#slide-how .slides {
71+
font-size: 0.9em;
72+
position: absolute;
73+
top: 151px;
74+
right: 140px;
75+
}
76+
#slide-how .slides h3 {
77+
margin-top: 0.2em;
78+
}
79+
#slide-how .slides .first, #slide-how .slides .second {
80+
padding: 1px 20px;
81+
height: 90px;
82+
width: 120px;
83+
-moz-box-shadow: 0 0 10px #777;
84+
-webkit-box-shadow: 0 0 10px #777;
85+
box-shadow: 0 0 10px #777;
86+
}
87+
#slide-how .slides .first {
88+
background: #fff;
89+
position: absolute;
90+
top: 20%;
91+
left: 20%;
92+
z-index: 1;
93+
}
94+
#slide-how .slides .second {
95+
position: relative;
96+
background: #fff;
97+
z-index: 0;
98+
}
99+
100+
/* Two-column layout */
101+
.left-column {
102+
color: #777;
103+
width: 20%;
104+
height: 92%;
105+
float: left;
106+
}
107+
.left-column h2:last-of-type, .left-column h3:last-child {
108+
color: #000;
109+
}
110+
.right-column {
111+
width: 75%;
112+
float: right;
113+
padding-top: 1em;
114+
}
115+
img[alt=img150] { width: 150px; }
116+
img[alt=img750] { width: 750px; }
117+
img[alt=img550] { width: 550px; }
118+
</style>
119+
</head>
120+
<body>
121+
<textarea id="source">
122+
123+
name: inverse
124+
layout: true
125+
class: center, middle, inverse
126+
---
127+
# Reactive programming with F# and Fable Elmish
128+
## <jonas.juselius@itpartner.no>
129+
### https://github.com/juselius
130+
### https://twitter.com/copointfree
131+
132+
---
133+
layout: false
134+
## Compiling F# to JavaScript
135+
.left-column[
136+
## Fable
137+
.left[![img150](./fable.png)]
138+
]
139+
.right-column[
140+
* [Fable](http://fable.io) is an F# to JavaScript compiler powered by Babel.
141+
* It's designed to produce readable and standard code.
142+
* Fable brings all the power of F# to the JavaScript ecosystem.
143+
* Static typing with type inference
144+
* Exhaustive pattern matching
145+
* Immutability by default
146+
* Structural equality or units of measure
147+
* And much more
148+
]
149+
150+
---
151+
## .NET Core templates
152+
.left-column[
153+
## Fable
154+
### About
155+
### Fable.Template
156+
]
157+
.right-column[
158+
Scaffold a simple Fable SPA:
159+
```sh
160+
dotnet new -i fable.template
161+
dotnet new fable -n FableApp -o FableApp
162+
cd FableApp
163+
.paket/paket.exe install
164+
yarn install
165+
yarn run start
166+
```
167+
(currently broken for Fable 2.0)
168+
]
169+
170+
---
171+
## .NET Core templates
172+
.left-column[
173+
## Fable
174+
### About
175+
### Fable.Template
176+
### SAFE.Template
177+
]
178+
.right-column[
179+
180+
Scaffold a client-server application using the SAFE template:
181+
182+
```sh
183+
dotnet new -i safe.template
184+
dotnet new safe -n SafeApp -o SafeApp -c remoting -d docker
185+
cd SafeApp
186+
.paket/paket.exe install
187+
yarn install
188+
cd Server; dotnet run
189+
cd src/Client
190+
dotnet restore
191+
dotnet fable webpack-dev-server -- \
192+
--config src/Client/webpack.config.js
193+
```
194+
]
195+
196+
---
197+
## The Elm architecture
198+
199+
* The Model-View-Update (MVU) architecture is a simple way to create reactive
200+
applications
201+
* First invented and popularized by Elm (Evan Czaplicki)
202+
* No explicit *mutable state*
203+
* **Everything** happens through *messages* and *commands*
204+
* Related to the *actor model*
205+
* Excellent fit for functional programming
206+
* Fable.Elmish is 251 lines of code in total
207+
208+
---
209+
## Model-View-Update
210+
.center[![img550](model-view-update.png)]
211+
212+
---
213+
## Model-View-Update-Command
214+
.center[![img750](model-view-update-commands.png)]
215+
216+
---
217+
## Model-View-Update-Command-Subscription
218+
.center[![img750](model-view-update-command-subscription.png)]
219+
220+
---
221+
## Elmish implementation
222+
```fsharp
223+
let runWith (arg: 'arg) (program: Program<'arg, 'model, 'msg, 'view>) =
224+
let (model,cmd) = program.init arg
225+
let inbox = MailboxProcessor.Start(fun (mb:MailboxProcessor<'msg>) ->
226+
let rec loop (state:'model) =
227+
async {
228+
let! msg = mb.Receive()
229+
let newState =
230+
try
231+
let (model',cmd') = program.update msg state
232+
program.setState model' mb.Post
233+
cmd' |> Cmd.exec mb.Post
234+
model'
235+
with ex ->
236+
program.onError ("Unable to process a message:", ex)
237+
state
238+
return! loop newState
239+
}
240+
loop model
241+
)
242+
program.setState model inbox.Post
243+
let sub =
244+
try
245+
program.subscribe model
246+
with ex ->
247+
program.onError ("Unable to subscribe:", ex)
248+
Cmd.none
249+
250+
```
251+
252+
---
253+
.left-column[
254+
## Combinators
255+
]
256+
.right-column[
257+
* The word *combinator* is used for functions which are designed to be combined
258+
in various flexible ways
259+
* (In lambda calculus it's a function with no *free* variables)
260+
* Often used to create *embedded domain specific languages* (EDSL)
261+
* Examples are: HTML and parser combinators
262+
]
263+
264+
---
265+
.left-column[
266+
## Combinators
267+
### Elmish.React
268+
]
269+
.right-column[
270+
271+
The Elmish.React combinator library defines functions for *every* html tag, with
272+
the following signature:
273+
```fsharp
274+
val elem: seq<IHTMLProp> -> seq<ReactElement> -> ReactElement
275+
```
276+
277+
For example:
278+
```fsharp
279+
div [] [
280+
h1 [] [ str "Hello World!" ]
281+
p [] [
282+
ul [] [
283+
li [] [ str "foo" ]
284+
li [] [ str "bar" ]
285+
]
286+
]
287+
br [] []
288+
]
289+
```
290+
]
291+
292+
---
293+
.left-column[
294+
## Combinators
295+
### Elmish.React
296+
### Elmish.React.Props
297+
]
298+
.right-column[
299+
The Elmish.React.Props module contains combinators for html attributes:
300+
301+
```fsharp
302+
div [ Id "main" ] [
303+
h1 [ FontSize "30px" ] [ str "Hello World!" ]
304+
p [ Style [ CSSProp.BackgroundColor "green" ] ] [
305+
ul [] [
306+
li [ OnClick (fun ev -> console.log "foo") ]
307+
[ str "foo" ]
308+
li [] [ str "bar" ]
309+
]
310+
]
311+
]
312+
```
313+
]
314+
315+
---
316+
.left-column[
317+
## Combinators
318+
### Elmish.React
319+
### Elmish.React.Props
320+
### Fulma
321+
]
322+
.right-column[
323+
* Using HTML and CSS directly is quite low level and primitive, not to say
324+
inefficient
325+
* [Bootstrap](https://getbootstrap.com) is a popular high-level CSS framework
326+
* [Bulma](https://bulma.io) is another popular, modern CSS framework
327+
* [Fulma](https://mangelmaxime.github.io/Fulma/) is an EDSL built around Bulma.
328+
* Fulma provides higher-level html combinators:
329+
* Layout: Container, Columns, Title, Foooter
330+
* Elements: Box, Button, Content, Form, Table, Progress
331+
* Compoents: Breadcrumb, Card, Dropdown, Navbar, Modal, Panel, Tabs
332+
* And much more
333+
* Fulma and Elmish.React can be freely mixed, similar type signatures
334+
* Fulma has many submodules, with "internal" type signatures
335+
]
336+
337+
---
338+
.left-column[
339+
## Combinators
340+
### Elmish.React
341+
### Elmish.React.Props
342+
### Fulma
343+
### Fulma example
344+
]
345+
.right-column[
346+
```fsharp
347+
Panel.panel [] [
348+
Content.content [] [
349+
Button.button [
350+
Button.Color IsDanger
351+
Button.OnClick (fun _ -> console.log "hello")
352+
] [ str "Say hello" ]
353+
]
354+
]
355+
356+
```
357+
]
358+
359+
---
360+
## Odds and ends
361+
* Time-traveling debugger
362+
* Saturn
363+
* Cordova
364+
* React Native
365+
366+
367+
</textarea>
368+
<script src="https://remarkjs.com/downloads/remark-latest.min.js">
369+
</script>
370+
<script>
371+
var slideshow = remark.create();
372+
</script>
373+
</body>
374+
</html>

0 commit comments

Comments
 (0)