Skip to content
Brian Marick edited this page Jul 2, 2015 · 8 revisions

In keeping with the general principle of hiding libraries behind facades, I recommend you have one types.clj file for your project. It will redefine types/checked to refer to your type repo.

It can look like this:

(ns my.types
  (:require [structural-typing.type :as type]
            ...)
  ;; I know it's unfashionable, but in this case a separate `use` is clearer than :refer :all
  (:use [structural-typing.type :exclude [checked]]))


(def type-repo
  (-> empty-type-repo
      (named :Point
             (requires :x :y)
             {:x integer? :y integer?})

      ...))

(def checked (partial type/checked type-repo))

Then use it from other namespaces:

(ns my.services
  (:require [my.types :as type])
  ...)

(defn frob [payload]
  (some-> (type/checked :Point payload)
          form-triangle
          ...))

... or, if you use the Either monad:

(defn frob [payload]
   (monad-let [validated (type/checked :Point payload)
               triangle (form-triangle validated)
               ...]
     (right ...)))

Tip: if you find yourself wanting more than one type repository, perhaps that's a sign your one project contains more than one bounded context. Perhaps you should have two projects?