#lang turnstile (provide Hash (for-syntax ~Hash) hash hash-set hash-ref (typed-out [[hash-ref/failure- : (∀ (K V) (→fn (Hash K V) K V V))] hash-ref/failure]) hash-has-key? hash-update (typed-out [[hash-update/failure- : (∀ (K V) (→fn (Hash K V) K (→fn V V) V (Hash K V)))] hash-update/failure]) hash-remove hash-map hash-keys hash-values hash-keys-subset? hash-count hash-empty? hash-union (typed-out [[hash-union/combine- : (∀ (K V) (→fn (Hash K V) (Hash K V) (→fn V V V) (Hash K V)))] hash-union/combine]) ) (require "core-types.rkt") (require (only-in "list.rkt" List)) (require (only-in "prim.rkt" Int Bool)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Immutable Hash Tables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define-container-type Hash #:arity = 2) (begin-for-syntax (define-splicing-syntax-class key-val-list #:attributes (items) (pattern (~seq k1 v1 rest:key-val-list) #:attr items #`((k1 v1) #,@#'rest.items)) (pattern (~seq) #:attr items #'()))) (define-typed-syntax (hash keys&vals:key-val-list) ≫ #:with ((key val) ...) #'keys&vals.items [⊢ key ≫ key- (⇒ : τ-k)] ... [⊢ val ≫ val- (⇒ : τ-val)] ... #:fail-unless (all-pure? #'(key- ... val- ...)) "gotta be pure" #:with together-again (stx-flatten #'((key- val-) ...)) -------------------------------------------------- [⊢ (#%app- hash- #,@#'together-again) (⇒ : (Hash (U τ-k ...) (U τ-val ...)))]) (require/typed racket/base ;; don't have a type for ConsPair #;[make-hash : (∀ (K V) (→fn (List (ConsPair K V)) (Hash K V)))] [hash-set : (∀ (K V) (→fn (Hash K V) K V (Hash K V)))] [hash-ref : (∀ (K V) (→fn (Hash K V) K V))] ;; TODO hash-ref/failure [hash-has-key? : (∀ (K V) (→fn (Hash K V) K Bool))] [hash-update : (∀ (K V) (→fn (Hash K V) K (→fn V V) (Hash K V)))] ;; TODO hash-update/failure [hash-remove : (∀ (K V) (→fn (Hash K V) K (Hash K V)))] [hash-map : (∀ (K V R) (→fn (Hash K V) (→fn K V R) (List R)))] [hash-keys : (∀ (K V) (→fn (Hash K V) (List K)))] [hash-values : (∀ (K V) (→fn (Hash K V) (List V)))] ;; TODO hash->list makes cons pairs #;[hash->list : (∀ (K V) (→fn (Hash K V) (List (ConsPair K V))))] [hash-keys-subset? : (∀ (K1 V1 K2 V2) (→fn (Hash K1 V1) (Hash K2 V2) Bool))] [hash-count : (∀ (K V) (→fn (Hash K V) Int))] [hash-empty? : (∀ (K V) (→fn (Hash K V) Bool))]) (require/typed racket/hash [hash-union : (∀ (K1 V1 K2 V2) (→fn (Hash K1 V1) (Hash K2 V2) (Hash (U K1 K2) (U V1 V2))))] ;; TODO - hash-union with #:combine ) (define- (hash-ref/failure- h k err) (#%app- hash-ref- h k err)) (define- (hash-update/failure- h k u err) (#%app- hash-update- h k u err)) (define- (hash-union/combine- h1 h2 combine) (#%app- hash-union- h1 h2 #:combine combine))