247 lines
7.8 KiB
Markdown
247 lines
7.8 KiB
Markdown
|
# thunderstrike.ai intern resources
|
||
|
|
||
|
## contents
|
||
|
* [rust](#rust)
|
||
|
* [in brief](#rust-in-brief)
|
||
|
* [purescript](#purescript)
|
||
|
* [in brief](#purescript-in-brief)
|
||
|
* [example - frontend app](#purescript-example-frontend-app)
|
||
|
* [optional exercise](#exercise)
|
||
|
* [setup](#exercise-setup)
|
||
|
* [task](#exercise-task)
|
||
|
* [further reading](#further-reading)
|
||
|
|
||
|
## rust
|
||
|
**Rust** is a strongly-typed <a href="https://en.wikipedia.org/wiki/Type_safety"><sup>[type safety]</sup></a>
|
||
|
systems programming language <a href="https://en.wikipedia.org/wiki/System_programming_language"><sup>[systems programming language]</sup></a>.
|
||
|
|
||
|
### Rust in brief
|
||
|
<ul>
|
||
|
<li>Error handling is done with a special type that represents "the `Result` of this may be an error"</li>
|
||
|
<li>Null values are represented by special type that represents "this value is `Option`al"</li>
|
||
|
<li>Rust programs are incredibly fast and predictable</li>
|
||
|
</ul>
|
||
|
|
||
|
## purescript
|
||
|
**Purescript** is a strongly-typed <a href="https://en.wikipedia.org/wiki/Type_safety"><sup>[type safety]</sup></a>
|
||
|
purely functional <a href="https://en.wikipedia.org/wiki/Purely_functional_programming"><sup>[purely functional]</sup></a>
|
||
|
programming language that compiles to javascript (like typescript).
|
||
|
|
||
|
### Purescript in brief
|
||
|
<ul>
|
||
|
<li>Error handling is done with a special type that represents "`Either` it succeeded or failed"</li>
|
||
|
<li>Null values are represented by special type that represents "`Maybe` it's present or not"</li>
|
||
|
<li>
|
||
|
effectful code
|
||
|
<a href="https://en.wikipedia.org/wiki/Side_effect_(computer_science)"><sup>[side effect]</sup></a>
|
||
|
is isolated from non-effectful code. This makes programs much more consistent to run and reason about.
|
||
|
</li>
|
||
|
<li>everything is an expression</li>
|
||
|
<li>interacting with raw javascript is relatively painless</li>
|
||
|
</ul>
|
||
|
|
||
|
### Purescript Example - Frontend App
|
||
|
You don't have to understand exactly how these examples work,
|
||
|
I'm providing them simply for you to glance over and get a feeling
|
||
|
for reading typescript/javascript vs purescript.
|
||
|
|
||
|
This app:
|
||
|
1. renders `"Loading..."` until either data or error
|
||
|
1. fetches data from a server
|
||
|
1. if ok, render items in a list. if error, render error span at the bottom of the page.
|
||
|
|
||
|
<details>
|
||
|
<summary><b>React (click to expand)</b></summary>
|
||
|
|
||
|
```typescript
|
||
|
type Item = {id: string, title: string, description: string}
|
||
|
|
||
|
export const App: () => React.Node = () => {
|
||
|
const [items, setItems] = React.useState<Array<Item> | undefined>(undefined)
|
||
|
const [error, setError] = React.useState<Error | undefined>(undefined)
|
||
|
|
||
|
React.useEffect(() => {
|
||
|
fetch('/api/item')
|
||
|
.then(rep => rep.json<Array<Item>>())
|
||
|
.then(items => setItems(items))
|
||
|
.catch(e => setError(e))
|
||
|
}, [])
|
||
|
|
||
|
return error !== undefined
|
||
|
? (<p class="error">{error.message}</p>)
|
||
|
: items === undefined
|
||
|
? (<p>Loading...</p>)
|
||
|
: items.map(item => {
|
||
|
return (
|
||
|
<div key={item.id}>
|
||
|
<p>{item.title}</p>
|
||
|
<span class="small">
|
||
|
{item.description}
|
||
|
</span>
|
||
|
</div>
|
||
|
)
|
||
|
})
|
||
|
}
|
||
|
```
|
||
|
|
||
|
</details>
|
||
|
|
||
|
<details>
|
||
|
<summary><b>Purescript Halogen (click to expand)</b></summary>
|
||
|
|
||
|
```haskell
|
||
|
type Item = { id :: String, title :: String, description :: String }
|
||
|
|
||
|
data State
|
||
|
= StateEmpty
|
||
|
| StateErrored Error
|
||
|
| StateGotItems (Array Item)
|
||
|
|
||
|
data Action = ActionInit
|
||
|
|
||
|
renderItem item = div [] [ p [] [text item.title]
|
||
|
, span
|
||
|
[className "small"]
|
||
|
[text item.description]
|
||
|
]
|
||
|
|
||
|
renderApp StateEmpty = p [] [text "Loading..."]
|
||
|
renderApp (StateErrored e) = p [className "error"] [text (message e)]
|
||
|
renderApp (StateGotItems items) = map renderItem items
|
||
|
|
||
|
action ActionInit = do
|
||
|
response <- fetch (URL "/api/item") {method: Get}
|
||
|
jsonString <- text response
|
||
|
itemsOrError <- readJSON jsonString
|
||
|
case itemsOrError of
|
||
|
Right items -> put (StateGotItems items)
|
||
|
Left error -> put (StateErrored error)
|
||
|
|
||
|
app = mkComponent
|
||
|
{ initialState: StateEmpty
|
||
|
, render: renderApp
|
||
|
, eval: mkEval ( defaultEval { handleAction = action, initialize: Just ActionInit } )
|
||
|
}
|
||
|
```
|
||
|
|
||
|
</details>
|
||
|
|
||
|
## Exercise
|
||
|
This is an optional code exercise for you to use if you have extra
|
||
|
time and would like a somewhat guided foray into one or both of the languages
|
||
|
mentioned here.
|
||
|
|
||
|
### Exercise - Setup
|
||
|
#### Windows
|
||
|
This guide assumes you are using linux or macos.
|
||
|
On windows, install an ubuntu virtual machine on WSL2 using this guide: https://learn.microsoft.com/en-us/windows/wsl/install
|
||
|
|
||
|
After installing, run the following:
|
||
|
```sh
|
||
|
apt-get update -y
|
||
|
apt-get upgrade -y
|
||
|
apt-get install -y wget curl git openssl zsh
|
||
|
```
|
||
|
|
||
|
If using Visual Studio Code, this guide will help you configure VSCode to run in WSL instead of Windows: https://learn.microsoft.com/en-us/windows/wsl/tutorials/wsl-vscode
|
||
|
|
||
|
#### VSCode
|
||
|
* [rust](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)
|
||
|
* [purescript](https://marketplace.visualstudio.com/items?itemName=nwolverson.ide-purescript)
|
||
|
|
||
|
#### asdf
|
||
|
For tooling, I recommend using [asdf](asdf-vm.com)
|
||
|
|
||
|
```sh
|
||
|
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.13.1
|
||
|
echo 'source "$HOME/.asdf/asdf.sh"' >> ~/.bashrc
|
||
|
echo 'source "$HOME/.asdf/completions/asdf.bash"' >> ~/.bashrc
|
||
|
echo '[ -s "~/.bun/_bun" ] && source "~/.bun/_bun"' >> ~/.bashrc
|
||
|
echo 'export BUN_INSTALL="~/.bun"' >> ~/.bashrc
|
||
|
echo 'export PATH=$PATH:$HOME/.bun/bin' >> ~/.bashrc
|
||
|
|
||
|
asdf plugin add rust
|
||
|
asdf plugin add bun
|
||
|
asdf plugin add purescript
|
||
|
|
||
|
asdf install rust latest
|
||
|
asdf install bun latest
|
||
|
asdf install purescript latest
|
||
|
|
||
|
asdf global rust latest
|
||
|
asdf global bun latest
|
||
|
asdf global purescript latest
|
||
|
|
||
|
bun install --global spago@next
|
||
|
|
||
|
cargo --version
|
||
|
echo -n "bun " && bun --version
|
||
|
echo -n "purescript " && purs --version
|
||
|
echo -n "spago " && spago --version
|
||
|
# cargo 1.70.0
|
||
|
# bun 1.0.3
|
||
|
# purescript 0.15.11-3
|
||
|
# spago 0.93.14
|
||
|
```
|
||
|
|
||
|
#### Clone this repo
|
||
|
```sh
|
||
|
git clone https://git.orionkindel.com/orion/intern-resources.git
|
||
|
|
||
|
cd intern-resources/example-rs
|
||
|
cargo build
|
||
|
cargo run
|
||
|
|
||
|
cd ../example-purs
|
||
|
spago build
|
||
|
spago run
|
||
|
```
|
||
|
|
||
|
### Exercise - Task
|
||
|
In either purescript or rust, write a program that operates on CSV data and transforms it into JSON.
|
||
|
|
||
|
#### Purescript Instructions
|
||
|
* use the provided template `./exercise-purs/`
|
||
|
* use the provided CSV parser `./exercise-purs/src/Data.CSV.purs`
|
||
|
* modify `./exercise-purs/src/Main.purs` to read a csv file and print it as JSON to the terminal
|
||
|
|
||
|
_hints:_
|
||
|
* [`Node.FS.Sync.readFile`](https://pursuit.purescript.org/packages/purescript-node-fs/9.1.0/docs/Node.FS.Sync#v:readFile)
|
||
|
* [`Simple.JSON.writeJSON`](https://pursuit.purescript.org/packages/purescript-simple-json/9.0.0/docs/Simple.JSON#v:writeJSON)
|
||
|
|
||
|
#### Rust Instructions
|
||
|
* use the provided template `./exercise-rs/`
|
||
|
* use the [`csv`](https://docs.rs/csv/latest/csv/) crate to parse csvs
|
||
|
* modify `./exercise-rs/src/main.rs` to read a csv file and print it as JSON to the terminal
|
||
|
|
||
|
_hints:_
|
||
|
* [`csv`](https://docs.rs/csv/latest/csv/)
|
||
|
* [`serde_json`](https://docs.rs/csv/latest/serde-json/)
|
||
|
|
||
|
**Example**
|
||
|
The input
|
||
|
```csv
|
||
|
Title,Salary,Name
|
||
|
CEO,100000,Jack
|
||
|
CTO,100000,Bryan
|
||
|
Engineer,80000,Jennifer
|
||
|
```
|
||
|
|
||
|
Should output
|
||
|
```json
|
||
|
[
|
||
|
{"Title": "CEO", "Salary": "100000", "Name": "Jack"},
|
||
|
{"Title": "CTO", "Salary": "100000", "Name": "Bryan"},
|
||
|
{"Title": "Engineer", "Salary": "80000", "Name": "Jennifer"},
|
||
|
]
|
||
|
```
|
||
|
|
||
|
## Further reading
|
||
|
* [purescript website](https://www.purescript.org/)
|
||
|
* [purescript by example (free online book)](https://book.purescript.org/)
|
||
|
* [purescript in depth (free online book)](https://leanpub.com/purescript/read)
|
||
|
* [purescript halogen docs](https://purescript-halogen.github.io/purescript-halogen/)
|
||
|
* [purescript halogen implementation of the realworld project](https://github.com/thomashoneyman/purescript-halogen-realworld)
|
||
|
* [rust website](https://www.rust-lang.org/)
|
||
|
* [rust book (free online book)](https://doc.rust-lang.org/book/)
|