@effekt-lang/effekt 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +36 -0
  3. package/bin/effekt +0 -0
  4. package/bin/effekt.sh +2 -0
  5. package/libraries/chez/THIRD-PARTY.txt +11 -0
  6. package/libraries/chez/callcc/datatype.ss +188 -0
  7. package/libraries/chez/callcc/effekt.effekt +221 -0
  8. package/libraries/chez/callcc/effekt.ss +31 -0
  9. package/libraries/chez/callcc/seq.ss +44 -0
  10. package/libraries/chez/callcc/seq0.ss +69 -0
  11. package/libraries/chez/callcc/tail.ss +76 -0
  12. package/libraries/chez/callcc/tail0.ss +89 -0
  13. package/libraries/chez/common/effekt_matching.ss +100 -0
  14. package/libraries/chez/common/effekt_primitives.ss +97 -0
  15. package/libraries/chez/common/immutable/cslist.effekt +31 -0
  16. package/libraries/chez/common/immutable/dequeue.effekt +78 -0
  17. package/libraries/chez/common/immutable/list.effekt +643 -0
  18. package/libraries/chez/common/immutable/option.effekt +39 -0
  19. package/libraries/chez/common/immutable/result.effekt +29 -0
  20. package/libraries/chez/common/io/args.effekt +20 -0
  21. package/libraries/chez/common/mutable/array.effekt +27 -0
  22. package/libraries/chez/common/mutable/dict.effekt +30 -0
  23. package/libraries/chez/common/mutable/heap.effekt +12 -0
  24. package/libraries/chez/common/test.effekt +59 -0
  25. package/libraries/chez/common/text/pregexp.scm +772 -0
  26. package/libraries/chez/common/text/regex.effekt +33 -0
  27. package/libraries/chez/common/text/string.effekt +46 -0
  28. package/libraries/chez/lift/effekt.effekt +217 -0
  29. package/libraries/chez/lift/effekt.ss +118 -0
  30. package/libraries/chez/monadic/effekt.effekt +218 -0
  31. package/libraries/chez/monadic/effekt.ss +84 -0
  32. package/libraries/chez/monadic/seq0.ss +76 -0
  33. package/libraries/js/effekt.effekt +284 -0
  34. package/libraries/js/effekt_builtins.js +26 -0
  35. package/libraries/js/effekt_matching.js +79 -0
  36. package/libraries/js/effekt_runtime.js +385 -0
  37. package/libraries/js/immutable/dequeue.effekt +78 -0
  38. package/libraries/js/immutable/list.effekt +643 -0
  39. package/libraries/js/immutable/option.effekt +49 -0
  40. package/libraries/js/immutable/result.effekt +29 -0
  41. package/libraries/js/io/args.effekt +9 -0
  42. package/libraries/js/io/async.effekt +28 -0
  43. package/libraries/js/io/async.js +2 -0
  44. package/libraries/js/io/file.effekt +50 -0
  45. package/libraries/js/io/file_include.js +13 -0
  46. package/libraries/js/mutable/array.effekt +98 -0
  47. package/libraries/js/mutable/heap.effekt +32 -0
  48. package/libraries/js/mutable/map.effekt +32 -0
  49. package/libraries/js/test.effekt +59 -0
  50. package/libraries/js/text/regex.effekt +34 -0
  51. package/libraries/js/text/string.effekt +64 -0
  52. package/libraries/js/unsafe/cont.effekt +11 -0
  53. package/libraries/js/web/dom.effekt +45 -0
  54. package/libraries/llvm/buffer.c +181 -0
  55. package/libraries/llvm/effekt.effekt +243 -0
  56. package/libraries/llvm/forward-declare-c.ll +24 -0
  57. package/libraries/llvm/hole.c +11 -0
  58. package/libraries/llvm/immutable/list.effekt +678 -0
  59. package/libraries/llvm/immutable/option.effekt +53 -0
  60. package/libraries/llvm/immutable/result.effekt +29 -0
  61. package/libraries/llvm/io/args.effekt +24 -0
  62. package/libraries/llvm/io.c +24 -0
  63. package/libraries/llvm/main.c +39 -0
  64. package/libraries/llvm/rts.ll +619 -0
  65. package/libraries/llvm/sanity.c +16 -0
  66. package/libraries/llvm/text/string.effekt +179 -0
  67. package/libraries/llvm/types.c +20 -0
  68. package/libraries/ml/effekt.effekt +267 -0
  69. package/libraries/ml/effekt.sml +63 -0
  70. package/libraries/ml/immutable/dequeue.effekt +81 -0
  71. package/libraries/ml/immutable/list.effekt +674 -0
  72. package/libraries/ml/immutable/option.effekt +53 -0
  73. package/libraries/ml/immutable/result.effekt +29 -0
  74. package/libraries/ml/immutable/seq.effekt +903 -0
  75. package/libraries/ml/internal/option.effekt +18 -0
  76. package/libraries/ml/io/args.effekt +41 -0
  77. package/libraries/ml/mutable/array.effekt +43 -0
  78. package/libraries/ml/random.effekt +85 -0
  79. package/libraries/ml/test.effekt +60 -0
  80. package/libraries/ml/text/regex.effekt +107 -0
  81. package/libraries/ml/text/string.effekt +81 -0
  82. package/licenses/THIRD-PARTY.txt +21 -0
  83. package/licenses/apache-2.0 - license-2.0.txt +202 -0
  84. package/licenses/eclipse public license, version 2.0 - epl-2.0.html +61 -0
  85. package/licenses/kiama-license.txt +373 -0
  86. package/licenses/kiama-readme.txt +186 -0
  87. package/licenses/mit license - mit-license.html +769 -0
  88. package/licenses/the apache software license, version 2.0 - license-2.0.txt +202 -0
  89. package/licenses/the bsd license - bsd-license.html +762 -0
  90. package/licenses/the mit license - mit.html +769 -0
  91. package/package.json +26 -18
@@ -0,0 +1,76 @@
1
+ ;;; tail.ss
2
+ ;;; Copyright (c) 2005, R. Kent Dybvig, Simon L. Peyton Jones, and Amr Sabry
3
+
4
+ ;;; Tail-recursive implementation of the operators
5
+
6
+ ;(case-sensitive #t)
7
+
8
+ (define-syntax pushPrompt
9
+ (syntax-rules ()
10
+ [(_ p e1 e2 ...)
11
+ ($pushPrompt p (lambda () e1 e2 ...))]))
12
+
13
+ (define-syntax pushSubCont
14
+ (syntax-rules ()
15
+ [(_ subk e1 e2 ...)
16
+ ($pushSubCont subk (lambda () e1 e2 ...))]))
17
+
18
+ (define abort)
19
+ (define mk)
20
+ (define base-k)
21
+
22
+ (define (PushSeg/t k seq)
23
+ (if (eqv? k base-k)
24
+ seq
25
+ (PushSeg k seq)))
26
+
27
+ (define ($pushPrompt p th)
28
+ (call/cc (lambda (k)
29
+ (set! mk (PushP p (PushSeg/t k mk)))
30
+ (abort th))))
31
+
32
+ (define (state init th)
33
+ (define b (box init))
34
+ (set! mk (PushState b #f mk))
35
+ (th b))
36
+
37
+ (define (getter ref)
38
+ (lambda () (unbox ref)))
39
+
40
+ (define (setter ref)
41
+ (lambda (v) (set-box! ref v)))
42
+
43
+ (define (withSubCont p f)
44
+ (let-values ([(subk mk*) (splitSeq p mk)])
45
+ (set! mk mk*)
46
+ (call/cc (lambda (k)
47
+ (abort (lambda () (f (PushSeg/t k subk))))))))
48
+
49
+ (define ($pushSubCont subk th)
50
+ (call/cc (lambda (k)
51
+ (set! mk (appendSeq subk (PushSeg/t k mk)))
52
+ (abort th))))
53
+
54
+ (define newPrompt (lambda () (string #\p)))
55
+
56
+ (define (run th)
57
+ (set! mk (EmptyS))
58
+ (underflow
59
+ (call/cc/base
60
+ (lambda (k_1)
61
+ (set! base-k k_1)
62
+ ((call/cc (lambda (k_2)
63
+ (set! abort k_2)
64
+ (abort th))))))))
65
+
66
+ (define (underflow v)
67
+ (Seq-case mk
68
+ [(EmptyS) v]
69
+ [(PushP _ mk*) (set! mk mk*) (underflow v)]
70
+ [(PushState b _ mk*) (set! mk mk*) (underflow v)]
71
+ [(PushSeg k mk*) (set! mk mk*) (k v)]))
72
+
73
+ (define (go)
74
+ (new-cafe
75
+ (lambda (x)
76
+ (run (lambda () (eval x))))))
@@ -0,0 +1,89 @@
1
+ ;;; tail.ss
2
+ ;;; Copyright (c) 2005, R. Kent Dybvig, Simon L. Peyton Jones, and Amr Sabry
3
+
4
+ ;;; Tail-recursive implementation of the operators
5
+
6
+ ;(case-sensitive #t)
7
+
8
+ (define-syntax pushPrompt
9
+ (syntax-rules ()
10
+ [(_ p e1 e2 ...)
11
+ ($pushPrompt p (lambda () e1 e2 ...))]))
12
+
13
+ (define-syntax pushSubCont
14
+ (syntax-rules ()
15
+ [(_ subk e1 e2 ...)
16
+ ($pushSubCont subk (lambda () e1 e2 ...))]))
17
+
18
+ (define abort)
19
+ (define mk)
20
+ (define base-k)
21
+
22
+ (define ($pushPrompt p th)
23
+ (call/cc (lambda (k)
24
+ (pushFrame k)
25
+ (set! mk (cons (make-Stack (list) (make-arena) p) mk))
26
+ (abort th))))
27
+
28
+ (define (with-region body)
29
+ (let* ([stack (car mk)]
30
+ [arena (Stack-arena stack)])
31
+ (body arena)))
32
+
33
+ (define (withSubCont p f)
34
+ (call/cc (lambda (k)
35
+ (pushFrame k)
36
+ (let-values ([(subk mk*) (splitSeq p mk)])
37
+ (set! mk mk*)
38
+ (abort (lambda () (f subk)))))))
39
+
40
+ (define (pushFrame f)
41
+ (if (eqv? f base-k) (values)
42
+ (if (null? mk) (error "ERROR! Cannot push on empty meta cont" #f)
43
+ (let* ([stack (car mk)]
44
+ [frames (Stack-frames stack)]
45
+ [arena (Stack-arena stack)]
46
+ [prompt (Stack-prompt stack)]
47
+ [rest (cdr mk)])
48
+ (set! mk (cons (make-Stack (cons f frames) arena prompt) rest))))))
49
+
50
+ (define ($pushSubCont subk th)
51
+ (call/cc (lambda (k)
52
+ (pushFrame k)
53
+ (set! mk (appendSeq subk mk))
54
+ (abort th))))
55
+
56
+ (define newPrompt (lambda () (string #\p)))
57
+
58
+ (define (run th)
59
+ (define global (make-Stack '() (make-arena) (newPrompt)))
60
+ (set! mk (list global))
61
+ (underflow
62
+ (call/cc
63
+ (lambda (k_1)
64
+ (set! base-k k_1)
65
+ ((call/cc (lambda (k_2)
66
+ (set! abort k_2)
67
+ (abort th))))))))
68
+
69
+ (define (underflow v)
70
+ (if (null? mk) v
71
+ (let* ([stack (car mk)]
72
+ [frames (Stack-frames stack)]
73
+ [arena (Stack-arena stack)]
74
+ [prompt (Stack-prompt stack)]
75
+ [rest (cdr mk)])
76
+ (if (null? frames) (begin (set! mk rest) (underflow v))
77
+ (begin
78
+ (set! mk (cons (make-Stack (cdr frames) arena prompt) rest))
79
+ ((car frames) v))))))
80
+
81
+
82
+ (define-syntax shift0-at
83
+ (syntax-rules ()
84
+ [(_ P id exp ...)
85
+ (withSubCont
86
+ P
87
+ (lambda (s)
88
+ (let ([id (lambda (v) (pushSubCont s v))])
89
+ exp ...)))]))
@@ -0,0 +1,100 @@
1
+ ; Matcher = (SCRUTINEE, ANS -> () -> R, () -> R, (ANS -> () -> R) -> R) -> R
2
+
3
+ (define done (lambda (matched) (matched)))
4
+
5
+ (define (any m matched failed k)
6
+ (k (matched m)))
7
+
8
+ (define (ignore m matched failed k)
9
+ (k matched))
10
+
11
+ (define (literal l)
12
+ (lambda (m matched failed k)
13
+ (if (equal_impl m l)
14
+ (k matched)
15
+ (failed))))
16
+
17
+ (define (bind p)
18
+ (lambda (m matched failed k)
19
+ (p m (matched m) failed k)))
20
+
21
+ ;; for this record
22
+ ; (define-record Pair (fst snd))
23
+
24
+ ;; this is what we need to generate
25
+ ; (define (match-Pair p1 p2)
26
+ ; (lambda (m matched failed k)
27
+ ; (if (Pair? m)
28
+ ; (p1 (Pair-fst m) matched failed (lambda (matched)
29
+ ; (p2 (Pair-snd m) matched failed k)))
30
+ ; (failed))))
31
+
32
+
33
+ (define-syntax define-matcher
34
+ (syntax-rules ()
35
+ [(_ name pred ())
36
+ (define (name)
37
+ (lambda (sc matched failed k)
38
+ (if (pred sc) (k matched) (failed))))]
39
+ [(_ name pred ((p1 sel1) (p2 sel2) ...))
40
+ (define (name p1 p2 ...)
41
+ (lambda (m matched failed k)
42
+ ;; has correct tag?
43
+ (if (pred m)
44
+ (match-fields m matched failed k ([p1 sel1] [p2 sel2] ...))
45
+ (failed))))]))
46
+
47
+ (define-syntax match-fields
48
+ (syntax-rules ()
49
+ [(_ m matched failed k ()) (k matched)]
50
+ [(_ m matched failed k ([p1 sel1] [p2 sel2] ...))
51
+ (p1 (sel1 m) matched failed (lambda (matched)
52
+ (match-fields m matched failed k ([p2 sel2] ...))))]))
53
+
54
+
55
+ ; forces the pattern match
56
+ (define-syntax pattern-match
57
+ (syntax-rules ()
58
+ [(_ m ()) (raise "no patterns provided")]
59
+ [(_ m ([p1 k1] [p2 k2]...))
60
+ (p1 m k1 (lambda () (pattern-match m ([p2 k2] ...))) done)]))
61
+
62
+ ;; Examples
63
+
64
+ ; (define-matcher match-Pair2 Pair? ([p1 Pair-fst] [p2 Pair-snd]))
65
+
66
+ ; (define (match sc p matched)
67
+ ; (p sc matched abort done))
68
+
69
+ ; (display (match (make-Pair 1 2)
70
+ ; (match-Pair2 any any)
71
+ ; (lambda (x) (lambda (y) (lambda () (+ x y))))))
72
+
73
+ ; (display (match 3
74
+ ; (match-Pair2 any any)
75
+ ; (lambda (x) (lambda (y) (lambda () (+ x y))))))
76
+
77
+ ; (display (match (make-Pair 1 2)
78
+ ; (match-Pair2 any (match-Pair2 ignore any))
79
+ ; (lambda (x) (lambda (y) (lambda () (+ x y))))))
80
+
81
+ ; (display (match (make-Pair 1 (make-Pair 2 3))
82
+ ; (match-Pair2 any (match-Pair2 ignore any))
83
+ ; (lambda (x) (lambda (y) (lambda () (+ x y))))))
84
+
85
+ ; (display (match (make-Pair (make-Pair 1 2) (make-Pair 3 4))
86
+ ; (match-Pair (match-Pair ignore any) (match-Pair ignore any))
87
+ ; (lambda (x) (lambda (y) (lambda () (+ x y))))))
88
+
89
+ ; (display (match (make-Pair (make-Pair 1 2) (make-Pair 10 15))
90
+ ; (match-Pair2 (match-Pair2 any ignore) (match-Pair2 ignore any))
91
+ ; (lambda (x) (lambda (y) (lambda () (+ x y))))))
92
+
93
+ ; (display (match (make-Pair (make-Pair 1 2) (make-Pair 10 15))
94
+ ; (match-Pair2 (match-Pair2 any ignore) (match-Pair2 ignore any))
95
+ ; (lambda (x) (lambda (y) (lambda () (+ x y))))))
96
+
97
+ ; (display (pattern-match (make-Pair 1 2)
98
+ ; ([(match-Pair2 (match-Pair2 any ignore) (match-Pair2 ignore any))
99
+ ; (lambda (x) (lambda (y) (lambda () (+ x y))))]
100
+ ; [any (lambda (x) (lambda () (Pair-snd x)))])))
@@ -0,0 +1,97 @@
1
+ (define (show_impl obj)
2
+ (cond
3
+ [(number? obj) (show-number obj)]
4
+ [(string? obj) obj]
5
+ [(boolean? obj) (if obj "true" "false")]
6
+ ; [(record? obj)
7
+ ; (let* ([rtd (record-rtd obj)]
8
+ ; [name (symbol->string (record-type-name rtd))])
9
+ ; ;; how can we show the fields?
10
+ ; (string-append name))]
11
+ [(list? obj) (map show_impl obj)]
12
+ [(record? obj) (show-record obj)]
13
+ [else (generic-show obj)]))
14
+
15
+ (define (generic-show obj)
16
+ (define out (open-output-string))
17
+ (write obj out)
18
+ (get-output-string out))
19
+
20
+ ; conform with the JS way of printing numbers
21
+ (define (show-number n)
22
+ (if (integer? n) (number->string (exact n)) (number->string n)))
23
+
24
+ ; here we use eval to find the show function defined with the record...
25
+ ; (define (show-record rec)
26
+ ; (let* ([rtd (record-rtd rec)]
27
+ ; [showName (string-append "show" (generic-show (record-type-name rtd)))]
28
+ ; [showFun (eval (string->symbol showName))])
29
+ ; (showFun rec)))
30
+
31
+ ; we needed to add a unique id to the types in order to prevent duplicate definitions
32
+ ; now for printing, we need to strip the unique id (starting with $) again.
33
+ (define (strip-type-name tpe)
34
+ (define out "")
35
+ (define found #f)
36
+ (for-each
37
+ (lambda (el)
38
+ (if (char=? el #\$) (set! found #t) #f)
39
+ (if found #f (set! out (string-append out (string el)))))
40
+ (string->list tpe))
41
+ out)
42
+
43
+ (define (show-record rec)
44
+ (let* ([rtd (record-rtd rec)]
45
+ [unique-tpe (generic-show (record-type-name rtd))]
46
+ [tpe (strip-type-name unique-tpe)]
47
+ [fields (record-type-field-names rtd)]
48
+ [n (vector-length fields)])
49
+ (define out (string-append tpe "("))
50
+ (do ([i 0 (+ i 1)])
51
+ ((= i n))
52
+ (set! out (string-append out (show_impl ((record-accessor rtd i) rec))))
53
+ (if (< i (- n 1)) (set! out (string-append out ", "))))
54
+ (set! out (string-append out ")"))
55
+ out))
56
+
57
+
58
+
59
+ (define (println_impl obj)
60
+ (display (show_impl obj))
61
+ (newline))
62
+
63
+ (define (equal_impl obj1 obj2)
64
+ (equal? obj1 obj2))
65
+
66
+ (define-syntax thunk
67
+ (syntax-rules ()
68
+ [(_ e ...) (lambda () e ...)]))
69
+
70
+ ;; Benchmarking utils
71
+
72
+ ; time in milliseconds
73
+ (define (timed block)
74
+ (let ([before (current-time)])
75
+ (block)
76
+ (let ([after (current-time)])
77
+ (seconds (time-difference after before)))))
78
+
79
+ (define (seconds diff)
80
+ (+ (time-second diff) (/ (time-nanosecond diff) 1000000000.0)))
81
+
82
+ (define (measure block warmup iterations)
83
+ (define (run n)
84
+ (if (<= n 0)
85
+ '()
86
+ (begin
87
+ (collect)
88
+ (cons (timed block) (run (- n 1))))))
89
+ (begin
90
+ (run warmup)
91
+ (run iterations)))
92
+
93
+ (define (hole)
94
+ (raise
95
+ (condition
96
+ (make-error)
97
+ (make-message-condition "not implemented"))))
@@ -0,0 +1,31 @@
1
+ module immutable/cslist
2
+
3
+ import immutable/list
4
+
5
+ // a chez scheme cons list
6
+ extern type CSList[A]
7
+ extern pure def cons[A](el: A, rest: CSList[A]): CSList[A] =
8
+ "(cons ${el} ${rest})"
9
+
10
+ extern pure def nil[A](): CSList[A] =
11
+ "(list)"
12
+
13
+ extern pure def isEmpty[A](l: CSList[A]): Boolean =
14
+ "(null? ${l})"
15
+
16
+ // unsafe!
17
+ extern pure def head[A](l: CSList[A]): A =
18
+ "(car ${l})"
19
+
20
+ // unsafe!
21
+ extern pure def tail[A](l: CSList[A]): CSList[A] =
22
+ "(cdr ${l})"
23
+
24
+
25
+ def toChez[A](l: List[A]): CSList[A] = l match {
26
+ case Nil() => nil()
27
+ case Cons(a, rest) => cons(a, rest.toChez)
28
+ }
29
+
30
+ def fromChez[A](l: CSList[A]): List[A] =
31
+ if (l.isEmpty) Nil() else Cons(l.head, l.tail.fromChez)
@@ -0,0 +1,78 @@
1
+ module immutable/dequeue
2
+
3
+ import immutable/list
4
+ import immutable/option
5
+
6
+ // An implementation of a functional dequeue, using Okasaki's
7
+ // bankers dequeue implementation.
8
+ //
9
+ // Translation from the Haskell implementation:
10
+ // https://hackage.haskell.org/package/dequeue-0.1.12/docs/src/Data-Dequeue.html#Dequeue
11
+ record Dequeue[R](front: List[R], frontSize: Int, rear: List[R], rearSize: Int)
12
+
13
+ def emptyQueue[R](): Dequeue[R] = Dequeue(Nil(), 0, Nil(), 0)
14
+
15
+ def isEmpty[R](dq: Dequeue[R]): Boolean = dq match {
16
+ case Dequeue(f, fs, r, rs) => (fs == 0) && (rs == 0)
17
+ }
18
+
19
+ def size[R](dq: Dequeue[R]): Int = dq match {
20
+ case Dequeue(f, fs, r, rs) => fs + rs
21
+ }
22
+
23
+ def first[R](dq: Dequeue[R]): Option[R] = dq match {
24
+ case Dequeue(f, fs, r, rs) =>
25
+ if ((fs == 0) && (rs == 1)) { r.headOption }
26
+ else { f.headOption }
27
+ }
28
+
29
+ def last[R](dq: Dequeue[R]): Option[R] = dq match {
30
+ case Dequeue(f, fs, r, rs) =>
31
+ if ((fs == 1) && (rs == 0)) { f.headOption }
32
+ else { r.headOption }
33
+ }
34
+
35
+ def check[R](dq: Dequeue[R]): Dequeue[R] = dq match {
36
+ case Dequeue(f, fs, r, rs) =>
37
+ val c = 4;
38
+ val size1 = (fs + rs) / 2;
39
+ val size2 = (fs + rs) - size1;
40
+
41
+ if (fs > c * rs + 1) {
42
+ val front = f.take(size1);
43
+ val rear = r.append(f.drop(size1).reverse);
44
+ Dequeue(front, size1, rear, size2)
45
+ } else if (rs > c * fs + 1) {
46
+ val front = f.append(r.drop(size1).reverse);
47
+ val rear = r.take(size1);
48
+ Dequeue(front, size2, rear, size1)
49
+ } else {
50
+ dq
51
+ }
52
+ }
53
+
54
+ def pushFront[R](dq: Dequeue[R], el: R): Dequeue[R] = dq match {
55
+ case Dequeue(f, fs, r, rs) => Dequeue(Cons(el, f), fs + 1, r, rs).check
56
+ }
57
+
58
+ def popFront[R](dq: Dequeue[R]): Option[(R, Dequeue[R])] = dq match {
59
+ case Dequeue(Nil(), fs, Cons(x, Nil()), rs) =>
60
+ Some((x, emptyQueue()))
61
+ case Dequeue(Nil(), fs, r, rs) =>
62
+ None()
63
+ case Dequeue(Cons(x, rest), fs, r, rs) =>
64
+ Some((x, Dequeue(rest, fs - 1, r, rs).check))
65
+ }
66
+
67
+ def pushBack[R](dq: Dequeue[R], el: R): Dequeue[R] = dq match {
68
+ case Dequeue(f, fs, r, rs) => Dequeue(f, fs, Cons(el, r), rs + 1).check
69
+ }
70
+
71
+ def popBack[R](dq: Dequeue[R]): Option[(R, Dequeue[R])] = dq match {
72
+ case Dequeue(Cons(x, Nil()), fs, Nil(), rs) =>
73
+ Some((x, emptyQueue()))
74
+ case Dequeue(f, fs, Nil(), rs) =>
75
+ None()
76
+ case Dequeue(f, fs, Cons(x, rest), rs) =>
77
+ Some((x, Dequeue(f, fs, rest, rs - 1).check))
78
+ }