intern-resources/exercise.md

7.8 KiB

thunderstrike.ai intern resources

contents

rust

Rust is a strongly-typed [type safety] systems programming language [systems programming language].

Rust in brief

  • Error handling is done with a special type that represents "the `Result` of this may be an error"
  • Null values are represented by special type that represents "this value is `Option`al"
  • Rust programs are incredibly fast and predictable

purescript

Purescript is a strongly-typed [type safety] purely functional [purely functional] programming language that compiles to javascript (like typescript).

Purescript in brief

  • Error handling is done with a special type that represents "`Either` it succeeded or failed"
  • Null values are represented by special type that represents "`Maybe` it's present or not"
  • effectful code [side effect] is isolated from non-effectful code. This makes programs much more consistent to run and reason about.
  • everything is an expression
  • interacting with raw javascript is relatively painless

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
  2. fetches data from a server
  3. if ok, render items in a list. if error, render error span at the bottom of the page.
React (click to expand)
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>
        )
      })
}
Purescript Halogen (click to expand)
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 } )
  }

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:

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

asdf

For tooling, I recommend using asdf

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

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:

Rust Instructions

  • use the provided template ./exercise-rs/
  • use the 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:

Example The input

Title,Salary,Name
CEO,100000,Jack
CTO,100000,Bryan
Engineer,80000,Jennifer

Should output

[
  {"Title": "CEO", "Salary": "100000", "Name": "Jack"},
  {"Title": "CTO", "Salary": "100000", "Name": "Bryan"},
  {"Title": "Engineer", "Salary": "80000", "Name": "Jennifer"},
]

Further reading