core-typed

Ben Sless 2022-10-23T08:48:09.221309Z

Principle of least surprise: I would not expect (defn too [a b] (+ a b)) to fail, but to infer return type Num

2022-10-24T02:06:57.619449Z

for performance reasons, the default of typed clojure is "never infer anything". This is so you can type check a namespace without checking its dependents.

Ben Sless 2022-10-24T02:56:39.698439Z

Is there an option to start inferring on case of failure?

2022-10-24T04:10:14.287069Z

You can try some of the options here in the old namespace https://github.com/typedclojure/typedclojure/blob/ae9b62e52b5744d8f04da252d05edce21c92477a/typed/clj.runtime/src/clojure/core/typed.clj#L1337-L1343 It does not work very well. The inference algorithm can't work backwards and figure out the type of a and b.

Ben Sless 2022-10-23T09:59:58.620179Z

How should I go about annotating an existing library? In particular, thinking about Promesa

2022-10-24T02:01:06.488619Z

See core.async annotations for a good example. 1. Choose a namespace to put your annotations: https://github.com/typedclojure/typedclojure/blob/main/typed/lib.core.async/src/typed/lib/clojure/core/async.clj 2. Create a typedclojure_config.clj file in your lib and put the namespace in the :ann entry https://github.com/typedclojure/typedclojure/blob/main/typed/lib.core.async/src/typedclojure_config.clj

2022-10-24T02:05:01.143559Z

to annotate macros, see the :ext entry and associated namespace for examples. Though that's still alpha-ish, but hasn't changed much in a while.

Ben Sless 2022-10-24T02:58:13.574289Z

I was looking for documentation on the meaning of variance and couldn't find it

Ben Sless 2022-10-24T03:01:22.919059Z

Example, the protocol has a method -map, that takes a IPromise [a] and a function a -> b and returns a IPromise[b] How would that look like?

2022-10-24T04:13:53.951519Z

Sounds like (ann-protocol IPromise [[a :variance :invariant]] -map (All [b] [(IPromise a) [a -> b] -> (IPromise b)])) The variance of a depends on all the places where it occurs. Here, it looks covariant because it's to the left of 2 arrows.

2022-10-24T04:14:07.204369Z

But :invariant is the conservative annotation.

2022-10-24T04:14:33.486509Z

if you expect (IPromise Int) <: (IPromise Num) then try annotating covariant.

2022-10-24T04:15:01.249419Z

The checker will tell you if it's actually covariant.

Ben Sless 2022-10-24T04:18:16.995269Z

That's great, thanks

Ben Sless 2022-10-24T04:18:43.914469Z

It should probably be covariant Any documentation on variance in the library I can read?

Ben Sless 2022-10-24T04:20:28.883939Z

Since it's essentially fmap, can I define fmap in the abstract then tell tc it applies to IPromise for method -map?

2022-10-24T14:46:25.633999Z

> Any documentation on variance in the library I can read? I don't think it's documented.

2022-10-24T14:48:48.263559Z

> Since it's essentially fmap, can I define fmap in the abstract then tell tc it applies to IPromise for method -map? Hmm I don't think that would work in practice. You'd want a way to instantiate fmap's a with IPromise's a . I can't think of a good way to do that.

Ben Sless 2022-10-24T16:41:17.541879Z

This is totally a nice-to-have, but I imagine something like declaring the signature for Functor, then saying IPromise implements Functor's fmap by way of -fmap

2022-10-24T16:57:31.480769Z

Yes. Perhaps it could be done with a macro too.

2022-10-24T16:57:55.213989Z

hmm no, maybe not. I'll keep it in mind.

Ben Sless 2022-10-24T17:35:54.423619Z

This is the sort of API I would imagine

(def-ann Functor [[a :variance :covariant]]
  (fmap [(Functor a) [a -> b] -> (Functor b)]))

(instance Functor IPromise
          [fmap -fmap])
A naive implementation would just do it with clojure.walk and rewrite

Ben Sless 2022-10-24T17:40:33.500179Z

The nicest part about having it is it creates a common language different libraries could participate in, a sort of community types repository for common stuff