Skip to content

Instantly share code, notes, and snippets.

@twfarland
Created January 24, 2012 03:22
Show Gist options
  • Save twfarland/1667588 to your computer and use it in GitHub Desktop.
Save twfarland/1667588 to your computer and use it in GitHub Desktop.
Difference lists with monoid functions in Racket
#lang racket
;; ## DIFFERENCE LISTS
;; # Constructors
;; Diff a is [a] -> [a]
;; implemented as - diff :: a... -> ([a] -> [a])
(define diff
(λ ls (curry append ls)))
;; list->diff :: [a] -> Diff a
(define list->diff
(curry append))
;; diff->list :: Diff a -> [a]
(define (diff->list d)
(d empty))
;; # Comparison
;; diff=? :: Diff a -> Diff a -> Bool
;; needs to convert to list first
(define (diff=? d1 d2)
(equal? (diff->list d1)
(diff->list d2)))
;; # Functions that allow Diffs to act as a monoid:
;; diff-empty :: Diff
(define diff-empty
(curry append empty))
;; diff-append :: Diff... -> Diff
;; no need for mconcat implementation because of arbitrary length args
(define diff-append
(λ ds (foldr compose diff-empty ds)))
;; # Convenience
;; append-as-diff :: [a]... -> [a]
(define append-as-diff
(λ ls (diff->list
(foldr (λ (l acc)
(compose (list->diff l) acc))
diff-empty ls))))
;; # Example data
(define d1 (diff 1 2 3))
(define d2 (diff 4 5 6))
(define d3 (diff 7 8 9))
(define l1 (list 1 2 3))
(define l2 (list 4 5 6))
(define l3 (list 7 8 9))
;; # Correctness tests
(equal? (diff->list d1)
l1)
(diff=? (diff-append d1 d2 d3)
(diff 1 2 3 4 5 6 7 8 9))
(diff=? (diff-append diff-empty diff-empty)
diff-empty)
(diff=? (diff-append diff-empty d1)
(diff-append d1 diff-empty))
(equal? (append l1 l2 l3)
(append-as-diff l1 l2 l3))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment