Skip to content

Instantly share code, notes, and snippets.

@kbridge
Created August 14, 2021 14:32
Show Gist options
  • Save kbridge/3f6b0f22ea8a99b7be18c01a2e4a72d7 to your computer and use it in GitHub Desktop.
Save kbridge/3f6b0f22ea8a99b7be18c01a2e4a72d7 to your computer and use it in GitHub Desktop.
lens implementation
(def p1
{:name "Danny",
:address {:country "Finland",
:city "Helsinki"}})
(defn lens [key]
(let [getter key
setter (fn [s a] (assoc s key a))]
(fn [fmap]
(fn [f]
(fn [s]
(fmap #(setter s %)
(f (getter s))))))))
(defn fmap-const [f x] x)
(defn fmap-identity [f x] (f x))
; modify --> 'set' in haskell
(defn view [lens s] (((lens fmap-const) identity) s))
(defn over [lens f s] (((lens fmap-identity) (comp f identity)) s))
(defn modify [lens s a] (over lens (fn [_] a) s))
(def person-name (lens :name))
(def person-address (lens :address))
(def address-city (lens :city))
; test 1
(view person-address p1)
(view address-city (view person-address p1))
; test 2
(over person-name clojure.string/upper-case p1)
; test 3
(modify person-name p1 "xxx")
;-------------------------------------------------------------------------------
(defn compose-lens [a b]
(fn [fmap]
(comp (a fmap) (b fmap))))
(def person-address-city (compose-lens person-address address-city))
; tests
(view person-address-city p1)
(over person-address-city clojure.string/upper-case p1)
(modify person-address-city p1 "Espoo")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment