Is Clojure is pervasively Monoidic? – nil checks are Bad Code Smell

Is Clojure pervasively monodic?

A monoid is…

  1. A set, S
  2. An operation, : S × S -> S
  3. An element of S, e : 1 -> S

…satisfying these laws:

  1. (a • b) • c = a • (b • c), for all a, b and c in S
  2. e • a = a = a • e, for all a in S

Consider concat:

(concat (concat [:a] [:b]) [:c]) => [:a :b :c]
(concat [:a] (concat [:b] [:c])) => [:a :b :c]
(concat [:a] []) => [:a]
(concat [] [:a]) => [:a]
(concat [] []) => []

For some operations, nil can be used as an empty seq:

(concat [:a] nil) => [:a]
(concat nil [:a]) => [:a]

… and with car-position key lookups:

(:a {:a 1}) => 1
(:a nil) => nil

However, this is not true for car-position map or set applications:

({:a 1} :a) => 1
(#{:a} :a) => :a
(nil :a) => ERROR

Map is not strictly monoidic, but nil can be substituted for empty seqs:

(map even? [1 2]) => [false true]
(map even? nil)   => ()