Last active
December 27, 2015 23:29
-
-
Save sritchie/7406280 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns paddleguru.algebra | |
"Shared algebras for cljs and clj.") | |
(defprotocol Semigroup | |
(plus [l r])) | |
;; Shared extensions | |
(extend-protocol Semigroup | |
nil | |
(plus [l r] r)) | |
;; Clojure-specific extension | |
#+clj | |
(extend-protocol Semigroup | |
String | |
(plus [l r] (str l r)) | |
java.lang.Long | |
(plus [l r] (+ l r)) | |
clojure.lang.Ratio | |
(plus [l r] (+ l r)) | |
clojure.lang.IPersistentVector | |
(plus [l r] (concat l r)) | |
clojure.lang.IPersistentList | |
(plus [l r] (concat l r)) | |
clojure.lang.IPersistentMap | |
(plus [l r] | |
(merge-with plus l r))) | |
(defn monoid [zero] | |
(fn | |
([] zero) | |
([l r] (plus l r)))) | |
(def numeric-monoid | |
(monoid 0)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns paddleguru.algebra-test | |
(:require [clojure.test :refer :all] | |
[paddleguru.algebra :as a] | |
[simple-check.core :as sc] | |
[simple-check.generators :as gen] | |
[simple-check.properties :as prop :refer (for-all)])) | |
(defn test-property | |
([p] (test-property 100 p)) | |
([num-tests p] | |
(is (:result (sc/quick-check num-tests p))))) | |
(defn associative? | |
"Returns a property that tests that the supplied function is | |
associative for values produced by the supplied generator." | |
[generator f] | |
(prop/for-all [x generator | |
y generator | |
z generator] | |
(= (f (f x y) z) | |
(f x (f y z))))) | |
(defn semigroup-law | |
"Tests that the supplied generator produces values that can add | |
together with paddleguru.algebra/plus." | |
[type-name generator] | |
(testing (str type-name " forms a semigroup.") | |
(test-property | |
(associative? generator a/plus)))) | |
(defn identity? | |
"Returns a property that checks that the supplied zero is an | |
identity for the supplied generator, when passed in to the supplied | |
function." | |
[generator f zero] | |
(prop/for-all [x generator] | |
(and (= (f x zero) x) | |
(= (f zero x) x)))) | |
(defn monoid-laws | |
"Tests that the supplied monoid is both associative (in the 2-arg | |
case) and produces an identity in the no-arg case." | |
[type-name generator monoid] | |
(let [zero (monoid)] | |
(semigroup-law type-name generator) | |
(testing (format "%s and %s form a monoid." type-name zero) | |
(test-property | |
(identity? generator a/plus zero))))) | |
(deftest numeric-monoid-laws | |
;; Checks that Clojure's numeric types work monoid style. | |
(monoid-laws "int" gen/int a/numeric-monoid) | |
(monoid-laws "ratio" gen/ratio a/numeric-monoid)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment