Skip to content

Latest commit

 

History

History
157 lines (116 loc) · 4.81 KB

README.md

File metadata and controls

157 lines (116 loc) · 4.81 KB

typed.clj.malli

Malli integration.

Releases and Dependency Information

Latest stable release is 1.0.20.

deps.edn JAR dependency information:

  org.typedclojure/typed.clj.malli {:mvn/version "1.0.20"}

deps.edn Git dependency information:

  • Note: use clj -Sresolve to resolve the :tag to a :sha
  org.typedclojure/typed.clj.malli
  {:git/url "https://github.com/typedclojure/typedclojure"
   :deps/root "typed/clj.malli"
   :tag "1.0.20"}

Leiningen dependency information:

[org.typedclojure/typed.clj.malli "1.0.20"]

Maven dependency information:

<dependency>
  <groupId>org.typedclojure</groupId>
  <artifactId>typed.clj.malli</artifactId>
  <version>1.0.20</version>
</dependency>

Documentation

API Reference

Usage

Note: the following assumes you have the Clojure core type annotations and full type checker on your classpath. Here is a quick way to create a REPL to follow this tutorial with:

clj -Sdeps '{:deps {org.typedclojure/typed.clj.malli {:mvn/version "1.0.20"}
                    ;; only needed if omitting typed.clj.checker
                    org.typedclojure/typed.lib.clojure {:mvn/version "1.0.20"}
                    org.typedclojure/typed.clj.checker {:mvn/version "1.0.20"}}}'

Now you can execute each form by copying it into this REPL.

(require '[malli.core :as m]
         '[typed.clj.malli :as tm]
         '[clojure.core.typed :as t])

Validation

typed.clj.malli/validate is a wrapper for malli.core/validate.

See also:

;; normally, `validate` takes schemas
(m/validate int? "1")
;=> false

(m/validate int? 1)
;=> true

;; the typed variant (note `tm` namespace) takes Typed Clojure types
(tm/validate t/AnyInteger "1")
;=> false

(tm/validate t/AnyInteger 1)
;=> true

;; it can be used to coerce values in a way the type checker understands
(t/cf (fn [x]
        {:pre [(tm/validate t/AnyInteger x)]}
        (inc x))
      [t/Any :-> Number])
;=> [[t/Any -> Number] {:then tt, :else ff}]

;; tm/explain works oppositely
(t/cf (fn [x]
        {:pre [(not (tm/explain t/AnyInteger x))]}
        (inc x))
      [t/Any :-> Number])
;=> [[t/Any -> Number] {:then tt, :else ff}]

Parsing values

typed.clj.malli/parse is a wrapper for malli.core/parse.

See also:

;; normally, `parse` takes schemas
(m/parse [:orn
          [:int int?]
          [:bool boolean?]]
         1)
;=> [:int 1]

;; `tm/parse` takes Typed Clojure types and infers the return value.
;; use `::tm/name` to specify `:orn` tags (bare union currently unsupported).
(t/defalias ParsableIntOrBool
  (t/U ^{::tm/name :int} t/AnyInteger
       ^{::tm/name :bool} t/Bool))

(tm/parse ParsableIntOrBool true)
;=> [:bool true] : (t/U
;                    (t/HVec [(t/Val :int) t/AnyInteger])
;                    (t/HVec [(t/Val :bool) t/Bool])
;                    (t/Val :malli.core/invalid))

;; example using `tm/parse` to type check a function
(t/cf
  (t/fn [a :- ParsableIntOrBool] :- t/AnyInteger
    (let [prs (tm/parse ParsableIntOrBool a)]
      (assert (not= ::m/invalid prs))
      (case (first prs)
        :int (second prs)))))
;=> [[ParsableIntOrBool -> t/AnyInteger] {:then tt, :else ff}]

License

Copyright © Ambrose Bonnaire-Sergeant, Rich Hickey & contributors.

Licensed under the EPL (see the file epl-v10.html).