I had a similar experience this year as I’m working on an ML-cousin to Golang. I actually found that ChatGPT (gpt4) was really good and breaking down the step of implementing a Hindley-Milner type system in a language I could understand. It could also provide follow up clarifications to my questions too. I then implemented it a small bit at a time and as the complexity grew I started to better understand the algorithm.
EDIT: ChatGPT could actually demonstrate the whole process for type checking small chunks of code, including: assigning them type variables, collecting constraints and then unification. It would even then point out if there was a type error in the code snippet!
I'm curious how you went. Here's my attempt: https://github.com/chewxy/hm , the core of which (i.e. the interface type) is what powers most of the languages I wrote (different languages I wrote have different unification schemes)
Cool to see an implementation in Go, nice! Here's where I got to with my first attempt: https://github.com/cobbweb/flite. There's definitely stuff I'd do a bit different, my second attempt is actually a project to learn Rust with, but I'm already considering switch to Ocaml haha!
I agree with this, I'm designing a similar language and have gone with this approach. Same syntax for all functions, but top-level functions require explicit type annotations (purely for documentation/sanity more so than a technical requirement).
Each line of code on the homepage hero appears to be truncating the last character for me (W11/FF/ultrawide screen). Somewhat comically yielding `moon new hell` XD
As some how is writing a compilter in TS, I agree it's not too bad. I started with Deno like the author but ended up switching to Bun which, despite some rough edges, I'm enjoying more than Deno and it's _very_ quick! (My main niggle with Bun is the test reporting, but it's getting the job done)
For standard parser generator frontend, Ohm-js[1] is quite pleasant. I wouldn't recommend anyone reviews the offical tsc compiler, it's huuuge - instead there's mini-typescript[2] (in particular the centi-typescript branch[3]) which does a nice job illustrating how tsc is working.
I know this is probably blasphemy at this point, but I actually wasn't enjoying package management in Deno (or lack thereof). I've been an avid user of the NPM ecosystem for a long time (10+ years), it's entrenched deep in me and I don't mind it haha! In particular with Deno, it was trying to remember all the dependency URLs, and not wanting to duplicate them - every time I wanted to read a file and I had to lookup the std library URL for the umpteenth time. The package discovery isn't as good, and documentation was too different (why is everything in a file called mod.ts? why do I need to see all of the files in a dependency?).
This led to the recommended advice of having a dedicated TS file where you pull all your external dependecies in and then re-export them locally. This felt worse than package.json (read: clunky not having a first-class system to list external dependencies). And this is in a project with minimal dependencies too - yet it still frustrated me. Plus my editor had no type info for any external imports. I then discovered import maps, but that was still hit and miss in my editor (Neovim mind you) with code completion, made worse by not having a clear way to import ohm-js. Not to mention having to explicitly list `--import-map` for every command and forgetting too often and then wondering why my code wasn't working. Just feels like it's on a roundabout path to reinventing package.json anyway, just with distributed packaging by default?
I'm not particularly concerned with security either, so having to list `--allow-x` and `--allow-y` got tiring very quick. At this point, I just felt like Deno was constantly trying to stop me from getting stuff done. I ended basically ditch most of the new stuff in Deno and was basically treating it a ts-node (thanks to the new NPM/Node compat feature) - but it had me off side now.
I knew Bun.sh has some rough edges in terms of compatibility, etc (which is fine as it's pre-v1)... but for writing a compiler: I'm mostly writing everything from scratch and just need to read/write from the filesystem which is definitely stable and well documented. Switching to Bun was painless and all of a sudden everything Just Worked™, ran faster and I can get back to actually working on my compiler. The only problem I've had with Bun is not being able to tweak the output the results of `bun test` (e.g. if one of the first tests fail, I have to keep scrolling back up through my big list of passing tests to see why it failed) - if Bun had a better error summary at the end of the test output I'd be set!
TLDR; As someone using NPM/node for over a decade, nothing in Deno "just worked" for me and instead blocked me at every turn and the lack of package management turned me off. I know there are sound and objective reasons for design decisions in Deno, but none of those things matter much _to me_. Bun, on the other hand, is intended as a drop-in replacement for Node, but faster and with native support for TypeScript which ticks all the boxes I need for this particular project. (FWIW I tried switching a Remix project to Bun and it didn't work and stuck with Node).
Interesting, I'll really have to dig deeper into Bun. I know I've been having a hard time switching to anything else because I rely heavily on a typescript compiler transformer and that hasn't wanted to transfer to well to other things (like from Webpack to esbuild for example).
I’m actually working on a language like this. I quite liked ReScript/ReasonML, but having to manually write binding to use TypeScript or JS code is a drag. I’m making a functional language that looks and feels like TS and lets you import TS directly. Mostly just stripping imperative statements, removing class declaration and adding pattern matching and better data constructors (never liked the discriminated unions). WASM as a target is a bit further off.
EDIT: ChatGPT could actually demonstrate the whole process for type checking small chunks of code, including: assigning them type variables, collecting constraints and then unification. It would even then point out if there was a type error in the code snippet!