From 452567c150d7a6b1345130ec7f19bbbe9e799c77 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sun, 30 Oct 2022 00:41:29 -0500 Subject: [PATCH 1/4] Update ST FFI to use StFns --- bower.json | 4 +- src/Data/Array/ST.js | 135 ++++++++++----------------------- src/Data/Array/ST.purs | 114 ++++++++++++++++++---------- src/Data/Array/ST/Partial.js | 18 +---- src/Data/Array/ST/Partial.purs | 14 ++-- 5 files changed, 125 insertions(+), 160 deletions(-) diff --git a/bower.json b/bower.json index bc2bff74..13c330c7 100644 --- a/bower.json +++ b/bower.json @@ -23,7 +23,7 @@ "purescript-partial": "^4.0.0", "purescript-prelude": "^6.0.0", "purescript-safe-coerce": "^2.0.0", - "purescript-st": "^6.0.0", + "purescript-st": "^6.2.0", "purescript-tailrec": "^6.0.0", "purescript-tuples": "^7.0.0", "purescript-unfoldable": "^6.0.0", @@ -35,4 +35,4 @@ "purescript-const": "^6.0.0", "purescript-minibench": "^4.0.0" } -} +} \ No newline at end of file diff --git a/src/Data/Array/ST.js b/src/Data/Array/ST.js index 7dfff146..3f4fa21a 100644 --- a/src/Data/Array/ST.js +++ b/src/Data/Array/ST.js @@ -1,107 +1,57 @@ -function newSTArray () { +function newSTArray() { return []; } export { newSTArray as new }; -export const peekImpl = function (just) { - return function (nothing) { - return function (i) { - return function (xs) { - return function () { - return i >= 0 && i < xs.length ? just(xs[i]) : nothing; - }; - }; - }; - }; +export const peekImpl = function (just, nothing, i, xs) { + return i >= 0 && i < xs.length ? just(xs[i]) : nothing; }; -export const poke = function (i) { - return function (a) { - return function (xs) { - return function () { - var ret = i >= 0 && i < xs.length; - if (ret) xs[i] = a; - return ret; - }; - }; - }; +export const pokeImpl = function (i, a, xs) { + var ret = i >= 0 && i < xs.length; + if (ret) xs[i] = a; + return ret; }; -export const length = function (xs) { - return function () { - return xs.length; - }; +export const lengthImpl = function (xs) { + return xs.length; }; -export const popImpl = function (just) { - return function (nothing) { - return function (xs) { - return function () { - return xs.length > 0 ? just(xs.pop()) : nothing; - }; - }; - }; +export const popImpl = function (just, nothing, xs) { + return xs.length > 0 ? just(xs.pop()) : nothing; }; -export const pushAll = function (as) { - return function (xs) { - return function () { - return xs.push.apply(xs, as); - }; - }; +export const pushAllImpl = function (as, xs) { + return xs.push.apply(xs, as); }; -export const shiftImpl = function (just) { - return function (nothing) { - return function (xs) { - return function () { - return xs.length > 0 ? just(xs.shift()) : nothing; - }; - }; - }; +export const shiftImpl = function (just, nothing, xs) { + return xs.length > 0 ? just(xs.shift()) : nothing; }; -export const unshiftAll = function (as) { - return function (xs) { - return function () { - return xs.unshift.apply(xs, as); - }; - }; +export const unshiftAllImpl = function (as, xs) { + return xs.unshift.apply(xs, as); }; -export const splice = function (i) { - return function (howMany) { - return function (bs) { - return function (xs) { - return function () { - return xs.splice.apply(xs, [i, howMany].concat(bs)); - }; - }; - }; - }; +export const spliceImpl = function (i, howMany, bs, xs) { + return xs.splice.apply(xs, [i, howMany].concat(bs)); }; -export const unsafeFreeze = function (xs) { - return function () { - return xs; - }; -}; +function unsafeFreezeThawImpl(xs) { + return xs; +} -export const unsafeThaw = function (xs) { - return function () { - return xs; - }; -}; +export const unsafeFreezeImpl = unsafeFreezeThawImpl; + +export const unsafeThawImpl = unsafeFreezeThawImpl; function copyImpl(xs) { - return function () { - return xs.slice(); - }; + return xs.slice(); } -export const freeze = copyImpl; +export const freezeImpl = copyImpl; -export const thaw = copyImpl; +export const thawImpl = copyImpl; export const sortByImpl = (function () { function mergeFromTo(compare, fromOrdering, xs1, xs2, from, to) { @@ -127,8 +77,7 @@ export const sortByImpl = (function () { if (c > 0) { xs1[k++] = y; ++j; - } - else { + } else { xs1[k++] = x; ++i; } @@ -141,26 +90,18 @@ export const sortByImpl = (function () { } } - return function (compare) { - return function (fromOrdering) { - return function (xs) { - return function () { - if (xs.length < 2) return xs; + return function (compare, fromOrdering, xs) { + if (xs.length < 2) return xs; - mergeFromTo(compare, fromOrdering, xs, xs.slice(0), 0, xs.length); + mergeFromTo(compare, fromOrdering, xs, xs.slice(0), 0, xs.length); - return xs; - }; - }; - }; + return xs; }; })(); -export const toAssocArray = function (xs) { - return function () { - var n = xs.length; - var as = new Array(n); - for (var i = 0; i < n; i++) as[i] = { value: xs[i], index: i }; - return as; - }; +export const toAssocArrayImpl = function (xs) { + var n = xs.length; + var as = new Array(n); + for (var i = 0; i < n; i++) as[i] = { value: xs[i], index: i }; + return as; }; diff --git a/src/Data/Array/ST.purs b/src/Data/Array/ST.purs index b4e6a87f..eb437b9c 100644 --- a/src/Data/Array/ST.purs +++ b/src/Data/Array/ST.purs @@ -31,8 +31,9 @@ module Data.Array.ST import Prelude -import Control.Monad.ST as ST import Control.Monad.ST (ST, Region) +import Control.Monad.ST as ST +import Control.Monad.ST.Uncurried (STFn1, STFn2, STFn3, STFn4, runSTFn1, runSTFn2, runSTFn3, runSTFn4) import Data.Maybe (Maybe(..)) -- | A reference to a mutable array. @@ -61,8 +62,8 @@ run st = ST.run (st >>= unsafeFreeze) withArray :: forall h a b . (STArray h a -> ST h b) - -> Array a - -> ST h (Array a) + -> Array a + -> ST h (Array a) withArray f xs = do result <- thaw xs _ <- f result @@ -70,17 +71,29 @@ withArray f xs = do -- | O(1). Convert a mutable array to an immutable array, without copying. The mutable -- | array must not be mutated afterwards. -foreign import unsafeFreeze :: forall h a. STArray h a -> ST h (Array a) +unsafeFreeze :: forall h a. STArray h a -> ST h (Array a) +unsafeFreeze = runSTFn1 unsafeFreezeImpl + +foreign import unsafeFreezeImpl :: forall h a. STFn1 (STArray h a) h (Array a) -- | O(1) Convert an immutable array to a mutable array, without copying. The input -- | array must not be used afterward. -foreign import unsafeThaw :: forall h a. Array a -> ST h (STArray h a) +unsafeThaw :: forall h a. Array a -> ST h (STArray h a) +unsafeThaw = runSTFn1 unsafeThawImpl + +foreign import unsafeThawImpl :: forall h a. STFn1 (Array a) h (STArray h a) -- | Create a new, empty mutable array. foreign import new :: forall h a. ST h (STArray h a) +thaw + :: forall h a + . Array a + -> ST h (STArray h a) +thaw = runSTFn1 thawImpl + -- | Create a mutable copy of an immutable array. -foreign import thaw :: forall h a. Array a -> ST h (STArray h a) +foreign import thawImpl :: forall h a. STFn1 (Array a) h (STArray h a) -- | Sort a mutable array in place. Sorting is stable: the order of equal -- | elements is preserved. @@ -89,14 +102,11 @@ sort = sortBy compare -- | Remove the first element from an array and return that element. shift :: forall h a. STArray h a -> ST h (Maybe a) -shift = shiftImpl Just Nothing +shift = runSTFn3 shiftImpl Just Nothing foreign import shiftImpl :: forall h a - . (forall b. b -> Maybe b) - -> (forall b. Maybe b) - -> STArray h a - -> ST h (Maybe a) + . STFn3 (forall b. b -> Maybe b) (forall b. Maybe b) (STArray h a) h (Maybe a) -- | Sort a mutable array in place using a comparison function. Sorting is -- | stable: the order of elements is preserved if they are equal according to @@ -106,17 +116,14 @@ sortBy . (a -> a -> Ordering) -> STArray h a -> ST h (STArray h a) -sortBy comp = sortByImpl comp case _ of +sortBy comp = runSTFn3 sortByImpl comp case _ of GT -> 1 EQ -> 0 LT -> -1 foreign import sortByImpl :: forall a h - . (a -> a -> Ordering) - -> (Ordering -> Int) - -> STArray h a - -> ST h (STArray h a) + . STFn3 (a -> a -> Ordering) (Ordering -> Int) (STArray h a) h (STArray h a) -- | Sort a mutable array in place based on a projection. Sorting is stable: the -- | order of elements is preserved if they are equal according to the projection. @@ -129,7 +136,13 @@ sortWith sortWith f = sortBy (comparing f) -- | Create an immutable copy of a mutable array. -foreign import freeze :: forall h a. STArray h a -> ST h (Array a) +freeze + :: forall h a + . STArray h a + -> ST h (Array a) +freeze = runSTFn1 freezeImpl + +foreign import freezeImpl :: forall h a. STFn1 (STArray h a) h (Array a) -- | Read the value at the specified index in a mutable array. peek @@ -137,76 +150,101 @@ peek . Int -> STArray h a -> ST h (Maybe a) -peek = peekImpl Just Nothing +peek = runSTFn4 peekImpl Just Nothing -foreign import peekImpl - :: forall h a r - . (a -> r) - -> r - -> Int +foreign import peekImpl :: forall h a r. STFn4 (a -> r) r Int (STArray h a) h r + +poke + :: forall h a + . Int + -> a -> STArray h a - -> (ST h r) + -> ST h Boolean +poke = runSTFn3 pokeImpl -- | Change the value at the specified index in a mutable array. -foreign import poke :: forall h a. Int -> a -> STArray h a -> ST h Boolean +foreign import pokeImpl :: forall h a. STFn3 Int a (STArray h a) h Boolean -- | Get the number of elements in a mutable array. -foreign import length :: forall h a. STArray h a -> ST h Int +foreign import lengthImpl :: forall h a. STFn1 (STArray h a) h Int + +length :: forall h a. STArray h a -> ST h Int +length = runSTFn1 lengthImpl -- | Remove the last element from an array and return that element. pop :: forall h a. STArray h a -> ST h (Maybe a) -pop = popImpl Just Nothing +pop = runSTFn3 popImpl Just Nothing foreign import popImpl :: forall h a - . (forall b. b -> Maybe b) - -> (forall b. Maybe b) - -> STArray h a - -> ST h (Maybe a) + . STFn3 (forall b. b -> Maybe b) (forall b. Maybe b) (STArray h a) h (Maybe a) -- | Append an element to the end of a mutable array. Returns the new length of -- | the array. push :: forall h a. a -> STArray h a -> ST h Int -push a = pushAll [a] +push a = runSTFn2 pushAllImpl [ a ] -- | Append the values in an immutable array to the end of a mutable array. -- | Returns the new length of the mutable array. -foreign import pushAll +pushAll :: forall h a . Array a -> STArray h a -> ST h Int +pushAll = runSTFn2 pushAllImpl + +foreign import pushAllImpl + :: forall h a + . STFn2 (Array a) (STArray h a) h Int -- | Append an element to the front of a mutable array. Returns the new length of -- | the array. unshift :: forall h a. a -> STArray h a -> ST h Int -unshift a = unshiftAll [a] +unshift a = runSTFn2 unshiftAllImpl [ a ] -- | Append the values in an immutable array to the front of a mutable array. -- | Returns the new length of the mutable array. -foreign import unshiftAll +unshiftAll :: forall h a . Array a -> STArray h a -> ST h Int +unshiftAll = runSTFn2 unshiftAllImpl + +foreign import unshiftAllImpl + :: forall h a + . STFn2 (Array a) (STArray h a) h Int -- | Mutate the element at the specified index using the supplied function. modify :: forall h a. Int -> (a -> a) -> STArray h a -> ST h Boolean modify i f xs = do entry <- peek i xs case entry of - Just x -> poke i (f x) xs + Just x -> poke i (f x) xs Nothing -> pure false -- | Remove and/or insert elements from/into a mutable array at the specified index. -foreign import splice +splice :: forall h a . Int -> Int -> Array a -> STArray h a -> ST h (Array a) +splice = runSTFn4 spliceImpl + +foreign import spliceImpl + :: forall h a + . STFn4 Int Int (Array a) (STArray h a) h (Array a) -- | Create an immutable copy of a mutable array, where each element -- | is labelled with its index in the original array. -foreign import toAssocArray :: forall h a. STArray h a -> ST h (Array (Assoc a)) +toAssocArray + :: forall h a + . STArray h a + -> ST h (Array (Assoc a)) +toAssocArray = runSTFn1 toAssocArrayImpl + +foreign import toAssocArrayImpl + :: forall h a + . STFn1 (STArray h a) h (Array (Assoc a)) diff --git a/src/Data/Array/ST/Partial.js b/src/Data/Array/ST/Partial.js index b289097c..8468ff7c 100644 --- a/src/Data/Array/ST/Partial.js +++ b/src/Data/Array/ST/Partial.js @@ -1,17 +1,7 @@ -export const peekImpl = function (i) { - return function (xs) { - return function () { - return xs[i]; - }; - }; +export const peekImpl = function (i, xs) { + return xs[i]; }; -export const pokeImpl = function (i) { - return function (a) { - return function (xs) { - return function () { - xs[i] = a; - }; - }; - }; +export const pokeImpl = function (i, a, xs) { + xs[i] = a; }; diff --git a/src/Data/Array/ST/Partial.purs b/src/Data/Array/ST/Partial.purs index 58253396..f492b6ed 100644 --- a/src/Data/Array/ST/Partial.purs +++ b/src/Data/Array/ST/Partial.purs @@ -8,6 +8,7 @@ module Data.Array.ST.Partial ) where import Control.Monad.ST (ST) +import Control.Monad.ST.Uncurried (STFn2, STFn3, runSTFn2, runSTFn3) import Data.Array.ST (STArray) import Data.Unit (Unit) @@ -18,9 +19,9 @@ peek => Int -> STArray h a -> ST h a -peek = peekImpl +peek = runSTFn2 peekImpl -foreign import peekImpl :: forall h a. Int -> STArray h a -> ST h a +foreign import peekImpl :: forall h a. STFn2 Int (STArray h a) h a -- | Change the value at the specified index in a mutable array. poke @@ -30,11 +31,6 @@ poke -> a -> STArray h a -> ST h Unit -poke = pokeImpl +poke = runSTFn3 pokeImpl -foreign import pokeImpl - :: forall h a - . Int - -> a - -> STArray h a - -> ST h Unit +foreign import pokeImpl :: forall h a. STFn3 Int a (STArray h a) h Unit From c5f3cdc63accf5cab7ddcf007fbe20d2bb660488 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sun, 30 Oct 2022 00:43:08 -0500 Subject: [PATCH 2/4] Add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fd99bc1..019e5f8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ New features: Other improvements: - Use more efficient implementation for `mapWithIndex` (#233 by @JordanMartinez) +- Updates `ST` FFI to use uncurried functions via `STFnX` types (#234 by @JordanMartinez) ## [v7.1.0](https://github.com/purescript/purescript-arrays/releases/tag/v7.1.0) - 2022-08-06 From 4e156a48a70cace728b9ac806dd8c40a5a2c5b57 Mon Sep 17 00:00:00 2001 From: JordanMartinez Date: Mon, 31 Oct 2022 10:42:57 -0500 Subject: [PATCH 3/4] Update bower.json Co-authored-by: Thomas Honeyman --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index 13c330c7..f1ec0831 100644 --- a/bower.json +++ b/bower.json @@ -35,4 +35,4 @@ "purescript-const": "^6.0.0", "purescript-minibench": "^4.0.0" } -} \ No newline at end of file +} From 429367637bc349f5870e46fb6d2d1aeee5bcef03 Mon Sep 17 00:00:00 2001 From: Thomas Honeyman Date: Tue, 13 Jun 2023 11:31:19 -0400 Subject: [PATCH 4/4] Move doc comment --- src/Data/Array/ST.purs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Array/ST.purs b/src/Data/Array/ST.purs index eb437b9c..e95864c5 100644 --- a/src/Data/Array/ST.purs +++ b/src/Data/Array/ST.purs @@ -165,9 +165,9 @@ poke = runSTFn3 pokeImpl -- | Change the value at the specified index in a mutable array. foreign import pokeImpl :: forall h a. STFn3 Int a (STArray h a) h Boolean --- | Get the number of elements in a mutable array. foreign import lengthImpl :: forall h a. STFn1 (STArray h a) h Int +-- | Get the number of elements in a mutable array. length :: forall h a. STArray h a -> ST h Int length = runSTFn1 lengthImpl