-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ [unitary-list] Contextual has unitary lists
Problem: - Unitary lists (lists with zero or one element) are useful for many things, as they are isomorphic to optional values but can also be spliced optionally into a list, a common pattern in macros. However, the contexutal library does not have a context for unitary lists. Solution: - Add a context for unitary lists.
- Loading branch information
Showing
3 changed files
with
89 additions
and
3 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
(in-package :cl-user) | ||
(defpackage :contextual-unitary-list | ||
(:use :cl :contextual) | ||
(:export #:make-unitary-list-context #:unitary-list-p #:unitary-list)) | ||
|
||
(in-package :contextual-unitary-list) | ||
|
||
(defun unitary-list-p (arg) | ||
"Return `T' if `ARG' is `NIL' or single element list." | ||
(or (null arg) | ||
(and (listp arg) | ||
(= 1 (length arg))))) | ||
|
||
(deftype unitary-list () | ||
'(satisfies unitary-list-p)) | ||
|
||
(defun make-unitary-list-context () | ||
"Return the monad operators for a unitary list. | ||
A unitary list is a list with 1 or zero elements" | ||
(make-instance 'monad-operators | ||
:mreturn #'list | ||
:flatmap (lambda (f mx) | ||
(and mx (funcall f (car mx)))))) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
(in-package :cl-user) | ||
(defpackage :contextual-unitary-list-test | ||
(:use :cl :5am :contextual :contextual-unitary-list) | ||
(:export :run-all-tests!)) | ||
|
||
(in-package :contextual-unitary-list-test) | ||
|
||
(def-suite unitary-list) | ||
|
||
(in-suite unitary-list) | ||
|
||
(defun run-all-tests! () | ||
(run! 'unitary-list)) | ||
|
||
|
||
(test type | ||
(is-true (unitary-list-p nil)) | ||
(is-true (unitary-list-p '(x))) | ||
(is-false (unitary-list-p '(x y))) | ||
(is-false (unitary-list-p "A pink elephant")) | ||
(is-true (typep nil 'unitary-list)) | ||
(is-true (typep '(x) 'unitary-list)) | ||
(is-false (typep '(x y) 'unitary-list)) | ||
(is-false (typep "A pink elephant" 'unitary-list))) | ||
|
||
(test functions | ||
(let ((context (make-unitary-list-context))) | ||
(is (equal '(x) (ctx-run context (pure 'x)))) | ||
(is (equal '("X") (ctx-run context (fmap #'symbol-name (pure 'x))))) | ||
(is (equal '("X") (ctx-run context (fapply (pure #'symbol-name) (pure 'x))))) | ||
(is (equal '((x y)) (ctx-run context (product (pure 'x) (pure 'y))))) | ||
(is (equal '("X") (ctx-run context (flatmap (lambda (x) (mreturn (symbol-name x))) (pure 'x))))))) | ||
|
||
(test binding | ||
(let ((context (make-unitary-list-context))) | ||
(is (equal '((7)) (ctx-run context | ||
(let*-fun ((x (pure 3)) | ||
(y (pure (1+ x)))) | ||
(+ x y))))) | ||
|
||
(is (equal '((7)) (ctx-run context | ||
(let-fun ((x (pure 3)) | ||
(y (pure 4))) | ||
(+ x y))))) | ||
|
||
(is (equal '(7) (ctx-run context | ||
(let-app ((x (pure 3)) | ||
(y (pure 4))) | ||
(+ x y))))) | ||
|
||
(is (equal '(7) (ctx-run context | ||
(let*-mon ((x (pure 3)) | ||
(y (pure (1+ x)))) | ||
(mreturn (+ x y)))))) | ||
|
||
(is (equal '(7) (ctx-run context | ||
(let-mon ((x (pure 3)) | ||
(y (pure 4))) | ||
(mreturn (+ x y)))))))) |