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?typedclojure version 1.1.2 supports update
Hi, update doesn't work yet, but I think (assoc address :zip (inc (:zip address))) should work.
I'll take another look at update support since the recently improved local inference might make it a little easier.
👍 thanks.
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))))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.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.