frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

Nginx introduces native support for ACME protocol

https://blog.nginx.org/blog/native-support-for-acme-protocol
312•phickey•4h ago•119 comments

PYX: The next step in Python packaging

https://astral.sh/pyx
80•the_mitsuhiko•1h ago•32 comments

OCaml as my primary language

https://xvw.lol/en/articles/why-ocaml.html
100•nukifw•1h ago•57 comments

Fuse is 95% cheaper and 10x faster than NFS

https://nilesh-agarwal.com/storage-in-cloud-for-llms-2/
20•agcat•47m ago•0 comments

FFmpeg 8.0 adds Whisper support

https://code.ffmpeg.org/FFmpeg/FFmpeg/commit/13ce36fef98a3f4e6d8360c24d6b8434cbb8869b
674•rilawa•9h ago•252 comments

Pebble Time 2* Design Reveal

https://ericmigi.com/blog/pebble-time-2-design-reveal/
124•WhyNotHugo•5h ago•55 comments

Launch HN: Golpo (YC S25) – AI-generated explainer videos

https://video.golpoai.com/
31•skar01•2h ago•48 comments

Cross-Site Request Forgery

https://words.filippo.io/csrf/
38•tatersolid•2h ago•8 comments

So what's the difference between plotted and printed artwork?

https://lostpixels.io/writings/the-difference-between-plotted-and-printed-artwork
142•cosiiine•6h ago•50 comments

Coalton Playground: Type-Safe Lisp in the Browser

https://abacusnoir.com/2025/08/12/coalton-playground-type-safe-lisp-in-your-browser/
74•reikonomusha•5h ago•25 comments

rerank-2.5 and rerank-2.5-lite: instruction-following rerankers

https://blog.voyageai.com/2025/08/11/rerank-2-5/
6•fzliu•1d ago•1 comments

ReadMe (YC W15) Is Hiring a Developer Experience PM

https://readme.com/careers#product-manager-developer-experience
1•gkoberger•3h ago

DoubleAgents: Fine-Tuning LLMs for Covert Malicious Tool Calls

https://pub.aimind.so/doubleagents-fine-tuning-llms-for-covert-malicious-tool-calls-b8ff00bf513e
60•grumblemumble•6h ago•18 comments

This website is for humans

https://localghost.dev/blog/this-website-is-for-humans/
366•charles_f•4h ago•175 comments

New treatment eliminates bladder cancer in 82% of patients

https://news.keckmedicine.org/new-treatment-eliminates-bladder-cancer-in-82-of-patients/
191•geox•4h ago•90 comments

The Mary Queen of Scots Channel Anamorphosis: A 3D Simulation

https://www.charlespetzold.com/blog/2025/05/Mary-Queen-of-Scots-Channel-Anamorphosis-A-3D-Simulation.html
57•warrenm•6h ago•13 comments

OpenIndiana: Community-Driven Illumos Distribution

https://www.openindiana.org/
53•doener•4h ago•44 comments

April Fools 2014: The *Real* Test Driven Development (2014)

https://testing.googleblog.com/2014/04/the-real-test-driven-development.html
74•omot•2h ago•13 comments

Google Play Store Bans Wallets That Don't Have Banking License

https://www.therage.co/google-play-store-ban-wallets/
29•madars•1h ago•10 comments

We caught companies making it harder to delete your personal data online

https://themarkup.org/privacy/2025/08/12/we-caught-companies-making-it-harder-to-delete-your-data
214•amarcheschi•6h ago•51 comments

DeepKit Story: how $160M company killed EU trademark for a small OSS project

https://old.reddit.com/r/ExperiencedDevs/comments/1mopzhz/160m_vcbacked_company_just_killed_my_eu_trademark/
20•molszanski•53m ago•6 comments

PCIe 8.0 Announced by the PCI-Sig Will Double Throughput Again – ServeTheHome

https://www.servethehome.com/pcie-8-0-announced-by-the-pci-sig-will-double-throughput-again/
47•rbanffy•3d ago•48 comments

29 years later, Settlers II gets Amiga release

https://gamingretro.co.uk/29-years-later-settlers-ii-finally-gets-amiga-release/
54•doener•1h ago•15 comments

Claude says “You're absolutely right!” about everything

https://github.com/anthropics/claude-code/issues/3382
525•pr337h4m•13h ago•411 comments

Job Listing Site Highlighting H-1B Positions So Americans Can Apply

https://www.newsweek.com/h1b-jobs-now-american-workers-green-cards-2041404
31•walterbell•1h ago•9 comments

A case study in bad hiring practice and how to fix it

https://www.tomkranz.com/blog1/a-case-study-in-bad-hiring-practice-and-how-to-fix-it
75•prestelpirate•3h ago•65 comments

