use lens/c contracts to enforce immutability
for dicts, make sure the dict supports functional update
This commit is contained in:
parent
e976bea02c
commit
782b1f6f92
|
@ -1,6 +1,10 @@
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
|
|
||||||
(provide dict-ref-lens)
|
(require racket/contract/base)
|
||||||
|
(provide (contract-out
|
||||||
|
[dict-ref-lens
|
||||||
|
(-> any/c (lens/c functional-dict? any/c))]
|
||||||
|
))
|
||||||
|
|
||||||
(require racket/dict fancy-app "base/main.rkt")
|
(require racket/dict fancy-app "base/main.rkt")
|
||||||
(module+ test
|
(module+ test
|
||||||
|
@ -10,6 +14,9 @@
|
||||||
(make-lens (dict-ref _ key)
|
(make-lens (dict-ref _ key)
|
||||||
(dict-set _ key _)))
|
(dict-set _ key _)))
|
||||||
|
|
||||||
|
(define (functional-dict? v)
|
||||||
|
(and (dict? v) (dict-can-functional-set? v)))
|
||||||
|
|
||||||
(module+ test
|
(module+ test
|
||||||
(check-equal? (lens-transform/list '((a . 1) (b . 2) (c . 3)) (dict-ref-lens 'a) (* 100 _))
|
(check-equal? (lens-transform/list '((a . 1) (b . 2) (c . 3)) (dict-ref-lens 'a) (* 100 _))
|
||||||
'((a . 100) (b . 2) (c . 3))))
|
'((a . 100) (b . 2) (c . 3))))
|
||||||
|
|
33
lens/util/immutable.rkt
Normal file
33
lens/util/immutable.rkt
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#lang racket/base
|
||||||
|
|
||||||
|
(provide (all-defined-out))
|
||||||
|
|
||||||
|
;; The immutable? predicate only works for strings, byte-strings, vectors, hash-tables, and boxes.
|
||||||
|
|
||||||
|
(define (immutable-string? v)
|
||||||
|
(and (string? v) (immutable? v)))
|
||||||
|
|
||||||
|
(define (immutable-bytes? v)
|
||||||
|
(and (bytes? v) (immutable? v)))
|
||||||
|
|
||||||
|
(define (immutable-vector? v)
|
||||||
|
(and (vector? v) (immutable? v)))
|
||||||
|
|
||||||
|
(define (immutable-hash? v)
|
||||||
|
(and (hash? v) (immutable? v)))
|
||||||
|
|
||||||
|
(define (immutable-box? v)
|
||||||
|
(and (box? v) (immutable? v)))
|
||||||
|
|
||||||
|
(define (list->immutable-string lst)
|
||||||
|
(string->immutable-string (list->string lst)))
|
||||||
|
|
||||||
|
(define (list->immutable-vector lst)
|
||||||
|
(apply vector-immutable lst))
|
||||||
|
|
||||||
|
(define (build-immutable-string n f)
|
||||||
|
(string->immutable-string (build-string n f)))
|
||||||
|
|
||||||
|
(define (build-immutable-vector n f)
|
||||||
|
(vector->immutable-vector (build-vector n f)))
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
|
|
||||||
(provide hash-pick-lens)
|
(require racket/contract/base)
|
||||||
|
(provide (contract-out
|
||||||
|
[hash-pick-lens
|
||||||
|
(->* [] #:rest list? (lens/c immutable-hash? immutable-hash?))]
|
||||||
|
))
|
||||||
|
|
||||||
(require racket/list
|
(require racket/list
|
||||||
lens/base/main
|
lens/base/main
|
||||||
|
lens/util/immutable
|
||||||
"hash.rkt"
|
"hash.rkt"
|
||||||
"join.rkt")
|
"join.rkt")
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,13 @@
|
||||||
|
|
||||||
(provide
|
(provide
|
||||||
(contract-out
|
(contract-out
|
||||||
[hash-ref-lens (-> any/c lens?)]
|
[hash-ref-lens (-> any/c (lens/c immutable-hash? any/c))]
|
||||||
[hash-ref-nested-lens (->* () #:rest list? lens?)]))
|
[hash-ref-nested-lens (->* () #:rest list? (lens/c immutable-hash? any/c))]))
|
||||||
|
|
||||||
(require fancy-app
|
(require fancy-app
|
||||||
lens)
|
lens
|
||||||
|
lens/util/immutable
|
||||||
|
)
|
||||||
|
|
||||||
(module+ test
|
(module+ test
|
||||||
(require rackunit))
|
(require rackunit))
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
(require fancy-app
|
(require fancy-app
|
||||||
lens
|
lens
|
||||||
lens/util/list-pair-contract
|
lens/util/list-pair-contract
|
||||||
|
lens/util/immutable
|
||||||
unstable/sequence)
|
unstable/sequence)
|
||||||
|
|
||||||
(module+ test
|
(module+ test
|
||||||
|
@ -10,10 +11,10 @@
|
||||||
|
|
||||||
(provide
|
(provide
|
||||||
(contract-out
|
(contract-out
|
||||||
[lens-join/list (->* () #:rest (listof lens?) lens?)]
|
[lens-join/list (->* () #:rest (listof lens?) (lens/c any/c list?))]
|
||||||
[lens-join/hash (->* () #:rest (listof2 any/c lens?) lens?)]
|
[lens-join/hash (->* () #:rest (listof2 any/c lens?) (lens/c any/c immutable-hash?))]
|
||||||
[lens-join/vector (->* () #:rest (listof lens?) lens?)]
|
[lens-join/vector (->* () #:rest (listof lens?) (lens/c any/c immutable-vector?))]
|
||||||
[lens-join/string (->* () #:rest (listof lens?) lens?)]
|
[lens-join/string (->* () #:rest (listof lens?) (lens/c any/c immutable-string?))]
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
|
@ -84,9 +85,6 @@
|
||||||
(λ (tgt) (f tgt))
|
(λ (tgt) (f tgt))
|
||||||
(λ (tgt v) (f-inv v))))
|
(λ (tgt v) (f-inv v))))
|
||||||
|
|
||||||
(define (list->immutable-vector lst)
|
|
||||||
(apply vector-immutable lst))
|
|
||||||
|
|
||||||
(define list->vector-lens
|
(define list->vector-lens
|
||||||
(inverse-function-lens list->immutable-vector vector->list))
|
(inverse-function-lens list->immutable-vector vector->list))
|
||||||
|
|
||||||
|
@ -104,9 +102,6 @@
|
||||||
(define (lens-join/string . lenses)
|
(define (lens-join/string . lenses)
|
||||||
(lens-compose list->string-lens (apply lens-join/list lenses)))
|
(lens-compose list->string-lens (apply lens-join/list lenses)))
|
||||||
|
|
||||||
(define (list->immutable-string lst)
|
|
||||||
(string->immutable-string (list->string lst)))
|
|
||||||
|
|
||||||
(define list->string-lens
|
(define list->string-lens
|
||||||
(inverse-function-lens list->immutable-string string->list))
|
(inverse-function-lens list->immutable-string string->list))
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
|
|
||||||
(provide string-ref-lens
|
(require racket/contract/base)
|
||||||
string-pick-lens)
|
(provide (contract-out
|
||||||
|
[string-ref-lens
|
||||||
|
(-> exact-nonnegative-integer?
|
||||||
|
(lens/c immutable-string? char?))]
|
||||||
|
[string-pick-lens
|
||||||
|
(->* [] #:rest (listof exact-nonnegative-integer?)
|
||||||
|
(lens/c immutable-string? immutable-string?))]
|
||||||
|
))
|
||||||
|
|
||||||
(require fancy-app
|
(require fancy-app
|
||||||
lens/base/main
|
lens/base/main
|
||||||
|
lens/util/immutable
|
||||||
"join.rkt")
|
"join.rkt")
|
||||||
|
|
||||||
(module+ test
|
(module+ test
|
||||||
|
@ -17,12 +25,12 @@
|
||||||
(string-set _ i _)))
|
(string-set _ i _)))
|
||||||
|
|
||||||
(define (string-set s i c)
|
(define (string-set s i c)
|
||||||
(string->immutable-string
|
(build-immutable-string
|
||||||
(build-string (string-length s)
|
(string-length s)
|
||||||
(λ (j)
|
(λ (j)
|
||||||
(if (= i j)
|
(if (= i j)
|
||||||
c
|
c
|
||||||
(string-ref s j))))))
|
(string-ref s j)))))
|
||||||
|
|
||||||
(module+ test
|
(module+ test
|
||||||
(check-equal? (lens-view (string-ref-lens 2) "abc") #\c)
|
(check-equal? (lens-view (string-ref-lens 2) "abc") #\c)
|
||||||
|
|
|
@ -1,11 +1,21 @@
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
|
|
||||||
(provide vector-ref-lens
|
(require racket/contract/base)
|
||||||
vector-ref-nested-lens
|
(provide (contract-out
|
||||||
vector-pick-lens)
|
[vector-ref-lens
|
||||||
|
(-> exact-nonnegative-integer?
|
||||||
|
(lens/c immutable-vector? any/c))]
|
||||||
|
[vector-ref-nested-lens
|
||||||
|
(->* [] #:rest (listof exact-nonnegative-integer?)
|
||||||
|
(lens/c immutable-vector? any/c))]
|
||||||
|
[vector-pick-lens
|
||||||
|
(->* [] #:rest (listof exact-nonnegative-integer?)
|
||||||
|
(lens/c immutable-vector? immutable-vector?))]
|
||||||
|
))
|
||||||
|
|
||||||
(require fancy-app
|
(require fancy-app
|
||||||
lens/base/main
|
lens/base/main
|
||||||
|
lens/util/immutable
|
||||||
"arrow.rkt"
|
"arrow.rkt"
|
||||||
"join.rkt")
|
"join.rkt")
|
||||||
|
|
||||||
|
@ -19,12 +29,12 @@
|
||||||
(vector-set _ i _)))
|
(vector-set _ i _)))
|
||||||
|
|
||||||
(define (vector-set v i x)
|
(define (vector-set v i x)
|
||||||
(vector->immutable-vector
|
(build-immutable-vector
|
||||||
(build-vector (vector-length v)
|
(vector-length v)
|
||||||
(λ (j)
|
(λ (j)
|
||||||
(if (= i j)
|
(if (= i j)
|
||||||
x
|
x
|
||||||
(vector-ref v j))))))
|
(vector-ref v j)))))
|
||||||
|
|
||||||
(module+ test
|
(module+ test
|
||||||
(check-equal? (lens-view (vector-ref-lens 0) #(a b c)) 'a)
|
(check-equal? (lens-view (vector-ref-lens 0) #(a b c)) 'a)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user