Fork me on GitHub
#core-typed
<
2022-10-23
>
Ben Sless08:10:09

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

ambrosebs02:10:57

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 Sless02:10:39

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

ambrosebs04:10:14

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 Sless09:10:58

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

ambrosebs02:10:06

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

ambrosebs02:10:01

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 Sless02:10:13

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

Ben Sless03:10:22

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?

ambrosebs04:10:53

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.

ambrosebs04:10:07

But :invariant is the conservative annotation.

ambrosebs04:10:33

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

ambrosebs04:10:01

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

Ben Sless04:10:16

That's great, thanks

Ben Sless04:10:43

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

Ben Sless04:10:28

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

ambrosebs14:10:25

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

ambrosebs14:10:48

> 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 Sless16:10:17

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

ambrosebs16:10:31

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

ambrosebs16:10:55

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

Ben Sless17:10:54

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 Sless17:10:33

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