Honky-Tonk Tokyo (2020)

https://www.afar.com/magazine/in-tokyo-japan-country-music-finds-an-audience
19•NaOH•4d ago•6 comments

New downgrade attack can bypass FIDO auth in Microsoft Entra ID

https://www.bleepingcomputer.com/news/security/new-downgrade-attack-can-bypass-fido-auth-in-microsoft-entra-id/
7•mikece•35m ago•1 comments

Gartner's Grift Is About to Unravel

https://dx.tips/gartner
91•mooreds•4h ago•44 comments

Claude Sonnet 4 now supports 1M tokens of context

https://www.anthropic.com/news/1m-context
1256•adocomplete•1d ago•664 comments
Open in hackernews

Coalton Playground: Type-Safe Lisp in the Browser

https://abacusnoir.com/2025/08/12/coalton-playground-type-safe-lisp-in-your-browser/
74•reikonomusha•5h ago

Comments

CraigJPerry•3h ago
Is Coalton not more about performance, removing the dynamicism - lisp (at least SBCL) is already type-safe. Or it behaves that way in my limited experience - e.g. i get feedback when i screw up.

I'm completely clueless about Coalton, (and almost completely an idiot when it comes to CL more generally - been playing for a couple of years at this point but even so, every day is still a school day...)

asplake•3h ago
I’ve looked at it rather than used it, but what it brings is ML-style polymorphism. Type safety is a given in that case, which may or may not be the case with CL (I’ll let others argue that one).
wild_egg•3h ago
CL is strongly typed but not statically typed. The compiler generally doesn't complain ahead of time that your function is going to do math on a string because it was called incorrectly. Typically a runtime condition will be signalled when it hits that point and you can sort it out from there.

Coalton moves that to the compilation step so you get an error back the instant you send the form to the REPL.

