aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarvin Borner2022-08-17 14:15:22 +0200
committerMarvin Borner2022-08-17 14:15:22 +0200
commitfee84dce1ed2ac8448b93b7bfaff934bd3c72041 (patch)
tree43ca66d3cce234a0278b844e81fce0496f62a82b
parentd7e6c86554acc2bf92d3adb40863d1f7351f8918 (diff)
Many additional functions
-rw-r--r--src/Parser.hs2
-rw-r--r--std/Combinator.bruijn2
-rw-r--r--std/List.bruijn170
-rw-r--r--std/Logic.bruijn56
-rw-r--r--std/Number.bruijn10
5 files changed, 172 insertions, 68 deletions
diff --git a/src/Parser.hs b/src/Parser.hs
index ddd74e2..9a4a793 100644
--- a/src/Parser.hs
+++ b/src/Parser.hs
@@ -18,7 +18,7 @@ sc :: Parser ()
sc = void $ char ' '
specialChar :: Parser Char
-specialChar = oneOf "!?*@.:;+-_#$%^&<>/|~='"
+specialChar = oneOf "!?*@.:;+-_#$%^&<>/\\|~='"
infixOperator :: Parser String
infixOperator = some specialChar
diff --git a/std/Combinator.bruijn b/std/Combinator.bruijn
index a1ffd1a..115ea93 100644
--- a/std/Combinator.bruijn
+++ b/std/Combinator.bruijn
@@ -28,6 +28,8 @@ B''' [[[[3 (2 (1 0))]]]]
# Cardinal combinator: Reverse arguments
C [[[2 0 1]]]
+\( C
+
# Cardinal once removed combinator
C* [[[[3 2 0 1]]]]
diff --git a/std/List.bruijn b/std/List.bruijn
index 44d833f..8683a43 100644
--- a/std/List.bruijn
+++ b/std/List.bruijn
@@ -60,19 +60,82 @@ index Z [[[case-some]]]
case-index =?1 ^0 (2 --1 ~0)
case-end empty
-(!!) C index
+(!!) \index
:test (((+1) : ((+2) : ((+3) : empty))) !! (+0)) ((+1))
:test (((+1) : ((+2) : ((+3) : empty))) !! (+2)) ((+3))
:test (((+1) : ((+2) : ((+3) : empty))) !! (-1)) (empty)
:test (((+1) : ((+2) : ((+3) : empty))) !! (+3)) (empty)
-# reverses a list
-reverse Z [[[case-some]]] case-empty
- case-some <>?0 case-end case-rev
- case-rev 2 (^0 : 1) ~0
+# applies a left fold on a list
+foldl Z [[[[case-some]]]]
+ case-some <>?0 case-end case-fold
+ case-fold 3 2 (2 1 ^0) ~0
case-end 1
- case-empty empty
+
+:test ((foldl add (+0) ((+1) : ((+2) : ((+3) : empty)))) =? (+6)) (true)
+:test ((foldl sub (+6) ((+1) : ((+2) : ((+3) : empty)))) =? (+0)) (true)
+
+# foldl without starting value
+foldl1 [[foldl 1 ^0 ~0]]
+
+# applies a right fold on a list
+foldr [[[Z [[case-some]] case-empty]]]
+ case-some <>?0 case-end case-fold
+ case-fold 4 ^0 (1 ~0)
+ case-end 3
+ case-empty 0
+
+:test ((foldr add (+0) ((+1) : ((+2) : ((+3) : empty)))) =? (+6)) (true)
+:test ((foldr sub (+2) ((+1) : ((+2) : ((+3) : empty)))) =? (+0)) (true)
+
+# foldr without starting value
+foldr1 [[foldl 1 ^0 ~0]]
+
+# applies or to all list elements
+lor? foldr or? false
+
+||( lor?
+
+:test (||(true : (true : empty))) (true)
+:test (||(true : (false : empty))) (true)
+:test (||(false : (false : empty))) (false)
+
+# applies and to all list elements
+land? foldr and? true
+
+&&( land?
+
+:test (&&(true : (true : empty))) (true)
+:test (&&(true : (false : empty))) (false)
+:test (&&(false : (false : empty))) (false)
+
+# multiplies all values in list
+product foldl mul (+1)
+
+Π product
+
+:test (Π ((+1) : ((+2) : ((+3) : empty)))) ((+6))
+
+# adds all values in list
+sum foldl add (+0)
+
+Σ sum
+
+:test (Σ ((+1) : ((+2) : ((+3) : empty)))) ((+6))
+
+# returns max value of list
+lmax foldl1 max
+
+:test (lmax ((+1) : ((+3) : ((+2) : empty)))) ((+3))
+
+# returns min value of list
+lmin foldl1 min
+
+:test (lmin ((+2) : ((+1) : ((+0) : empty)))) ((+0))
+
+# reverses a list
+reverse foldl \cons empty
<~>( reverse
@@ -110,32 +173,13 @@ map Z [[[case-some]]]
:test (inc <$> ((+1) : ((+2) : ((+3) : empty)))) ((+2) : ((+3) : ((+4) : empty)))
-# applies a left fold on a list
-foldl Z [[[[case-some]]]]
- case-some <>?0 case-end case-fold
- case-fold 3 2 (2 1 ^0) ~0
- case-end 1
-
-:test ((foldl add (+0) ((+1) : ((+2) : ((+3) : empty)))) =? (+6)) (true)
-:test ((foldl sub (+6) ((+1) : ((+2) : ((+3) : empty)))) =? (+0)) (true)
-
-# applies a right fold on a list
-foldr [[[Z [[case-some]] case-empty]]]
- case-some <>?0 case-end case-fold
- case-fold 4 ^0 (1 ~0)
- case-end 3
- case-empty 0
-
-:test ((foldr add (+0) ((+1) : ((+2) : ((+3) : empty)))) =? (+6)) (true)
-:test ((foldr sub (+2) ((+1) : ((+2) : ((+3) : empty)))) =? (+0)) (true)
-
# filters a list based on a predicate
filter Z [[[case-some]]]
case-some <>?0 case-end case-filter
case-filter 1 ^0 (cons ^0) I (2 1 ~0)
case-end empty
-(<#>) C filter
+(<#>) \filter
:test (((+1) : ((+0) : ((+3) : empty))) <#> zero?) ((+0) : empty)
@@ -157,6 +201,18 @@ init Z [[case-some]]
:test (init ((+1) : ((+2) : ((+3) : empty)))) ((+1) : ((+2) : empty))
+# concatenates a list of lists to one list
+concat foldr append empty
+
+# TODO: ?
+# :test (concat ((((+1) : ((+2) : empty)) : ((+3) : ((+4) : empty))) : empty)) ((+1) : ((+2) : ((+3) : ((+4) : empty))))
+:test (concat ("a" : ("b" : empty))) ("ab")
+
+# maps a function returning list of list and concatenates
+concat-map [foldr (append . 0) empty]
+
+:test (concat-map [-0 : (0 : empty)] ((+1) : ((+2) : empty))) ((-1) : ((+1) : ((-2) : ((+2) : empty))))
+
# zips two lists discarding excess elements
zip Z [[[case-some]]]
case-some <>?1 case-end case-zip
@@ -197,7 +253,7 @@ drop Z [[[case-some]]]
:test (drop (+2) ((+1) : ((+2) : ((+3) : empty)))) ((+3) : empty)
-# removes elements while a predicate is satisfied
+# removes elements from list while a predicate is satisfied
drop-while Z [[[case-some]]]
case-some <>?0 case-end case-drop
case-drop 1 ^0 (2 1 ~0) 0
@@ -205,7 +261,41 @@ drop-while Z [[[case-some]]]
:test (drop-while zero? ((+0) : ((+0) : ((+1) : empty)))) ((+1) : empty)
-# removes duplicates from list based on eq predicate (keeps only first occurrence)
+# returns true if any element in a list matches a predicate
+any? [lor? . (map 0)]
+
+:test (any? (\gre? (+2)) ((+1) : ((+2) : ((+3) : empty)))) (true)
+:test (any? (\gre? (+2)) ((+1) : ((+2) : ((+2) : empty)))) (false)
+
+# returns true if all elements in a list match a predicate
+all? [land? . (map 0)]
+
+:test (all? (\gre? (+2)) ((+3) : ((+4) : ((+5) : empty)))) (true)
+:test (all? (\gre? (+2)) ((+4) : ((+3) : ((+2) : empty)))) (false)
+
+# returns true if element is part of a list based on eq predicate
+in? [[any? (\1 0)]]
+
+:test (in? eq? (+3) ((+1) : ((+2) : ((+3) : empty)))) (true)
+:test (in? eq? (+0) ((+1) : ((+2) : ((+3) : empty)))) (false)
+
+# returns true if all elements of one list are equal to corresponding elements of other list
+# TODO: Better name
+leq? [[[land? (zip-with 2 1 0)]]]
+
+:test (leq? eq? ((+1) : ((+2) : empty)) ((+1) : ((+2) : empty))) (true)
+:test (leq? eq? ((+1) : ((+2) : empty)) ((+2) : ((+2) : empty))) (false)
+:test (leq? eq? empty empty) (true)
+
+# removes first element that match an eq predicate
+remove Z [[[[case-some]]]]
+ case-some <>?0 case-end case-remove
+ case-remove (2 ^0 1) ~0 (^0 : (3 2 1 ~0))
+ case-end empty
+
+:test (remove eq? (+2) ((+1) : ((+2) : ((+3) : ((+2) : empty))))) ((+1) : ((+3) : ((+2) : empty)))
+
+# removes duplicates from list based on eq predicate (keeps first occurrence)
nub Z [[[case-some]]]
case-some <>?0 case-end case-nub
case-nub ^0 : (2 1 (~0 <#> [!(2 0 ^1)]))
@@ -214,20 +304,26 @@ nub Z [[[case-some]]]
:test (nub eq? ((+1) : ((+2) : ((+3) : empty)))) (((+1) : ((+2) : ((+3) : empty))))
:test (nub eq? ((+1) : ((+2) : ((+1) : empty)))) (((+1) : ((+2) : empty)))
+# returns a list with infinite-times a element
+repeat Z [[case-some]]
+ case-some 0 : (1 0)
+
+:test (take (+3) (repeat (+4))) ((+4) : ((+4) : ((+4) : empty)))
+
# returns a list with n-times a element
-repeat Z [[[case-some]]]
- case-some =?1 case-end case-repeat
- case-repeat 0 : (2 --1 0)
- case-end empty
+replicate [[take 1 (repeat 0)]]
+
+:test (replicate (+3) (+4)) ((+4) : ((+4) : ((+4) : empty)))
+
+# returns an infinite list repeating a finite list
+cycle Z [[case-some]]
+ case-some 0 ++ (1 0)
-:test (repeat (+5) (+4)) (((+4) : ((+4) : ((+4) : ((+4) : ((+4) : empty))))))
-:test (repeat (+1) (+4)) (((+4) : empty))
-:test (repeat (+0) (+4)) (empty)
+:test (take (+6) (cycle "ab")) ("ababab")
# returns a list with infinite-times previous (or start) value applied to a function
iterate Z [[[case-some]]]
- case-some case-iterate
- case-iterate 0 : (2 1 (1 0))
+ case-some 0 : (2 1 (1 0))
:test (take (+5) (iterate inc (+0))) (((+0) : ((+1) : ((+2) : ((+3) : ((+4) : empty))))))
:test (take (+2) (iterate dec (+5))) (((+5) : ((+4) : empty)))
diff --git a/std/Logic.bruijn b/std/Logic.bruijn
index 4174712..94e737d 100644
--- a/std/Logic.bruijn
+++ b/std/Logic.bruijn
@@ -9,17 +9,17 @@ true K
false KI
# inverts boolean value
-not [0 false true]
+not! [0 false true]
-!( not
+!( not!
:test (!true) (false)
:test (!false) (true)
# true if both args are true
-and [[1 0 false]]
+and? [[1 0 false]]
-(&&) and
+(&&) and?
:test (true && true) (true)
:test (true && false) (false)
@@ -27,17 +27,17 @@ and [[1 0 false]]
:test (false && false) (false)
# true if not both args are true
-nand [[1 0 1 false true]]
+nand? [[1 0 1 false true]]
-:test (nand true true) (false)
-:test (nand true false) (true)
-:test (nand false true) (true)
-:test (nand false false) (true)
+:test (nand? true true) (false)
+:test (nand? true false) (true)
+:test (nand? false true) (true)
+:test (nand? false false) (true)
# true if one of the args is true
-or [[1 true 0]]
+or? [[1 true 0]]
-(||) or
+(||) or?
:test (true || true) (true)
:test (true || false) (true)
@@ -45,28 +45,28 @@ or [[1 true 0]]
:test (false || false) (false)
# true if both args are false
-nor [[1 1 0 false true]]
+nor? [[1 1 0 false true]]
-:test (nor true true) (false)
-:test (nor true false) (false)
-:test (nor false true) (false)
-:test (nor false false) (true)
+:test (nor? true true) (false)
+:test (nor? true false) (false)
+:test (nor? false true) (false)
+:test (nor? false false) (true)
# true if args are not same bools
-xor [[1 (not 0) 0]]
+xor? [[1 !0 0]]
-:test (xor true true) (false)
-:test (xor true false) (true)
-:test (xor false true) (true)
-:test (xor false false) (false)
+:test (xor? true true) (false)
+:test (xor? true false) (true)
+:test (xor? false true) (true)
+:test (xor? false false) (false)
# true if both args are same bools
-xnor [[1 0 (not 0)]]
+xnor? [[1 0 !0]]
-:test (xnor true true) (true)
-:test (xnor true false) (false)
-:test (xnor false true) (false)
-:test (xnor false false) (true)
+:test (xnor? true true) (true)
+:test (xnor? true false) (false)
+:test (xnor? false true) (false)
+:test (xnor? false false) (true)
# if first arg is true, exec first exp; else second exp
# this function is generally redundant
@@ -81,7 +81,7 @@ if [[[2 1 0]]]
:test ((false ?! true) false) (false)
# mathematical implies definition
-implies [[or (not 1) 0]]
+implies [[!1 || 0]]
(=>?) implies
@@ -91,7 +91,7 @@ implies [[or (not 1) 0]]
:test (false =>? false) (true)
# mathematical iff (if and only if) definition
-iff [[and (implies 1 0) (implies 0 1)]]
+iff [[(1 =>? 0) && (0 =>? 1)]]
(<=>?) iff
diff --git a/std/Number.bruijn b/std/Number.bruijn
index 81e6636..c7cce1b 100644
--- a/std/Number.bruijn
+++ b/std/Number.bruijn
@@ -299,7 +299,7 @@ gre? [[>?(1 - 0)]]
# returns whether number is less than other number
# smaller numbers should be second argument (performance)
-les? [[<?(1 - 0)]]
+les? \gre?
(<?) les?
@@ -319,7 +319,7 @@ leq? [[!(1 >? 0)]]
# returns whether number is greater than or equal to other number
# smaller numbers should be second argument (performance)
-geq? [[!(1 <? 0)]]
+geq? \leq?
(>=?) geq?
@@ -327,6 +327,12 @@ geq? [[!(1 <? 0)]]
:test ((+2) >=? (+2)) (true)
:test ((+3) >=? (+2)) (true)
+# returns max number of two
+max [[(1 <=? 0) 0 1]]
+
+# returns min number of two
+min [[(1 <=? 0) 1 0]]
+
# muls two balanced ternary numbers (can introduce leading 0s)
mul [[1 (+0) a< a> a=]]
a< [^=0 - 1]