From e70d62ac5c22b52f03777f66d0e8fd11516a0cb2 Mon Sep 17 00:00:00 2001 From: AlephAlpha Date: Thu, 1 Aug 2024 17:06:18 +0800 Subject: [PATCH] :curry: --- CHANGELOG.md | 7 +++-- doc/Builtins.md | 55 ++++++++++++++++++++++++++++++++++++ src/Nekomata/Builtin.hs | 48 ++++++++++++++++++++++++------- src/Nekomata/Builtin/List.hs | 8 +++++- 4 files changed, 104 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 699864d..a4b4682 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,17 +2,18 @@ ## 0.7.0.0 -- Unreleased -* Added examples to the documentation of some built-in functions. +* Added examples to the documentation of built-in functions. Examples for particles will be added in the future. * Fixed some errors in the documentation. * Fixed a bug in `\binomial`. Now it returns `0` when the second argument is negative. -* Fixed a bug in `\factor`. +* Fixed a bug in `\factor`. In earlier versions, it may return incorrect results. ### Breaking changes * Some modules in the library are no longer exposed. * The built-in function `\normalForm` is removed, because it is never used, and its semantics are not well-defined. -* `\divisors` now returns a sorted list of divisors. +* The result of `\divisors` is now sorted. * `\intersect` and `\union` are now multiset intersection and union. +* `\bifurcate` now works on numbers. If the input is a number, it is converted to the range from 0 to the number - 1. ## 0.6.1.0 -- 2024-06-07 diff --git a/doc/Builtins.md b/doc/Builtins.md index 633f702..7168759 100644 --- a/doc/Builtins.md +++ b/doc/Builtins.md @@ -2201,6 +2201,11 @@ If there are multiple shortest ones, return any of them non-deterministically. This function is non-deterministic. +__Examples__: + +- `[[1,2,3],[4],[5,6]]ş` → `[4]` +- `[[1,2],[3,4],[5],[6]]ş` → `[5] [6]` + ### `longest` (`Ş`, `1 -> 1`) Get the longest one in a list of lists. @@ -2209,40 +2214,85 @@ If there are multiple longest ones, return any of them non-deterministically. This function is non-deterministic. +__Examples__: + +- `[[1,2,3],[4],[5,6]]Ş` → `[1,2,3]` +- `[[1,2],[3,4],[5],[6]]Ş` → `[1,2] [3,4]` + ### `tuple` (`ŧ`, `2 -> 1`) Create a list with length n, whose elements are taken from another list. +If the first argument is a number, it is converted to a range from 0 to that number minus 1. + This function is non-deterministic, and automatically vectorized on the second argument. +__Examples__: + +- `[1,2] 2ŧ` → `[1,1] [1,2] [2,1] [2,2]` +- `2 2ŧ` → `[0,0] [0,1] [1,0] [1,1]` + ### `bifurcate` (`ƀ`, `1 -> 2`) Push the reverse of a list without popping the original list. +If the argument is a number, it is converted to a range from 0 to that number minus 1. + +__Examples__: + +- `[1,2,3]ƀÐ` → `[[1,2,3],[3,2,1]]` +- `3ƀÐ` → `[[0,1,2],[2,1,0]]` + ### `flatten` (`V`, `1 -> 1`) Flatten a nested list. If the argument is a number or a char, it is converted to a singleton list. +__Examples__: + +- `[[1,2],[3,4]]V` → `[1,2,3,4]` +- `[1,2,3]V` → `[1,2,3]` +- `[1,[2,[3,4]]]V` → `[1,2,3,4]` +- `1V` → `[1]` + ### `pad` (`Ḟ`, `1 -> 1`) Pad a nested list with zeros to make it rectangular. If the argument is a number or a char, it is unchanged. +__Examples__: + +- `[[1,2],[3]]Ḟ` → `[[1,2],[3,0]]` +- `[[[1,2,3],[4,5]],6]Ḟ` → `[[[1,2,3],[4,5,0]],[[6,0,0],[0,0,0]]]` +- `[1,2]Ḟ` → `[1,2]` +- `1Ḟ` → `1` + ### `ordering` (`õ`, `1 -> 1`) Get the ordering of a list. The n'th element of the result is the index of the n'th element in the sorted list. +__Examples__: + +- `[3,1,2]õ` → `[1,2,0]` +- `[1,2,3]õ` → `[0,1,2]` +- `[1,1,2]õ` → `[0,1,2]` + ### `elem` (`ē`, `2 -> 1`) Check if an element is in a list. If it is, push the element, otherwise fail. +__Examples__: + +- `2 [1,2,3]ē` → `2` +- `4 [1,2,3]ē` → Fail +- `'a "abc"ē` → `'a'` + ### `filterBy` (`ḟ`, `2 -> 1`) Filter a list by whether the corresponding element in another list is not failed. @@ -2251,6 +2301,11 @@ If the first list also contains failed items, those items are also removed. Fail when the two lists are of different lengths. +__Examples__: + +- `[1,2,3,4] [1,0,1,0]Zḟ` → `[1,3]` +- `[1,2,3,4] [1,0,1]Zḟ` → Fail + ## Particles ### `onBoth` (`ᵃ`, `(0 -> n) -> (0 -> 2 * n) or (m -> n) -> (m + 1 -> 2 * n) where m > 0`) diff --git a/src/Nekomata/Builtin.hs b/src/Nekomata/Builtin.hs index 96fa6e0..d86c62a 100644 --- a/src/Nekomata/Builtin.hs +++ b/src/Nekomata/Builtin.hs @@ -1997,7 +1997,9 @@ builtins = \If there are multiple shortest ones, \ \return any of them non-deterministically.\n\ \This function is non-deterministic." - [] + [ ("[[1,2,3],[4],[5,6]]ş", all_ ["[4]"]) + , ("[[1,2],[3,4],[5],[6]]ş", all_ ["[5]", "[6]"]) + ] , Builtin "longest" 'Ş' @@ -2006,22 +2008,32 @@ builtins = \If there are multiple longest ones, \ \return any of them non-deterministically.\n\ \This function is non-deterministic." - [] + [ ("[[1,2,3],[4],[5,6]]Ş", all_ ["[1,2,3]"]) + , ("[[1,2],[3,4],[5],[6]]Ş", all_ ["[1,2]", "[3,4]"]) + ] , Builtin "tuple" 'ŧ' tuple "Create a list with length n, \ \whose elements are taken from another list.\n\ + \If the first argument is a number, \ + \it is converted to a range from 0 to that number minus 1.\n\ \This function is non-deterministic, \ \and automatically vectorized on the second argument." - [] + [ ("[1,2] 2ŧ", all_ ["[1,1]", "[1,2]", "[2,1]", "[2,2]"]) + , ("2 2ŧ", all_ ["[0,0]", "[0,1]", "[1,0]", "[1,1]"]) + ] , Builtin "bifurcate" 'ƀ' bifurcate - "Push the reverse of a list without popping the original list." - [] + "Push the reverse of a list without popping the original list.\n\ + \If the argument is a number, \ + \it is converted to a range from 0 to that number minus 1." + [ ("[1,2,3]ƀÐ", all_ ["[[1,2,3],[3,2,1]]"]) + , ("3ƀÐ", all_ ["[[0,1,2],[2,1,0]]"]) + ] , Builtin "flatten" 'V' @@ -2029,14 +2041,22 @@ builtins = "Flatten a nested list.\n\ \If the argument is a number or a char, \ \it is converted to a singleton list." - [] + [ ("[[1,2],[3,4]]V", all_ ["[1,2,3,4]"]) + , ("[1,2,3]V", all_ ["[1,2,3]"]) + , ("[1,[2,[3,4]]]V", all_ ["[1,2,3,4]"]) + , ("1V", all_ ["[1]"]) + ] , Builtin "pad" 'Ḟ' pad "Pad a nested list with zeros to make it rectangular.\n\ \If the argument is a number or a char, it is unchanged." - [] + [ ("[[1,2],[3]]Ḟ", all_ ["[[1,2],[3,0]]"]) + , ("[[[1,2,3],[4,5]],6]Ḟ", all_ ["[[[1,2,3],[4,5,0]],[[6,0,0],[0,0,0]]]"]) + , ("[1,2]Ḟ", all_ ["[1,2]"]) + , ("1Ḟ", all_ ["1"]) + ] , Builtin "ordering" 'õ' @@ -2044,14 +2064,20 @@ builtins = "Get the ordering of a list.\n\ \The n'th element of the result is the index of the n'th element \ \in the sorted list." - [] + [ ("[3,1,2]õ", all_ ["[1,2,0]"]) + , ("[1,2,3]õ", all_ ["[0,1,2]"]) + , ("[1,1,2]õ", all_ ["[0,1,2]"]) + ] , Builtin "elem" 'ē' elem' "Check if an element is in a list.\n\ \If it is, push the element, otherwise fail." - [] + [ ("2 [1,2,3]ē", all_ ["2"]) + , ("4 [1,2,3]ē", all_ []) + , ("'a \"abc\"ē", all_ ["'a'"]) + ] , Builtin "filterBy" 'ḟ' @@ -2061,7 +2087,9 @@ builtins = \If the first list also contains failed items, \ \those items are also removed.\n\ \Fail when the two lists are of different lengths." - [] + [ ("[1,2,3,4] [1,0,1,0]Zḟ", all_ ["[1,3]"]) + , ("[1,2,3,4] [1,0,1]Zḟ", all_ []) + ] ] -- | The map from names to builtin functions diff --git a/src/Nekomata/Builtin/List.hs b/src/Nekomata/Builtin/List.hs index fdb34ca..44d3a5e 100644 --- a/src/Nekomata/Builtin/List.hs +++ b/src/Nekomata/Builtin/List.hs @@ -768,7 +768,13 @@ tuple = binaryVecArg2 tuple' | otherwise = Fail bifurcate :: Function -bifurcate = dup .* reverse' +bifurcate = unary2 bifurcate' + where + bifurcate' _ (DNumT x) = liftNum12 (bifurcate_ . fromList . range0_) x + bifurcate' _ (DListT xs) = liftList12 bifurcate_ xs + bifurcate' _ _ = (Fail, Fail) + bifurcate_ :: ListTry a -> Try (TryList a, TryList a) + bifurcate_ xs = Val (Val xs, reverse_ Nil xs) flatten :: Function flatten = unary flatten'