Age | Commit message (Collapse) | Author | Files | Lines |
|
I've been doing a few take-home assessment recently, all of which I've attempted
to solve using Haskell. I'm having a good time, and I'm noticing strong and weak
points with my Haskell programming. I always attempt to apply any feedback a
reviewer gives me, and I'm storing my first drafts, second attempts, and
feedback here for now.
This recently attempt was for a role at Jane Street.
|
|
Ideally I'd use exa insted of ls, but I cannot seem to support that yet.
|
|
I believe `use_nix` looks for shell.nix and then default.nix files, so I was
wrong earlier when I said that I could get rid of shell.nix files altogether.
I need to learn more about `use_nix` and getting environments from default.nix
files.
|
|
Cleaning things up...
|
|
I find it bothersome to share the list of Haskell dependencies between my
default.nix and shell.nix files. A few days ago, I created a THIRD file,
shared.nix, that defined the shared code b/w default.nix and shell.nix. This
DRY'd things up, but it also added a new file, which I didn't like.
Today I learned that direnv integrates with Nix using a function called
`use_nix`. Voila! I typically already have .envrc files per-project, so this
doesn't add any unnecessary files, and it allows me to delete my shell.nix
files.
I would use `lorri`, except that I encountered issues using Lorri on my work
computer, which I'm not interested in attempting to resolve now.
|
|
Timing myself to see how long it takes me to publish a change.
|
|
Much better than manually running:
```shell
$ cd ~/briefcase && git pull --rebase origin master
$ nix-rebuild switch
$ nix-build -A zoo
$ pkill zoo
$ ./result/zoo &
$ job -l
$ disown %<job-number>
```
|
|
Proving to my girlfriend that the zoo works.
|
|
I'd like to filter logs from {blog,git,zoo}.wpcarro.dev, etc.
|
|
Problem: The JSON that Nginx outputs cannot be successfully parsed by
journaldriver because Nginx prefixes it with "socrates nginx:". Adding
`nohostname` to `access_log` should solve this problem.
I borrow this from @tazjin's most recent definition of `commonHttpConfig`.
|
|
Attempting to use @tazjin's delightful simple logging library!
|
|
I haven't used this since I wrote it... and now the .tokens attribute is missing
and it's screwing up my other deployment... *sigh*
|
|
Right now the 8000 port is hard-coded into the zoo server, which isn't ideal,
but "it works" (TM).
|
|
I'm still unsure whether or not this is a good idea, but experimenting is a good
way to find out!
|
|
TL;DR:
- Adds string-conversions library
- Adds tests for remaining units and repeating requests
- Adds a REPL in main
|
|
Parse inputs like -10s into 10 second shifts back in time.
|
|
Interact with Stripe's payment_intents API endpoint.
I'm not committing the index.html that contains client-side code that interacts
with the /create-payment-intent endpoint, but it contains sensitive information,
so I'm omitting it for now.
TL;DR:
- Define POST /create-payment-intent endpoint
- Include envStripeAPIKey in Context record
- Define a top-level Stripe module for making API calls
- Define types and instances that align with Stripes request and response types
- Depend on the Req library: a higher-level library than http-client
|
|
Today @tazjin told me about Emacs's built-in project.el library, which he
recommended that I extend to support monorepo-specific tooling. It worked like a
charm!
Now when I press "<leader>f", it will resolve to either the nearest file named
default.nix or directory name .git.
|
|
I don't rely on this often, so it's best to leave it as the top-level directory
for briefcase.
|
|
Missed documenting this the first time...
|
|
Use the newly defined `buildHaskell` function for a few of my existing Haskell
projects. So far, it works as intended!
|
|
Use Nix and Briefcase to easily create Haskell executables.
I'd eventually like to support something like: briefcase.buildHaskell.project
that let me define a few top-level values (e.g. ghcExtensions) and would give me
a ghci environment with the proper `.ghci` settings so that my development
environment mirrored my build environment... baby steps, though.
|
|
Small but useful alias.
|
|
Per the assignment's instructions, the `Shift n` operation should treat
the *entire keyboard* like a cycle and shift that. I was erroneously
treating *each row* like a cycle and shifting those one-by-one.
This change fixes that. In addition, it also:
- Updates README.md with expected inputs and outputs
- Updates test suite
- Adds `split` dependency to {default,shell}.nix
|
|
Tests:
- HorizontalFlip
- VerticalFlip
- Shift n
|
|
TL:DR:
- Remove unused imports: Test.QuickCheck and Control.Exception
- Remove calls to `reverse` and `Utils.rotate` with their results
|
|
TL;DR:
- include a default.nix to allow users to build an named executable
- emphasize in the README that the user needs Nix to build this project
- pin nixpkgs to a specific commit and fetch it from GitHub
|
|
Per my take-home assignment's reviewer's comments, with which for the record I
agree, I should generate the character->coordinate table from my existing qwerty
keyboard definition.
The best part is: by doing this I found a bug: Notice how the original '0'
character was mapped to the Coordinate (0,0)... thus every subsequent digit
key (i.e. the first row) is off-by-one.
|
|
After burning a few hours wrestling with the type system, I decided to revert to
the simpler `Server API` type instead of the `ServantT` transformer type.
The problem is that I couldn't write a MonadError instance for `RIO Context`,
which is my `AppM` (i.e. application monad). Using `throwIO` in the server
handlers results in 500 errors, which is not what I wanted. I'm still pretty
fuzzy about what's happening; I now know that exception handling in Haskell is
pretty gnaryly. I may revisit this at a later time when my knowledge is more
extensive. For now: time to fry bigger fish.
An easier abstract is for me to pass `T.Context` into `server` as an argument,
which after all is what a Reader does.
TL;DR:
- Read server, client ports from .envrc
- Define a top-level Failure type (empty for now)
- Define a top-level Success type
- Define App as RIO Context (Either Failure Success)
|
|
Long story -> short: I'd like to access my App monad from within my Servant
handlers.
While this code type-checks, I'm not sure it's working as intended. Needing to
change throwError to throwIO fails the "smell test". I expect to refactor this
code, but I'm calling it a night for now.
|
|
I believe RIO stands for: "ReaderT <something-something> IO", which is a nod to
the top-level application data type:
```haskell
-- This is a simplification
newtype RIO env a = RIO { runRIO :: ReaderT env a () }
```
I read about RIO from an FP-Complete blog post a few months ago, and now I'm
excited to try it out for a real project. Bon voyage!
|
|
I'm getting tired of:
```shell
$ cd <project-root>
$ nix-shell
$ cd src/server
$ ghci Main.hs
```
Instead:
```shell
$ cd <project-root>/src/server
$ ghci Main.hs
```
|
|
Defining a few tables in init.sql to sketch a few records that I need to
persist.
|
|
As the previous commit mentions, I'm attempting to build and deploy this project
with `nix-shell` and `nix-build` instead of `cabal` and `stack`.
I'm in the Hamburg airport right now, and my internet connection isn't stable
enough to test this, so I'm committing it until I can more robustly test it.
|
|
I'd like to see if I can avoid using `cabal` and `stack` and build and deploy
this application using `nix-shell` and `nix-build` only. Let's see how that
goes.
|
|
TL;DR:
- Consume GoogleSignIn.validateJWT in the Handler for /verify
- Rename validation fn to validateJWT
- Prefer Text to String type
|
|
Assert that the exp field of the JWT is "fresh".
|
|
The JWT should match "accounts.google.com" or "https://accounts.google.com". If
it doesn't, we produce a validation error.
TL;DR:
- Group all failed stringOrURI function calls as StringOrURIParseFailure errors
|
|
The subject of this commit message says it all.
|
|
Test that when the JWT contains the client ID for my Google app, the JWT is
valid, and when it doesn't, it's invalid.
|
|
I need IO for:
- Getting the current time to validate `exp`
- Making an HTTP request to Google's token verifier endpoint
|
|
Thank you, -Wall. You are truly an unsung hero.
|
|
I'm attempting to be an obedient boy and implement this and future features
using TDD.
TL;DR:
- Defined a few tests
- Defined an empty GoogleSignIn module
- Defined a Fixtures module to quickly create JWTs to test
|
|
Dumping grounds for personal, stylistic functions intended to improve readabily
and writability (in that order).
|
|
TL;DR:
- Add common dependencies like Servant, Aeson, Warp, Cors
- Define a POST /verify endpoint for our client to hit
- POST to /verify client-side onSignIn
|
|
TODO: Support Google Sign-in server-side
Also:
- Add Haskell to project's shell.nix
- Add stubbed Main.hs and Spec.hs
- Add common .ghci file
|
|
Remember: always read the instructions; that's the most important part.
|
|
Partially optimize inputs and document rules for further optimizations we can
make.
|
|
TL;DR:
- Accept input from the CLI
- Add a project README.md
|
|
Apply the transform to a Keyboard. Onwards to the final demonstration!
|