Skip to content

Instantly share code, notes, and snippets.

@markhibberd
Last active August 29, 2015 13:56
Show Gist options
  • Save markhibberd/9245149 to your computer and use it in GitHub Desktop.
Save markhibberd/9245149 to your computer and use it in GitHub Desktop.
lens in clojure
;; repl session
(use 'lens)
(defrecord Address [street city postcode])
(defrecord Person [name age address])
(defrecord User [uid username identity password])
(def -postcode (mklens :postcode))
(def -city (mklens :city))
(def -street (mklens :street))
(def -address (mklens :address))
(def -age (mklens :age))
(def -name (mklens :name))
(def -uid (mklens :uid))
(def -username (mklens :username))
(def -identity (mklens :identity))
(def -password (mklens :password))
(-get -postcode home)
(-set -postcode home 500)
(-modify -postcode home #(+ 10 %))
(-get (comp -address -postcode) mark)
(-set (comp -address -postcode) mark 500)
(-get (comp -identity -address -postcode) user)
(-set (comp -identity -address -postcode) user 500)
(-modify (comp -identity -address -postcode) user #(+ 10 %))
(ns lens)
(defprotocol Functor
(fmap [functor f] "fmap :: f a -> (a -> b) -> f b"))
;; data Id a = Id { runId :: a }
(defrecord Id [runId]
Functor
(fmap [functor f]
(Id. (f (:runId functor)))))
;; data Const x a = Const { runConst :: x }
(defrecord Const [runConst]
Functor
(fmap [functor f]
(Const. (:runConst functor))))
;; get a value
(defn -get [lens a]
(:runConst ((lens (fn [z] (->Const z))) a)))
;; modify a value with f
(defn -modify [lens a f]
(:runId ((lens (fn [z] (->Id (f z)))) a)))
;; set a value with b
(defn -set [lens a b] (-modify lens a (fn [bb] b)))
;; build a lens from a get and set function
(defn lens [getter, setter]
(fn [b-fb]
(fn [a]
(fmap (b-fb (getter a))
(fn [b] (setter a b))))))
;;;;;; the actual lens functions, someone who can do macros should get rid of these in about 2 minutes
(defn mklens [func]
(lens
(fn [a] (func a))
(fn [a b] (assoc-in a [func] b))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment