Fork me on GitHub
#core-typed
<
2023-09-02
>
kokonut14:09:59

Hi, I am quite new to typedclojure, and am having difficulty with the built-in update . When I create a simple function using update such as follows,

(ns typedupclj.core
  (:require
   [malli.core :as m]
   [typed.clojure :as t]))

(def Address
  [:map
   [:street string?]
   [:city string?]
   [:zip int?]])

(defn step-up-zip [address]
  (update address :zip inc))

(m/=> step-up-zip
  [:=> [:cat Address] Address])

(t/cns 'typedupclj.core)
I am getting this error
Caused by clojure.lang.ExceptionInfo
   Type Checker: Found 1 error
   {:type-error :top-level-error, :errors (#error {
    :cause "Unannotated var clojure.core/update"
    :data {:type-error :clojure.core.typed.errors/type-error, :env {:line 13, :column 4, :file "file:/Users/darren/Work/jam/typed-up-clj/src/typedupclj/core.clj"}, :form update}
    :via
    [{:type clojure.lang.ExceptionInfo
      :message "Unannotated var clojure.core/update"
Should I annotate on update or should I simply use something else?

ambrosebs19:09:29

Hi, update doesn't work yet, but I think (assoc address :zip (inc (:zip address))) should work.

ambrosebs19:09:30

I'll take another look at update support since the recently improved local inference might make it a little easier.

kokonut19:09:04

👍 thanks.

ambrosebs19:09:37

FWIW you could also write a macro to help the checker:

(defmacro update [m k f & args]
  `(let [m# ~m k# ~k] (assoc m# k# (~f (get m# k#) ~@args))))

ambrosebs03:09:34

On update support: I think an annotation like this is my goal:

update : (t/All [m k v] [m k [(t/Get m k) :-> v] :-> (t/Assoc m k v)])
I think I can use similar inference gymnastics to symbolic closures to make it work. Basically I want to fix m and k as early as possible, then check the 3rd arg with the t/Get type eliminated (by substituting m and k). Then iterate until we learn nothing else about the type variables.

ambrosebs06:09:23

Success, figured it out on my machine with this annotation:

cc/update (t/All [m k v c :..] [m k [(t/Get m k) c :.. c :-> v] c :.. c :-> (t/Assoc m k v)])
It works fine with 3 args. Just need to figure out how to infer the c :.. c part.

ambrosebs05:09:24

typedclojure version 1.1.2 supports update

💯 1