Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4f9afb0
Update fable metadata and standalone packages
sheridanchris Jun 23, 2024
34c9b55
Update README.md
sheridanchris Jun 24, 2024
e3a741f
Don't load F# files in the documentation loader
sheridanchris Jun 24, 2024
59e6c34
Update iframe command to only parse messages from a specific iframe.
sheridanchris Jun 24, 2024
7f0c9b6
Remove react-syntax-highlighter dependency
sheridanchris Jun 24, 2024
ac1d297
Rework the docs to use a single editor instance per markdown code block
sheridanchris Jun 24, 2024
37ae80e
Actually remove the .fsx file from documentation loading logic
sheridanchris Jun 24, 2024
f497b28
Small misc improvements
sheridanchris Jun 24, 2024
c807358
Remove F# files from table-of-contents.json
sheridanchris Jun 24, 2024
0051c73
Misc styling improvements
sheridanchris Jun 28, 2024
2c581da
Various improvements and rough playground implementation
sheridanchris Jul 11, 2024
9aae610
Add null check in iframe logic
sheridanchris Jul 11, 2024
4ee74fd
go back to a single worker per editor instance
sheridanchris Jul 11, 2024
6c84510
Misc changes
sheridanchris Aug 6, 2024
7b26dea
Update npm packages
sheridanchris Sep 22, 2024
68610e2
Many UI improvements
sheridanchris Sep 29, 2024
7851df1
Start styling the UI
sheridanchris Sep 29, 2024
9d463ae
Improve code block rendering
sheridanchris Sep 29, 2024
07a3ad2
Misc improvements to the output logs
sheridanchris Sep 29, 2024
e767e6d
a bit more styling
sheridanchris Sep 30, 2024
8908b63
start reworking the documentation
sheridanchris Sep 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
# F# Tour

A guided interactive tour of the F# language.

## Development

### Prerequisites
* .NET 8.0
* NodeJS (npm)

### Running the Application
```
dotnet fsi build.fsx -- -p Setup
npm start
```

## Inspirations
- [Fable REPL](https://github.com/fable-compiler/repl)
- [Gleam Language Tour](https://tour.gleam.run)
- Originally based on the [Gleam Language Tour](https://tour.gleam.run) and the [Kotlin Tour](https://kotlinlang.org/docs/kotlin-tour-welcome.html)
- The core logic for compiling F# in the browser is based on the work done in the [Fable REPL](https://github.com/fable-compiler/repl).
16 changes: 3 additions & 13 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,13 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>F# Tour</title>
<link rel="stylesheet" href="css/pico.min.css" />
<link rel="icon" type="image/x-icon" href="img/favicon.ico">
<style>
html,
#app {
height: 100%;
}


body {
height: calc(100% - 1em);
}
</style>
<link rel="stylesheet" href="styles.css" />
<script src="https://kit.fontawesome.com/6d3af4481a.js" crossorigin="anonymous"></script>
</head>

<body>
<div id="app" class="container-fluid"></div>
<div id="app"></div>
<script src="./dist/App.js" type="module"></script>
</body>

Expand Down
1,017 changes: 414 additions & 603 deletions package-lock.json

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@
"bundle": "dotnet fable src/App --outDir dist/ --run vite build"
},
"dependencies": {
"@fable-org/fable-metadata": "^1.0.0",
"@fable-org/fable-standalone": "^1.1.0",
"@fable-org/fable-metadata": "^1.1.0",
"@fable-org/fable-standalone": "^1.9.0",
"@monaco-editor/react": "^4.6.0",
"lz-string": "^1.5.0",
"monaco-editor": "^0.46.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-markdown": "^8.0.4",
"react-syntax-highlighter": "^15.5.0",
"react-toastify": "^9.1.3",
"use-sync-external-store": "^1.2.0"
},
"devDependencies": {
"@vitejs/plugin-react": "^4.2.1",
"vite": "^5.0.12"
"@vitejs/plugin-react": "^4.3.1",
"vite": "^5.3.3"
}
}
}
4 changes: 0 additions & 4 deletions public/css/pico.min.css

This file was deleted.

9 changes: 0 additions & 9 deletions public/documentation/basics/conditional-expressions.fsx

This file was deleted.

2 changes: 2 additions & 0 deletions public/documentation/basics/conditional-expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ let fizzBuzz =
elif number % 5 = 0 then "Buzz"
elif number % 3 = 0 then "Fizz"
else string number

printfn "%s" fizzBuzz
```
5 changes: 0 additions & 5 deletions public/documentation/basics/expressions.fsx

This file was deleted.

13 changes: 5 additions & 8 deletions public/documentation/basics/expressions.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Expressions

The primary piece of F# syntax is an expression. An expression is simply, a block of code that when evaluated, produces a value.
The most fundamental construct in F# is an expression. An expression is a block of code that produces a value when evaluated.

_Let bindings_ allow you to bind the result of an expression to a name.

Expand Down Expand Up @@ -34,14 +34,11 @@ let ten = 10

The advantage of top-down evaluation is that the flow of your application's code is easier to reason about. Code is read and evaluated from top to bottom sequentially, from a higher to a lower level, from core components to specific implementation details. We can clearly understand and reason about our dependent modules, types, functions and their dependencies.

This top-down evaluation also applies to the ordering of files within a project. You can only use functions, types, and modules defined in other files if the file is ordered above the current definition.
This top-down evaluation also applies to the ordering of files within a project. You can only use functions, types, and modules defined in other files if the file is ordered above the current definition. Assuming you define a project with the structure of:
1. Logic.fs
2. Program.fs

```
1. Logic.fs
2. Program.fs
```

Here, any code in `Program.fs` can access modules, types, functions, and bindings in `Logic.fs`, but not the other way around. This is because `Logic.fs` is ordered above `Program.fs`.
Any code in `Program.fs` can access modules, types, functions, and bindings in `Logic.fs`, but not the other way around. This is because `Logic.fs` is ordered above `Program.fs`.

F# relies on the level of indentation to determine the beginning and end of an expression. You may be familiar with this if you've programmed in languages with syntatic indentation before. When writing an expression block, the level of indentation must be consistent for each expression within that block.

Expand Down
1 change: 0 additions & 1 deletion public/documentation/basics/hello-world.fsx

This file was deleted.

6 changes: 5 additions & 1 deletion public/documentation/basics/hello-world.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Here is a program that prints out the text `"Hello, World!"`.

```fsharp
printfn "Hello, World!"
```

In a normal F# program, this would be executed by using the command `dotnet run` on the command line.

Try changing the text being printed to `"Hello!"` and click the `Run` button at the top right to see what happens.
Try changing the text being printed and click the `Compile` button to see what happens!
17 changes: 0 additions & 17 deletions public/documentation/basics/operators.fsx

This file was deleted.

10 changes: 0 additions & 10 deletions public/documentation/basics/patterns-and-match-expressions.fsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Pattern matching allows you to match a value against patterns, which act as rule

To demonstrate pattern matching, let's get started with a pattern you're already familiar with: the _variable_ pattern. This pattern allows you to bind a value to a name like so: `let five = 5`. That's right, you've been using the variable pattern the whole time! Just like how everything on the right-hand side of the equals sign in a binding is an expression, the left-hand side is always a pattern.

```fsharp
```
let <pattern> = <expression>
```

Expand All @@ -16,6 +16,8 @@ let result =
match number with
| 10 -> "The number is Ten"
| number -> $"The number is not ten, but instead: {number}"

printfn "%s" result
```

Here you can see two patterns in action: the _constant_ and _variable_ patterns. The _constant_ pattern will match a value against a constant value like `10` or `"Hello, World!"`. This match expression is exhaustive as the last branch utilizes the _variable_ pattern which will always match against the value.
Expand All @@ -34,16 +36,20 @@ A branch in a match expression can also include a conditional expression. This i

```fsharp
let number = 10

let result =
match number with
| number when number % 2 = 0 -> $"{number} is even"
| number -> $"{number} is odd"

printfn "%s" result
```

Two patterns can lead to the same expression being evaluated using the _OR_ pattern.

```fsharp
let number = 10

let result =
match number with
| pattern1
Expand Down
6 changes: 0 additions & 6 deletions public/documentation/basics/primitive-types.fsx

This file was deleted.

12 changes: 6 additions & 6 deletions public/documentation/basics/primitive-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ What do these primitive types represent?
- `unit`, when passed to a function, means that function has no arguments. When returned from a function, it indicates that the function has no useful return value. Often used when a function e.g. prints to the screen and does nothing else.

