Created
January 24, 2012 03:22
-
-
Save twfarland/1667588 to your computer and use it in GitHub Desktop.
Difference lists with monoid functions in Racket
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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