tmtvl•3h ago
In CL you can't declare, for example, a proper-list-of type, which is to say a type which accepts a second type and represents a proper list containing only members of that second type.

  (deftype Proper-List-Of (subtype)
    `(or Null
         (Cons ,subtype
               (Proper-List-Of ,subtype))))
Doesn't work (for example). There kind of are ways to work around it to some extent with satisfies and ad-hoc predicate generation, but Coalton is a true value add in that aspect.
skulk•2h ago
FWIW, SBCL is pretty good at optimizing away dynamic type checks if you help it out.

Here are some examples under:

    (declaim (optimize (speed 2)))
First example is a generic multiplication. x and y could be _any_ type at all.

    (defun fn (x y) (* x y))
If we disassemble this function, we get the following:

    ; disassembly for FN
    ; Size: 34 bytes. Origin: #x1001868692                        ; FN
    ; 92:       488975F8         MOV [RBP-8], RSI
    ; 96:       4C8945F0         MOV [RBP-16], R8
    ; 9A:       498BD0           MOV RDX, R8
    ; 9D:       488BFE           MOV RDI, RSI
    ; A0:       FF142540061050   CALL [#x50100640]                ; SB-VM::GENERIC-*
    ; A7:       4C8B45F0         MOV R8, [RBP-16]
    ; AB:       488B75F8         MOV RSI, [RBP-8]
    ; AF:       C9               LEAVE
    ; B0:       F8               CLC
    ; B1:       C3               RET
    ; B2:       CC0F             INT3 15                          ; Invalid argument count trap
Note that it calls `GENERIC-*` which probably checks a lot of things and has a decent overhead.

Now, if we tell it that x and y are bytes, it's going to give us much simpler code.

    (declaim (ftype (function ((unsigned-byte 8) (unsigned-byte 8)) (unsigned-byte 16)) fn-t))
    (defun fn-t (x y) (* x y))
The resulting code uses the imul instruction.

    ; disassembly for FN-T
    ; Size: 15 bytes. Origin: #x1001868726                        ; FN-T
    ; 26:       498BD0           MOV RDX, R8
    ; 29:       48D1FA           SAR RDX, 1
    ; 2C:       480FAFD7         IMUL RDX, RDI
    ; 30:       C9               LEAVE
    ; 31:       F8               CLC
    ; 32:       C3               RET
    ; 33:       CC0F             INT3 15                          ; Invalid argument count trap*
matheusmoreira•1h ago
Can SBCL actually check at compile time that the arguments to fn-t are bytes? I wonder how that works with Lisp's extreme dynamism. Also wondering about the calling convention it uses.
reikonomusha•1h ago
It can detect simple-ish instances, like calling

    (fn-t "hello" "world")
But a good rule-of-thumb is that these compile-time type errors are more of a courtesy, rather than a guarantee. As soon as you abstract over fn-t with another function, like so:

    (defun g (x y)
      (fn-t x y))
and proceed to use g in your code, all the static checking won't happen anymore, because as far as g is concerned, it can take any input argument types.

    CL-USER> (defun will-it-type-error? ()
               (g "x" "y"))
    ;; compilation WILL-IT-TYPE-ERROR? successful
No compile-time warning is issued. Contrast with Coalton:

    COALTON-USER> (coalton-toplevel
                    (declare fn-t (U8 -> U8 -> U8))
                    (define (fn-t x y)
                      (* x y))
                    
                    (define (g x y)
                      (fn-t x y))
                    
                    (define (will-it-type-error?)
                      (g "hello" "world")))

    error: Type mismatch
      --> <macroexpansion>:8:7
       |
     8 |      (G "hello" "world")))
       |         ^^^^^^^ Expected type 'U8' but got 'STRING'
       [Condition of type COALTON-IMPL/TYPECHECKER/BASE:TC-ERROR]
tgbugs•1h ago
I highly recommend watching [0] for an introduction to Coalton in the context of CL. Specifically it provides an excellent example of how the type system makes the language more expressive (by making it more composable) while also improving performance (e.g. because it can prove that certain optimizations are safe and thus can automatically generate the type annotations).

0. https://www.youtube.com/watch?v=of92m4XNgrM

reikonomusha•1h ago
I think it's three things:

1. Bringing abstractions that are only possible with static types, like ad hoc polymorphism via type classes. For example, type classes allow polymorphism on the return type rather than the argument types. Something like

    (declare stringify (Into :a String => :a -> :a -> String))
    (define (stringify a b)
      (str:concat (into a) (into b)))

    ; COALTON-USER> (coalton (stringify 1 2))
    ; "12"
The function `into` is not possible in a typical dynamically typed language, at least if we aim for the language to be efficient. It only takes one argument, but what it does depends on what it's expected to return. Here, it's expected to return a string, so it knows to convert the argument type to a string (should knowledge of how to do that be known by the compiler). Common Lisp's closest equivalents would be

    (concatenate 'string (coerce a 'string) (coerce b 'string))
which, incidentally, won't actually do what we want.

2. Making high performance more accessible. It's possible to get very high performance out of Common Lisp, but it usually leads to creating difficult or inextensible abstractions. A lot of very high performance Common Lisp code ends up effectively looking like monomorphic imperative code; it's the most practical way to coax the compiler into producing efficient assembly.

Coalton, though, has an optimizing compiler that does (some amount of) heuristic inlining, representation selection, stack allocation, constant folding, call-site optimization, code motion, etc. Common Lisp often can't do certain optimizations because the language must respect the standard, which allows things to be redefined at run-time, for example. Coalton's delineation of "development" and "release" modes gives the programmer the option to say "I'm done!" and let the compiler rip through the code and optimize it.

3. Type safety, of course, in the spirit of ML/Haskell/etc.

bitwize•1h ago
Strong static typing is an absolute must for large scale software engineering. CL code can be made very performant without it, but there are enormous development speed and correctness gains to be had by type-checking programs before they are executed rather than at runtime.

It's 2025, people. Dynamic languages for serious projects were a 90s fad, hopefully never to be repeated.

anentropic•3h ago
Layout is broken on non-maximised window sizes (text overflows off the right edge of the page)

EDIT: I'm referring to layout of the blog post in the thread title, the https://coalton.app/ is ok

anentropic•3h ago
FYI coalton.app "Type Classes" example has "Error: unmatched close parenthesis" when you run it

"JSON Parser" example also has errors

paddy_m•2h ago
I have heard multiple people claim that macros are incompatible with strong or static typing and I don't see why.

If there were a lisp with optional static typing like typescript, it would seem to me to be completely possible to write macros that write types. In many cases it woudl do away with the need for generic types (and allow multiple competing syntaxes for dynamic types). Most interestingly it would allow you to write new generic forms instead of waiting for whatever the language designer gives you. It would also allow you access to types at runtime (which the typescript language designers took away).

Maybe people were telling me that lisp style macros were incompatible with hindley millner typing, but I still don't see how. The macros would just emit a hindley milmner subset.

What am I missing?

reikonomusha•2h ago
As far as your first question is concerned, macros in and of themselves are not incompatible with a typed language. Coalton uses Lisp macros, for example, and they work seamlessly and as expected.

But a Coalton macro is typically written in Lisp, not Coalton. This isn't in and of itself a problem---it's very easy and straightforward thus to write Common Lisp-style macros in Coalton. The difficulties arise when the macro must itself be (1) written in a statically typed manner, which gets into having a complete typing on your metalanguage (or your AST), and (2) allowed to access the type environment of the surrounding context in which the expansion is happening. If (2) should be accomplished, then the type-checking machinery must collaborate with the macro-expansion machinery, and that in practice makes both tasks very difficult to specify semantics for and implement.

The language Hackett [1] worked toward solving the problem of having true typed and type-aware macros (they call them "type-aware" and "type-directed" macros [2]). Development unfortunately ceased ~7 years ago.

[1] https://github.com/lexi-lambda/hackett

[2] I think this video has a good discussion of Lisp, macros, and static types, from the perspective of implementing a Haskell in Racket. https://www.youtube.com/watch?v=5QQdI3P7MdY

spooky_deep•1h ago
Since the macros run at compile time, I am ok with them not being statically checked. Statically checked macros seems like an academic curiosity.

What am I missing?

wk_end•1h ago
One concern I’d have is that any type errors would be reported on the macro expanded code and thus be pretty much inscrutable outside of toy examples.
reikonomusha•1h ago
I think you're right that debugging errors involving complicated macros can get difficult, but to at least make the situation more tolerable, when Coalton expands a macro, it remembers where the expansion came from, so an error will be reported in the right place with the right source code. For example, using the RPN macro from the sister comment, here's an intentional type error:

    COALTON-USER> (coalton (rpn "x" "y" +)) 
      --> <macroexpansion>:1:9
       |
     1 |  (COALTON (RPN "x" "y" +))
       |           ^^^^^^^^^^^^^^^ expression has type ∀. (NUM STRING) => STRING with unresolved constraint (NUM STRING)
       |           ^^^^^^^^^^^^^^^ Add a type assertion with THE to resolve ambiguity
       [Condition of type COALTON-IMPL/TYPECHECKER/BASE:TC-ERROR]
reikonomusha•1h ago
Then nothing. Macros work.

Silly example:

    COALTON-USER> (defmacro rpn (x y op)
                    `(,op ,x ,y))
    RPN

    COALTON-USER> (coalton-toplevel
                    (define (double x)
                      (rpn 2 x *)))
    ;; DOUBLE :: ∀ A. NUM A ⇒ (A → A)

    COALTON-USER> (coalton (double 3.0))
    6.0
taeric•46m ago
The big miss here is that "compile time" is typically understood to be "batch compilation" time for languages. For Common LISP, macros run at read time. Which is often doable during runtime.
kscarlet•1h ago
It's easy to just stick them together, but to me (who writes too much Lisp for my own health) this is unsatisfactory.

The dream: just like macro can be seen as a (staged) extension mechanism for Lisp evaluator, there should be an extension mechanism for the static type system, which allows me to define new types, define new syntax (like Haskell do-notation) which makes use of typing environment and expected type of current context (return-type polymorphism), etc.

The reality: very few environments figure this out. In Coalton Lisp macros do work, but only at the level of untyped S-expr. A Lisp macro can't know about types of the variables in the lexical environment, or expected type of its own context. But it quite possibly works fine for the "typescript-like" use case you described.

The problem I see: H-M type system isn't designed with extensibility in mind, and it's hopeless to make it extensible. More technical explanation of why it's hard to integrate with Lisp macro is that H-M relies on a unification-based inference stage which execution flow is very different from macro expansion.

Possible solution: There's no fundamental reason why static type can't have something as powerful as Lisp macro. However first of all you would need an extensible type system, which seems to still be an open research problem. I think bidirectional type system is hopeful -- it's so different from H-M at a fundamental level though that I think it's hopeless to retrofit into Coalton.

JonChesterfield•1h ago
What's the objection to putting type annotations on the macro, and refusing to compile code where the arguments to the macro don't match the type?
reikonomusha•55m ago
Since a macro is a definition of syntax, I think you'd essentially need something like typing judgments to show how the typed elements of the syntax relate to one another, so that the type checker (e.g., a typical Hindley-Milner unifier) can use those rules. These are usually written as the fraction-looking things that show up in PLT papers. This is, as GP says, essentially extending the type system, which is a task fraught with peril (people write entire papers about type system extensions and their soundness, confluence, etc.).
JonChesterfield•45m ago
Depends on your point of view really. I'd define a macro as a function with slightly weird evaluation rules.

If you want to write a macro where any call to it which typechecks creates code which itself typechecks, you have to deal with eval of sexpr which is roughly a recursive typecheck on partial information, which sounds tractable to me.

kscarlet•50m ago
There's no objection, but I think this solves a different problem than above described, and is possibly a more complicate matter in itself than it may look like. First, are you describing a way to typecheck macro so that it doesn't generate ill-typed code? The type system that does this is active research (I think requires modal typing?). Also this does not increase the expressive power of untyped Lisp macro -- just making them safer, while I was proposing their expressive power is unsatisfactory and should be enhanced via a sort of reflection. That would only makes them even harder to type!
manoDev•1h ago
OP: You might want to check, a bunch of examples after "maybe monad" are broken.