core-typed

2022-04-11T02:17:29.012679Z

https://github.com/typedclojure/typedclojure/commit/0f222f73cc85d74ccd73bb3d9701a05da902ad03, can now check such higher-order function definitions:

(ann takes-hof [[[t/Int :-> t/Int] :-> t/Int] :-> t/Int])
(defn takes-hof [f] (f #(inc %)))
Before, could not infer the type of %.

2022-04-11T03:33:54.766609Z

Real-world function this helped check with just a top-level annotation:

(t/defalias ParserK [t/Any Pos (t/Seqable t/Any) :-> t/Any])
(t/defalias ParserTramp [t/Any t/Any Pos (t/Coll t/Any) ParserK :-> t/Any])
(t/ann re/fmap-parser [[t/Any :-> t/Any] ParserTramp :-> ParserTramp])
https://github.com/metosin/malli/blob/3599fbd7fe1eba96c35e5c39073397cba0984b6a/src/malli/impl/regex.cljc#L135-L137

2022-04-11T03:46:39.153149Z

I think Typed Clojure found a bug in malli's impl, that's always fun.

❤️ 1
Ben Sless 2022-04-11T04:00:46.186409Z

How far is typed's implementation from being used as an inline pass in a compiler?

🤔 1
2022-04-11T14:32:44.427869Z

Nope, haven't tackled that yet. Actually it's unclear if it'll straightjacket the rest of the type checker, we'll see.

2022-04-11T14:41:54.466219Z

It'll probably be fine in practice, if I ever figure out how to do it.

rayat 2022-04-12T02:27:01.779459Z

This channel is riveting

Ben Sless 2022-04-11T04:03:02.194519Z

Isn't it close to type inference in terms of implementation and partial application?

2022-04-11T04:15:31.714069Z

Hmm well it takes and receives a mostly tools.analyzer format. If any compilers used that format it could be compatible.

2022-04-11T04:16:10.877339Z

It would be pretty easy to convert to a tools.analyzer version. There's just one extra op for an unexpanded form--you'd just expand it into the normal ops.

1
2022-04-11T04:17:39.478039Z

As to whether Typed Clojure's been designed that way, no. I've intentionally left evaluation of forms untouched to fulfill the promise of a truly optional type system.

🧠 1
2022-04-11T04:17:57.858389Z

Most of the inlining logic that Typed Clojure does never makes it way back to the AST.

2022-04-11T04:18:11.595699Z

It just passes things around in its type environment.

2022-04-11T04:19:51.155039Z

It actually leaves a lot of breathing room in terms of implementation. I can think a bit more out of the box. Kind of interesting too when you think about proving type soundness. Usually you have a source -> target lang translation, and prove the type system compiles from one to the other. That's not really the full story on some of the things I want to do with Typed Clojure.

🤔 1
2022-04-11T04:22:16.879429Z

I mean, I'm sure most type system impls fudge the details in practice compared to papers. Just something we realized a few years ago.

2022-04-11T04:23:20.821449Z

That we're sort of beating around the bush trying to make a source -> target language to prove soundness for a symbolic analysis idea.

Ben Sless 2022-04-11T04:41:32.551349Z

Writing an inline pass on tools analyzer isn't hard, I did it myself. Same for constant propagation. The harder parts are: Partial application Escaped closures

1
2022-04-11T04:49:30.018849Z

Ah ok. Inlining passes don't really make sense in a lot of cases for Typed Clojure. e.g., some functions are checked multiple times, how to combine results?

🤔 1
2022-04-11T04:50:18.232699Z

There's literature in the intersection type community but I haven't used it in the impl.

2022-04-11T04:51:13.635959Z

It's not obvious to me how to combine Typed Clojure with a compiler and get a non-negligible improvement over just the compiler.

🤔 1
Ben Sless 2022-04-11T04:52:39.215599Z

One thing comes to mind, dispatch to protocol or interface implementation at compile time over run time

2022-04-11T04:53:48.460499Z

Yes true. The attitude I've been taking is that's something that Typed Clojure could tell the user to annotate in their programs. Like Racket's optimization coach.

2022-04-11T04:54:18.383179Z

It's just so much extra baggage and complexity for a couple of implicit type hints.

🤔 1
Ben Sless 2022-04-11T04:54:41.209719Z

But I was thinking more in line of if there are some internals which could be used even for untyped inline passes

Ben Sless 2022-04-11T04:56:01.338129Z

Where type checking can be used to ensure correctness

2022-04-11T04:56:49.786579Z

No nothing like that. In terms of manipulating the AST, Typed Clojure does almost literally nothing.

Ben Sless 2022-04-11T04:57:08.267689Z

The day I manage to properly inline get-in without ad-hoc code I'll know I got it

🤔 1
Ben Sless 2022-04-11T04:57:44.924269Z

Any entry point if I want to familiarize myself with the implementation?

2022-04-11T04:58:17.857699Z

Ok, technically there's this beta-reduction pass you might be interested in. But it isn't used https://github.com/typedclojure/typedclojure/blob/main/typed/clj.analyzer/src/typed/clj/analyzer/passes/beta_reduce.clj

2022-04-11T04:58:38.414869Z

It was an experiment which trying to figure out how to write rules for macros.

2022-04-11T05:00:36.280099Z

Here's a tiny type system in this analyzer. It's a great introduction https://github.com/typedclojure/typedclojure/blob/main/typed/clj.analyzer/test/typed_test/clj/analyzer/gilardi_test.clj

Ben Sless 2022-04-11T05:00:50.389939Z

Cool. Thanks

2022-04-11T05:01:02.579019Z

analyze-outer == macroexpand1 on an AST node

2022-04-11T05:01:14.023359Z

analyze-outer-root == macroexpand

2022-04-11T05:01:31.876589Z

otherwise, it's just tools.analyzer.

2022-04-11T05:01:38.893229Z

enjoy 🙂

Ben Sless 2022-04-11T05:10:16.486229Z

I'll try to enjoy it responsibly 🙂

😆 1
Ben Sless 2022-04-11T05:11:20.841319Z

Another thing I think I asked on before is something like life time analysis which can be used to identify points between which a collection can be transient

Ben Sless 2022-04-11T05:11:52.865809Z

Or even mutable if you can guarantee it does not escape