This commit is contained in:
orion 2023-10-06 19:36:55 -05:00
parent 9169968d89
commit 36a993eb96
Signed by: orion
GPG Key ID: 6D4165AE4C928719
8 changed files with 277 additions and 3 deletions

12
exercise-purs/.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
bower_components/
node_modules/
.pulp-cache/
output/
output-es/
generated-docs/
.psc-package/
.psc*
.purs*
.psa*
.spago

16
exercise-purs/spago.yaml Normal file
View File

@ -0,0 +1,16 @@
package:
dependencies:
- arrays
- console
- effect
- ordered-collections
- parsing
- prelude
name: foo
test:
dependencies: []
main: Test.Main
workspace:
extra_packages: {}
package_set:
registry: 42.2.1

View File

@ -0,0 +1,89 @@
module Data.CSV where
import Prelude hiding (between)
import Control.Alt ((<|>))
import Data.Array (some)
import Data.Either (Either)
import Data.Foldable (all)
import Data.List (List(..))
import Data.List.NonEmpty (NonEmptyList, zip)
import Data.Map as M
import Data.String.CodeUnits (fromCharArray, toCharArray, singleton)
import Parsing (ParseError, Parser, runParser)
import Parsing.Combinators (sepEndBy, sepBy1, between)
import Parsing.String (eof, satisfy, string)
type P a = Parser String a
type Parsers a =
{
quoted :: (P a -> P a),
chars :: P String,
qchars :: P String,
field :: P String,
row :: P (NonEmptyList String),
file :: P (List (NonEmptyList String)),
fileHeaded :: P (List (M.Map String String))
}
makeQuoted :: forall a. String -> (P a -> P a)
makeQuoted q = between (string q) (string q)
makeChars :: String -> P String
makeChars xs = do
fromCharArray <$> some char
where
char = satisfy $ excluded xs
excluded ys = \x -> all identity $ terms ys <*> [x]
terms ys = map (/=) $ toCharArray ys
makeQchars :: Char -> P String
makeQchars c = fromCharArray <$> some (qchar <|> escapedQuote)
where
escapedQuote :: P Char
escapedQuote = (string $ (singleton c <> singleton c)) $> c
qchar = satisfy (\c' -> c' /= c)
makeField :: (P String -> P String) -> P String -> P String -> P String
makeField qoutes qoutedChars purechars = qoutes qoutedChars <|> purechars <|> string ""
makeRow :: String -> P String -> P (NonEmptyList String)
makeRow s f = f `sepBy1` string s
makeFile :: String -> P (NonEmptyList String) -> P (List (NonEmptyList String))
makeFile s r = r `sepEndBy` string s <* eof
makeFileHeaded :: P (List (NonEmptyList String)) -> P (List (M.Map String String))
makeFileHeaded file = do
f <- file
pure $ case f of
Nil -> Nil
Cons header rows -> mkRow header <$> rows
where
mkRow header row' = M.fromFoldable $ zip header row'
makeParsers :: Char -> String -> String -> Parsers String
makeParsers quote seperator eol = do
let quoted' = makeQuoted $ singleton quote
let chars' = makeChars $ (singleton quote) <> seperator <> eol
let qchars' = makeQchars quote
let field' = makeField quoted' qchars' chars'
let row' = makeRow seperator field'
let file' = makeFile eol row'
let fileHeaded' = makeFileHeaded file'
{
quoted: quoted',
chars: chars',
qchars: qchars',
field: field',
row: row',
file: file',
fileHeaded: fileHeaded'
}
defaultParsers :: Parsers String
defaultParsers = makeParsers '"' "," "\n"
parse :: String -> Either ParseError (List (NonEmptyList String))
parse = flip runParser $ defaultParsers.file

View File

@ -0,0 +1,11 @@
module Main where
import Prelude
import Effect (Effect)
import Effect.Console (log)
main :: Effect Unit
main = do
log "🍝"

View File

@ -0,0 +1,12 @@
module Test.Main where
import Prelude
import Effect (Effect)
import Effect.Class.Console (log)
main :: Effect Unit
main = do
log "🍕"
log "You should add some tests."

8
exercise-rs/Cargo.toml Normal file
View File

@ -0,0 +1,8 @@
[package]
name = "exercise-rs"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

3
exercise-rs/src/main.rs Normal file
View File

@ -0,0 +1,3 @@
fn main() {
println!("Hello, world!");
}

129
readme.md
View File

@ -1,10 +1,21 @@
# 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>.
### In brief
### 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>
@ -16,7 +27,7 @@ systems programming language <a href="https://en.wikipedia.org/wiki/System_progr
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).
### In brief
### 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>
@ -29,7 +40,7 @@ programming language that compiles to javascript (like typescript).
<li>interacting with raw javascript is relatively painless</li>
</ul>
### Motivating example: React vs Halogen
### 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.
@ -115,9 +126,121 @@ app = mkComponent
</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/)