```fsharp
10 // int
10.0 // float
'a' // char
"Hello, World!" // string
true // bool
() // unit
let intValue: int = 10
let floatValue: float = 10.0
let charValue: char = 'a'
let stringValue: string = "Hello, World!"
let boolValue: bool = true
let unitValue: unit = ()
```
3 changes: 0 additions & 3 deletions public/documentation/basics/string-formatting.fsx

This file was deleted.

9 changes: 5 additions & 4 deletions public/documentation/basics/string-formatting.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ String formatting is the process of integrating additional values into string li

```fsharp
let name = "John Doe"
sprintf "Your name is %s" name // "Your name is John Doe"
let nameDescription = sprintf "Your name is %s" name
printfn "%s" nameDescription
```

Here, we specify that the string format contains a single string value, indicated by the `%s` format specifier.
Expand All @@ -26,12 +27,12 @@ Another method is to use interpolated strings which allow you to bake the values

```fsharp
let name = "John Doe"
$"Your name is {name}" // "Your name is John Doe"
printfn $"Your name is {name}"
```

These interpolated strings can also be type checked by providing a format before the template. This will result in a compiler error if the type of the value doesn't match the format specifier.

```fsharp
$"Your name is %s{name}" // this works.
$"Your name is %b{name}" // compiler error. %b = boolean
printfn $"Your name is %s{name}" // this works.
printfn $"Your name is %b{name}" // compiler error. %b = boolean
```
6 changes: 0 additions & 6 deletions public/documentation/data-and-types/abbreviations.fsx

This file was deleted.

2 changes: 2 additions & 0 deletions public/documentation/data-and-types/abbreviations.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ type Logger = string -> unit
Because the `Logger` type is just an abbreviation for the function signature `string -> unit` you can use the two interchangeably.

```fsharp
type Logger = string -> unit

let exclaim (logger: Logger) (value: string) = logger (sprintf "%s!!!" value)

let logger: Logger = printfn "%s"
Expand Down
11 changes: 0 additions & 11 deletions public/documentation/data-and-types/discriminated-unions.fsx

This file was deleted.

46 changes: 42 additions & 4 deletions public/documentation/data-and-types/discriminated-unions.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,57 @@ type Color =
| Red
| Green
| Blue
| RGB of int * int * int
| Rgb of int * int * int
```

The discriminated union defined above has four cases: `Red`, `Green`, `Blue`, and `Rgb`.
Only the `RGB` case has data associated with it. You can construct instances of these cases using the identifier and any data.

```fsharp
type Color =
| Red
| Green
| Blue
| Rgb of int * int * int

let red = Red
let black = RGB (0, 0, 0)
let black = Rgb (0, 0, 0)
printfn "%A" black
```

The case constructor for the `RGB` case is a function with the signature of `int * int * int -> Color`.

```fsharp
let rgb: int * int * int -> Color = RGB
type Color =
| Red
| Green
| Blue
| Rgb of int * int * int

let rgb: int * int * int -> Color = Rgb
let color: Color = rgb (255, 255, 255)
printfn "%A" color
```

You can match against the cases of a discriminated union by using the _identifier_ pattern. The _identifier_ pattern allows you to match against the case by its identifier and additionally, supply a pattern for any data associated with it.

```fsharp
type Color =
| Red
| Green
| Blue
| Rgb of int * int * int

let rgb color =
match color with
| Red -> 255, 0, 0
| Green -> 0, 255, 0
| Blue -> 0, 0, 255
| RGB (r, g, b) -> r, g, b
| Rgb (r, g, b) -> r, g, b

let color = Red
let (r, g, b) = rgb color
printfn "R: %d, G: %d, B: %d" r g b
```

When dealing with a case that has data in the form of a tuple, it can be difficult to discern which tuple value corresponds to which piece of the data. In these cases, it is good practice to include labels on tuple elements like so:
Expand All @@ -48,4 +70,20 @@ type Color =
| Rgb of r: int * g: int * b: int

let color = Rgb (r = 255, g = 255, b = 255)
printfn "%A" color
```

Another common option is to use a record for a union case with multiple fields.

```fsharp
type RgbColor = { R: int; G: int; B: int }

type Color =
| Red
| Green
| Blue
| Rgb of RgbColor

let color = Rgb { R = 255; G = 255; B = 255 }
printfn "%A" color
```
3 changes: 0 additions & 3 deletions public/documentation/data-and-types/generic-types.fsx

This file was deleted.

Loading