Fork me on GitHub

Q: I have a single arg fn that I am trying to generatively test. The single arg is vector that is checked using a :catn schema. when I use the => syntax, it interprets the nested :catn schema for the fn arity instead of treating it as a single arg. has anyone figured out how to do this?


[:cat [:cat :int :int]]


all fn args are cat


oh wait no i just realized your issue


Yeah. Simple but not easy. I can work around it by wrapping with another fn with a map arg.


I'll log an issue to see if we are missing something


wrap in :schema to push out of the sequence


thx @U055NJ5CC I’ll give that a try


confirming, using :schema around the vector schema fixes the problem

Ben Sless07:12:28

Reading @afoltzm FSM post again, I returned to the idea of some sort of schema router / compiler, where an or of schemas will pull out the common denominator then dispatch to the difference Thoughts?

💡 1

can you explain more? I’ve been using them more in SPA’s so interested in this

Ben Sless10:12:41

Imagine [:or [:map [:a any?] [:b any?]] [:map [:a any?] [:c any?]]] => [:and [:map [:a any?]] [:or [:map [:b any?]] [:map [:c any?]]]] to start with, even smarter to have a dispatch to the correct schema instead of or


Sounds like a malli.diff namespace might be an interesting idea, because this concept may be applicable beyond just :or schemas – for example, you'd be able to compare two seqex schemas and say things like "sequence B can contain all the same elements as sequence A except for elements X and Y"

Ben Sless15:12:36

I'm just getting started, [:or :int :number] => :number

Ben Sless15:12:18

schemas as segments and sets


Can I have a link for this post? It looks interesting.


This is really interesting, both the post and the routing idea 👏


just would have needed an intersection of two map schemas yesterday.


pluggable optimizer is a great idea, here's one stab at it:

Ben Sless09:12:23

@U7XR2PZFW's work on inference could intersect with this as well. Every type of/or schema can represent a set of predicates. A predicate can be a singular predicate, a segment (upper and lower bounds) or finite domain (min max)


Sounds like roughly equivalent to sub-typing for structural types. If we assume collections are covariant with respect to elements, functions are contravariant with respect to arguments, and a few other assumptions, I suspect small-ish rule system could be used to implement a sub-type predicate.

Ben Sless19:12:58

We can even unpack map schemas to a closed set of predicates, being map? and a set of all the entry predicates. Same for tuples. Then conjunction and disjunction are pretty well defined and we remain in predicate land and not structure. Not sure if it's good

Ben Sless20:12:14


(defprotocol SchemaDomain
  (-conj [this that]) ;; and
  (-disj [this that]) ;; or
  (-isa? [this that])
  (-walk [this]))

(defrecord EntrySchema [k v]
  (-conj [this that]
    (EntrySchema. k (-conj v (:v that))))
  (-disj [this that]
    (EntrySchema. k (-disj v (:v that)))))

(defrecord PredicateSchema [p]
  (-conj [this that]
      (-isa? this that) this
      (-isa? that this) that
      :else (-and this that)))
  (-disj [this that]
      (-isa? this that) that
      (-isa? that this) this
      :else (-or this that))))

👀 1
👍 1

I've encountered an issue where sequence schemas appear not to preserve metadata of input collections:

(meta (m/decode
         [:schema {:decode/get {:enter identity}} [:cat [:= :start] :map]]
         (with-meta [:start {:a 2}] {:meta true})
         (mt/transformer {:name :get})))
;; => nil

(meta (m/encode
         [:schema {:encode/get {:enter identity}} [:cat [:= :start] :map]]
         (with-meta [:start {:a 2}] {:meta true})
         (mt/transformer {:name :get})))
;; => nil
is this expected behavior, or should malli preserve this information?


(happy to file an issue on GitHub if it would be helpful)