Hey there I'm looking for a way to use malli and function schemas to express something similar to generics. And I've noticed that there's been some progress with adding this feature to malli via polymorphic schemas: Issue: https://github.com/metosin/malli/issues/846 Original PR: https://github.com/metosin/malli/pull/1053 Latest PR: https://github.com/frenchy64/malli/pull/11 And I was wondering, if there are any known problems with integrating this into malli? I'm hoping to use this feature for some projects, so I'd be happy to help with moving this forward. please let me know your thoughts cc @ambrosebs
what exactly are you hoping to accomplish with a supposed generic?
Well for example, I'd like to write some code like this:
(m/=> my-map-fn
(m/all [a b]
[:-> [:-> a b] [:sequential a] [:sequential b]]))
So in this case I'm able to express that I have function that receives a function that receives a type and returns another type, and later on these types can be supplied or inferred.
I'm hoping that the result of this annotation would allow for clj-kondo to infer the correct type when supplying the function to my-map-fn function. For example:
(m/=> my-map-fn
(m/all [a b]
[:-> [:-> a b] [:sequential a] [:sequential b]]))
(defn my-map-fn [f xs] (map f xs))
(def thing-schema
[:map
[:tag :string]
[:val :int]])
(m/=> do-stuff
[:-> [:sequential thing-schema] [:sequential :string]])
(defn do-stuff [things]
(my-map-fn
(fn [thing]
(:tag thing) ;; here clj-kondo would know that this complies with thing-schema
)
things))
(do-stuff [{:tag "label"
:val 0}])oh interesting. i odn't have a lot of experience with clj-kondo's type system, but i believe it's much simpler than that
yup yup, at the moment m/all does not exist yet in malli, but it's proposed in the PR https://github.com/metosin/malli/pull/1053/files. Though, I'm not sure how it would integrate with clj-kondo yet. From what I've noticed, malli will emit a file into the .clj-kondo directory (relative to project root), and from there clj-kondo will lint based on whatever type mismatches are reported. So hopefully that means malli could report a mismatch after evaluating the generics
right, i'm talking about clj-kondo. i've reviewed ambrose's PR, i think it's cool. but if you're looking for clj-kondo to throw errors, i don't know that it can handle that. i believe it works purely with concrete types (x is a seq or a long)
yeah i agree that clj-kondo wouldn't support generic types (at least atm). But i was thinking it wouldn't need to support them if malli emits the concrete type as the mismatch, So the generics are resolved before clj-kondo attempts to lint
hmmmmm compelling idea
might run into issues if the generic is used in multiple places with different types, so the concrete type needs to change per invocation
oh yeah good point, hmm not sure how to overcome that atm
we'd almost need some way of emitting the resolved schema and linking it back to the invocation, but i don't see anything that can do that in the clj-kondo data
yeah, at that point we're into typed-clojure land
well i suppose the next simplest thing would be to teach clj-kondo (or a similar tool) how to evaluate the type mismatches with the generic arguments. so at least then we don't need to worry about resolving+linking the instantiated schemas ahead-of-time
@hagstromsg I need to gather my notes and I'll get back to you.
awesome, looking forward to it, thank you 🙏