Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schema variables, aka generics #846

Open
NoahTheDuke opened this issue Feb 7, 2023 · 1 comment
Open

Schema variables, aka generics #846

NoahTheDuke opened this issue Feb 7, 2023 · 1 comment
Labels
enhancement New feature or request for discussion Discussion is main focus of PR

Comments

@NoahTheDuke
Copy link
Contributor

Hey friends,

Sometimes I have a function schema where an argument can be one of many different schemas and I want the return value to match the input schema. From reading the docs, I don't think this is currently possible, so I would like to register my desire for some way to do this.

Given this function definition and schema:

(defn simple [arg]
  (if (map? arg)
    (update arg :a (fnil inc 0))
    (conj arg :success)))
(m/=> simple [:=>
               [:cat [:or [:map [:a :int]] [:vector :keyword]]]
               [:or [:map [:a :int]] [:vector :keyword]]])

(simple {:a 1}) ; {:a 2}
(simple [:a]) ; [:a :success]

Changing the implementation continues to validate:

(defn simple [arg]
  (if (map? arg)
    [:a :success]
    {:a 2}))
(m/=> simple [:=>
               [:cat [:or [:map [:a :int]] [:vector :keyword]]]
               [:or [:map [:a :int]] [:vector :keyword]]])

(simple {:a 1}) ; [:a :success]
(simple [:a]) ; {:a 2}

@erp12 extended Malli's schema system to handle this while experimenting in their schema inference repo; maybe their design would work here?

Something like:

(m/=> simple [:=> {:schemes {'S [:or [:map [:a :int]] [:vector :keyword]]}}
               [:cat 'S]
               'S])
@erp12
Copy link

erp12 commented Feb 9, 2023

Thanks for the shout out!

I agree that polymorphic schemas abstractly pop up everywhere, albeit less frequently at the edges of applications where schemas are typically used. The canonical example of a function which would logically have polymorphic schema is identity.

Our extension of the malli syntax to include schemas with parametric polymorphism was motivated by a desire for static analysis of Clojure code using malli schemas as annotations. In turn, this was used by our automatic-programming tool for synthesizing "schema safe" Clojure code from a unit test suite. The paper published at the GECCO conference can be found here, and the project is open source but not production ready.

If the malli team wants to embrace any of the schema extensions or code analysis concepts from our research, I would be happy to help port them over.

@ilmoraunio ilmoraunio added enhancement New feature or request for discussion Discussion is main focus of PR labels Mar 7, 2023
@ilmoraunio ilmoraunio moved this to 🇰‍🇼 Waiting in Metosin Open Source Backlog Mar 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request for discussion Discussion is main focus of PR
Projects
Status: 🇰‍🇼 Waiting
Development

Successfully merging a pull request may close this issue.

3 participants