Principle of least surprise: I would not expect (defn too [a b] (+ a b)) to fail, but to infer return type Num
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.
Is there an option to start inferring on case of failure?
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.
How should I go about annotating an existing library? In particular, thinking about Promesa
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
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.
I was looking for documentation on the meaning of variance and couldn't find it
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?
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.
But :invariant is the conservative annotation.
if you expect (IPromise Int) <: (IPromise Num) then try annotating covariant.
The checker will tell you if it's actually covariant.
That's great, thanks
It should probably be covariant Any documentation on variance in the library I can read?
Since it's essentially fmap, can I define fmap in the abstract then tell tc it applies to IPromise for method -map?
> Any documentation on variance in the library I can read? I don't think it's documented.
> 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.
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
Yes. Perhaps it could be done with a macro too.
hmm no, maybe not. I'll keep it in mind.
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 rewriteThe 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