Releases: reazen/relude
v0.40.0
✨ New
Parallel semantics for IO
APPLY
- Implement parallel execution semantics for the
IO
APPLY
typeclass! 🎆 - Anything that uses an
APPLY
-based parallelization (apply
,map2-5
,tuple2-5
,mapTuple2-5
,all
,traverse
/sequence
, etc.) should now execute the IO operations in parallel rather than sequential.- You shouldn't have to change anything - it should just now be parallel when run
- This was implemented by adding a new
Apply
constructor toIO
, to go along with theMap
andFlatMap
constructors - Prior to this change the
IO
apply
function was implemented in terms offlatMap
, which is why it had the sequential execution semantics. AddingApply
allows for parallel semantics.
IO
unsafeRunAsyncPar2
and 3
- Added
unsafeRunAsyncPar2
and3
functions for IO - These are used internally to implement the paralell semantics of
IO
'sApply
, so it's better to useapply
-based combinators to compose parallelIO
values, rather than manually running them using these. - That said, if people find these useful, we can add more, like up to the usual 5, or more!
compose
function for IO
, Result
and Option
- Added a compose function for the above types, which allow you to compose two functions that are each wrapped inside their own functor contexts.
let rec compose:
'a 'b 'c 'e.
(t('b => 'c, 'e), t('a => 'b, 'e)) => t('a => 'c, 'e) = ...
let (<<<) = compose;
let andThen:
'a 'b 'c 'e.
(t('a => 'b, 'e), t('b => 'c, 'e)) => t('a => 'c, 'e) = ...
let (>>>) = andThen;
- This was useful for implementing some of the
IO
pattern matching with the addition ofApply
- I also made
IO
,Result
, andOption
implementSemigroupoid
instances using the abovecompose
functions. I'm not 100% sure if this is a valid thing to do, but it seemed reasonable. Happy to be corrected if this is invalid (and at some point we need to add property-based tests).
🚨 Breaking
-
A small breaking change to
IO.withDelay
- I realized thatwithDelay
was actually creating a newIO
that put the delay before the inputIO
, so I changed this to split thewithDelay
function into two different versions:withDelayAfter
- creates a new IO which when run, will execute the givenIO
first, then add the delaywithDelay
- alias forwithDelayAfter
withDelayBefore
- creates a new IO which when run, will execute the delay, then the givenIO
The breaking change is that withDelay
used to work more like withDelayBefore
, but now is just an alias for withDelayAfter
. The end result of each of these is the same, they just put the delay at either the start or the end of the IO
operation
🗣️ Request for feedback
This change to IO
Apply
has not been tested super thoroughly other than some high-level unit tests and some production use cases in our app, so I'd love to hear from anyone as to whether the parallel behavior is working for you, or if you encounter any new problems. If you adopt this version of relude in an existing app, I'd recommend exercising all parts of your app which use IO
to make sure there are no regressions.
If you do find regressions, I'd recommend reverting the version of relude for now, and I can try to look into specific cases. If you encounter issues, I'd appreciate minimal reproduction test cases, but any sort of issue description would be appreciated. The most useful information is just a description of what IO
combinators you're using, and the order in which they are being used (i.e. "we are doing an async
, followed by flatMap
, apply
, summonError
, etc.").
v0.39.0
✨ New
- @johnhaley81 - add Set.update - an operation for removing and adding a value from a
Set
- likely useful when dealing with mutable values in aSet
#198
v0.38.0
✨ New
- @johnhaley81 - added
ApplicativeExtensions.add
- a function for runninglist
of applicative effectslist(A.t('a))
to produce anA.t(list('a))
- See discussion on #195 - this
all
function is automatically added to any type with anApplicative
instance that utilizesinclude ApplicativeExtensions(Applicative)
- The
all
function is a specialization ofTraversable
sequence
with the container type oflist
and the givenAPPLICATIVE
instance
- See discussion on #195 - this
- Added
alt
,orElse
,ALT
instance, and<|>
infix operator forIO
- See #189
- The
alt
function is a useful new operation inIO
where you can attempt an effect, and if it fails, attempt a "fallback" effect (and so on for as many effects as you want). - e.g.
io1 <|> io2 <|> io3 <|> etc
- Because
IO
is lazy, none of the effects will be run until the chain is run usingIO.unsafeRunAsync
- When run,
io1
will be run, and if (and only if) it fails,io2
will be run, and so on - See the tests for example usage
v0.37.0
🚨 Breaking
Map.compare
is nowMap.compareBy
and it expects the provided comparison function to return anordering
Map.keys
andMap.values
return alist
instead of anarray
... seekeyArray
andvalueArray
for the old behavior
✨ New
StringMap
(a specialization of Map where the keys arestring
s) is included for your convenienceMap.singleton
constructs a Map from a single key and valueMap.fromValueList
andMap.fromValueArray
construct maps from alist('value)
orarray('value)
as long as you can provide a'value => 'key
mapping. Unlike thegroupBy
functions, these assume that thekey
returned by your function will be unique for eachvalue
.Option
now has specializations likeOption.String.eq
andOption.IO.traverse
. It's not quite as built-out as theList
andArray
specializations, but it's a start
📝 Docs
Map
now has doc comments, but turns out they get lost when you construct a specialized Map (e.g.StringMap
)
✔️ Code quality
- Lots more tests for Map
- More
option
functions are written here, instead of calling off to other libraries
v0.36.1
✨ New
- Added
RIO
toRelude
andRelude_Globals
modules (forgot to do this in v0.36.0)
v0.36.0
v0.35.0
v0.34.0
✨ New
- Added
concatNamed(~prefix, suffix)
function toSemigroup
andSemigroupAny
Extensions, which affects any module that has aSemigroup
orSemigroupAny
module and includes theRelude_Extensions_Semigroup|Any
module. #150- In other words,
Array
,List
,Nel
, andNea
now have aconcatNamed
function that takes a named argument to disambiguate which argument is which - The normal
concat
function is used in theSemigroup
|SemigroupAny
function with unlabelled args, so I left that one alone
- In other words,
- Added
guard
andpower
to theMonoidAnyExtensions
, to bring it inline withMonoidExtensions
- Added some more random tests to improve coverage
v0.33.0
✔️ Code "quality"
- Moved
extensions/Relude_Extensions_List.re
tolist/Relude_List_Specializations.re
to better categorize what this module is - it is mostly a set of modules that provide extra functions for various specializations ofList
, likeList.String
,List.Int
, etc. #176 - Same change as above for
Relude_Extensions_Array
#176 - Finally removed the long-lingering
Array.rei
andList.rei
which we've been somewhat pointlessly re-generating for a long time. Our current stance on .rei files is to not use them because of the maintenance burden they introduce because of our wide-spread use ofinclude
for typeclass extensions/etc. #109- If someday there is a good solution for managing docs in .rei files in the presence of
include
s, we can revisit the use of .rei files
- If someday there is a good solution for managing docs in .rei files in the presence of
v0.32.0
✨ New
- Added
Relude.Timer
- which contains basic utility functions for scheduling delayed or repeated invocations of functions, returning a cancel function.- These are currently backed by Js.Global.setTimeout/setInterval, but this could be abstracted out in the future if needed
- This currently includes the functions
delay
,repeat
, andrepeatTimes
, which can all be canceled once scheduled
- Added
Relude.Debounce.debounce
- a utility function for creating debouncedunit => unit
functions- The implementation of this might be subject to change going forward - feedback is appreciated
- Added
Relude.Throttle.throttle
- a utility function for creating throttledunit => unit
functions- The implementation of this might be subject to change going forward - feedback is appreciated
- Added
Relude.Js.Animation
with some basic bindings for therequestAnimationFrame
-related functions- At one point I was using these, but that code got removed, so these functions aren't actually used in relude anywhere. I just included them because they are small and harmless, but they can be removed in the future if needed.
- Added various utility functions in
Relude.Function
#178memoize0
- utility function for memoizing aunit => 'a
functionmemoize1
- utility function for memoizing a'a => 'b
function, using a string-map-based cacheafter
- utility function for creating a function that suppresses invocations of a given function before a certain number of callsbefore
- utility function for creating a function that suppresses invocations of a given function after a certain number of callsonce
- utility function for creating a function that suppresses invocations of a given function after one callwrap
- utility function for wrapping a given function with functions that manipulate the input and output of the given functionnegate
- utility function for creating a function that is the negation of a given predicate