doc
This commit is contained in:
parent
9169968d89
commit
36a993eb96
12
exercise-purs/.gitignore
vendored
Normal file
12
exercise-purs/.gitignore
vendored
Normal 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
16
exercise-purs/spago.yaml
Normal 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
|
89
exercise-purs/src/Data.CSV.purs
Normal file
89
exercise-purs/src/Data.CSV.purs
Normal 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
|
11
exercise-purs/src/Main.purs
Normal file
11
exercise-purs/src/Main.purs
Normal file
@ -0,0 +1,11 @@
|
||||
module Main where
|
||||
|
||||
import Prelude
|
||||
|
||||
import Effect (Effect)
|
||||
import Effect.Console (log)
|
||||
|
||||
main :: Effect Unit
|
||||
main = do
|
||||
log "🍝"
|
||||
|
12
exercise-purs/test/Test/Main.purs
Normal file
12
exercise-purs/test/Test/Main.purs
Normal 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
8
exercise-rs/Cargo.toml
Normal 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
3
exercise-rs/src/main.rs
Normal file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
129
readme.md
129
readme.md
@ -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/)
|
||||
|
Loading…
Reference in New Issue
Block a user