-
Notifications
You must be signed in to change notification settings - Fork 9
Recommended setup
Brian Marick edited this page Sep 30, 2015
·
8 revisions
The structural-typing.type
class contains both functions that create types and also those that check them. That's convenient for examples and playing around at the repo. In your code, I recommend you isolate type creation in one namespace, create in it checking functions that hide the type repo, and require
that namespace in all the rest of your code.
A file that creates types
A file that uses them
Here's an example stripped down to the essentials.
(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 [built-like all-built-like
<>built-like <>all-built-like
built-like?]]))
(def type-repo
(-> empty-type-repo
(named :Point
(requires :x :y)
{:x integer? :y integer?})
...))
(def built-like (partial type/built-like type-repo))
(def all-built-like (partial type/all-built-like type-repo))
(def <>built-like (partial type/<>built-like type-repo))
(def <>all-built-like (partial type/<>all-built-like type-repo))
(def built-like? (partial type/built-like? 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?