diff --git a/LanguageExt.Pipes/Client/Client.cs b/LanguageExt.Pipes/Client/Client.cs deleted file mode 100644 index 5a7c88c3b..000000000 --- a/LanguageExt.Pipes/Client/Client.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Diagnostics.Contracts; -using System.Runtime.CompilerServices; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -/// -/// `Client` sends requests of type `REQ` and receives responses of type `RES`. -/// -/// Clients only `request` and never `respond`. -/// -/// -/// -/// Upstream | Downstream -/// +---------+ -/// | | -/// REQ 〈== 〈== Unit -/// | | -/// RES ==〉 ==〉Void -/// | | | -/// +----|----+ -/// | -/// A -/// -public class Client -{ - /// - /// Monad return / pure - /// - [Pure, MethodImpl(Proxy.mops)] - public static Client Pure(R value) - where M : Monad => - new Pure(value).ToClient(); - - /// - /// Send a value of type `RES` downstream and block waiting for a reply of type `REQ` - /// - /// - /// `respond` is the identity of the respond category. - /// - [Pure, MethodImpl(Proxy.mops)] - public static Client request(REQ value) - where M : Monad => - new Request(value, r => new Pure(r)).ToClient(); - - /// - /// Lift am IO monad into the `Proxy` monad transformer - /// - [Pure, MethodImpl(Proxy.mops)] - public static Client lift(K ma) - where M : Monad => - new ProxyM(M.Map(Proxy.Pure, ma)).ToClient(); - - /// - /// Lift am IO monad into the `Proxy` monad transformer - /// - [Pure, MethodImpl(Proxy.mops)] - public static Client liftIO(IO ma) - where M : Monad => - new ProxyM(M.Map(Proxy.Pure, M.LiftIO(ma))).ToClient(); -} diff --git a/LanguageExt.Pipes/Client/CoreTypes.cs b/LanguageExt.Pipes/Client/CoreTypes.cs deleted file mode 100644 index 93937f49c..000000000 --- a/LanguageExt.Pipes/Client/CoreTypes.cs +++ /dev/null @@ -1,237 +0,0 @@ -using System; -using System.Diagnostics.Contracts; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -/// -/// `Client` sends requests of type `REQ` and receives responses of type `RES`. -/// -/// Clients only `request` and never `respond`. -/// -/// -/// -/// Upstream | Downstream -/// +---------+ -/// | | -/// REQ 〈== 〈== Unit -/// | | -/// RES ==〉 ==〉Void -/// | | | -/// +----|----+ -/// | -/// A -/// -public record Client : Proxy - where M : Monad -{ - public readonly Proxy Value; - - /// - /// Constructor - /// - /// Correctly shaped `Proxy` that represents a `Client` - public Client(Proxy value) => - Value = value; - - /// - /// Calling this will effectively cast the subtype to the base. - /// - /// This type wraps up a `Proxy` for convenience, and so it's a `Proxy` proxy. So calling this method - /// isn't exactly the same as a cast operation, as it unwraps the `Proxy` from within. It has the same effect - /// however, and removes a level of indirection - /// A general `Proxy` type from a more specialised type - [Pure] - public override Proxy ToProxy() => - Value.ToProxy(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public override Proxy Bind(Func> f) => - Value.Bind(f); - - /// - /// Lifts a pure function into the `Proxy` domain, causing it to map the bound value within - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy Map(Func f) => - Value.Map(f); - - /// - /// Map the lifted monad - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy MapM(Func, K> f) => - Value.MapM(f); - - /// - /// Extract the lifted IO monad (if there is one) - /// - /// The map function - /// A new `Proxy` that represents the innermost IO monad, if it exists. - /// `Errors.UnliftIONotSupported` if there's no IO monad in the stack - [Pure] - public override Proxy> ToIO() => - Value.ToIO(); - - /// - /// Monadic bind operation, for chaining `Client` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Client Bind(Func> f) => - Value.Bind(f).ToClient(); - - /// - /// Monadic bind operation, for chaining `Client` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Client SelectMany(Func> f) => - Value.Bind(f).ToClient(); - - /// - /// Monadic bind operation, for chaining `Client` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Client SelectMany(Func> f, Func project) => - Value.Bind(a => f(a).Map(b => project(a, b))).ToClient(); - - /// - /// Lifts a pure function into the `Proxy` domain, causing it to map the bound value within - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public new Client Select(Func f) => - Value.Map(f).ToClient(); - - /// - /// `For(body)` loops over the `Proxy p` replacing each `yield` with `body` - /// - /// Any `yield` found in the `Proxy` will be replaced with this function. It will be composed so - /// that the value yielded will be passed to the argument of the function. That returns a `Proxy` to continue the - /// processing of the computation - /// A new `Proxy` that represents the composition of this `Proxy` and the function provided - [Pure] - public override Proxy For(Func> body) => - Value.For(body); - - /// - /// Applicative action - /// - /// Invokes this `Proxy`, then the `Proxy r` - /// - /// `Proxy` to run after this one - [Pure] - public override Proxy Action(Proxy r) => - Value.Action(r); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - /// - /// (f +>> p) pairs each 'request' in `this` with a 'respond' in `lhs`. - /// - [Pure] - public override Proxy PairEachRequestWithRespond(Func> lhs) => - Value.PairEachRequestWithRespond(lhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy ReplaceRequest(Func> lhs) => - Value.ReplaceRequest(lhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy PairEachRespondWithRequest(Func> rhs) => - Value.PairEachRespondWithRequest(rhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy ReplaceRespond(Func> rhs) => - Value.ReplaceRespond(rhs); - - /// - /// Reverse the arrows of the `Proxy` to find its dual. - /// - /// The dual of `this` - [Pure] - public override Proxy Reflect() => - Value.Reflect(); - - /// - /// - /// Observe(lift (Pure(r))) = Observe(Pure(r)) - /// Observe(lift (m.Bind(f))) = Observe(lift(m.Bind(x => lift(f(x))))) - /// - /// This correctness comes at a small cost to performance, so use this function sparingly. - /// This function is a convenience for low-level pipes implementers. You do not need to - /// use observe if you stick to the safe API. - /// - [Pure] - public override Proxy Observe() => - Value.Observe(); - - [Pure] - public void Deconstruct(out Proxy value) => - value = Value; - - /// - /// Compose a `Server` and a `Client` together into an `Effect`. Note the `Server` is provided as a function - /// that takes a value of `REQ`. This is how we model the request coming into the `Server`. The resulting - /// `Server` computation can then call `Server.respond(response)` to reply to the `Client`. - /// - /// The `Client` simply calls `Client.request(req)` to post a request to the `Server`, it is like an `awaiting` - /// that also posts. It will await the response from the `Server`. - /// - /// `Server` - /// `Client` - /// `Effect` - [Pure] - public static Effect operator |(Func> x, Client y) => - y.PairEachRequestWithRespond(x).ToEffect(); - - /// - /// Chain one client after another - /// - [Pure] - public static Client operator &( - Client lhs, - Client rhs) => - lhs.Bind(_ => rhs); - - [Pure] - public override string ToString() => - "client"; -} diff --git a/Samples/PipesExamples/Concurrent/Buffer.cs b/LanguageExt.Pipes/Concurrent/Buffer.cs similarity index 97% rename from Samples/PipesExamples/Concurrent/Buffer.cs rename to LanguageExt.Pipes/Concurrent/Buffer.cs index 731b83590..7d8ef078e 100644 --- a/Samples/PipesExamples/Concurrent/Buffer.cs +++ b/LanguageExt.Pipes/Concurrent/Buffer.cs @@ -1,4 +1,4 @@ -namespace LanguageExt.Pipes2.Concurrent; +namespace LanguageExt.Pipes.Concurrent; /// /// Settings for `Mailbox` channels diff --git a/Samples/PipesExamples/Concurrent/Inbox/Inbox.CoFunctor.cs b/LanguageExt.Pipes/Concurrent/Inbox/Inbox.CoFunctor.cs similarity index 92% rename from Samples/PipesExamples/Concurrent/Inbox/Inbox.CoFunctor.cs rename to LanguageExt.Pipes/Concurrent/Inbox/Inbox.CoFunctor.cs index 14b233f0f..4ba6cf859 100644 --- a/Samples/PipesExamples/Concurrent/Inbox/Inbox.CoFunctor.cs +++ b/LanguageExt.Pipes/Concurrent/Inbox/Inbox.CoFunctor.cs @@ -1,6 +1,7 @@ +using System; using LanguageExt.Traits; -namespace LanguageExt.Pipes2.Concurrent; +namespace LanguageExt.Pipes.Concurrent; public class Inbox : Decidable { diff --git a/Samples/PipesExamples/Concurrent/Inbox/Inbox.DSL.cs b/LanguageExt.Pipes/Concurrent/Inbox/Inbox.DSL.cs similarity index 98% rename from Samples/PipesExamples/Concurrent/Inbox/Inbox.DSL.cs rename to LanguageExt.Pipes/Concurrent/Inbox/Inbox.DSL.cs index 69f566cfa..632b3e531 100644 --- a/Samples/PipesExamples/Concurrent/Inbox/Inbox.DSL.cs +++ b/LanguageExt.Pipes/Concurrent/Inbox/Inbox.DSL.cs @@ -1,8 +1,9 @@ +using System; using System.Threading.Channels; using LanguageExt.Common; using static LanguageExt.Prelude; -namespace LanguageExt.Pipes2.Concurrent; +namespace LanguageExt.Pipes.Concurrent; record InboxWriter(ChannelWriter Writer) : Inbox { diff --git a/Samples/PipesExamples/Concurrent/Inbox/Inbox.Extensions.cs b/LanguageExt.Pipes/Concurrent/Inbox/Inbox.Extensions.cs similarity index 83% rename from Samples/PipesExamples/Concurrent/Inbox/Inbox.Extensions.cs rename to LanguageExt.Pipes/Concurrent/Inbox/Inbox.Extensions.cs index 2e5dda100..f2c7670fa 100644 --- a/Samples/PipesExamples/Concurrent/Inbox/Inbox.Extensions.cs +++ b/LanguageExt.Pipes/Concurrent/Inbox/Inbox.Extensions.cs @@ -1,6 +1,6 @@ using LanguageExt.Traits; -namespace LanguageExt.Pipes2.Concurrent; +namespace LanguageExt.Pipes.Concurrent; public static class InboxExtensions { diff --git a/Samples/PipesExamples/Concurrent/Inbox/Inbox.cs b/LanguageExt.Pipes/Concurrent/Inbox/Inbox.cs similarity index 98% rename from Samples/PipesExamples/Concurrent/Inbox/Inbox.cs rename to LanguageExt.Pipes/Concurrent/Inbox/Inbox.cs index dfa29d54c..2ce767fa2 100644 --- a/Samples/PipesExamples/Concurrent/Inbox/Inbox.cs +++ b/LanguageExt.Pipes/Concurrent/Inbox/Inbox.cs @@ -1,7 +1,8 @@ +using System; using LanguageExt.Common; using LanguageExt.Traits; -namespace LanguageExt.Pipes2.Concurrent; +namespace LanguageExt.Pipes.Concurrent; /// /// Entry point to a channel. Inboxes receive values and propagate them through the diff --git a/Samples/PipesExamples/Concurrent/Mailbox/Mailbox.Module.cs b/LanguageExt.Pipes/Concurrent/Mailbox/Mailbox.Module.cs similarity index 97% rename from Samples/PipesExamples/Concurrent/Mailbox/Mailbox.Module.cs rename to LanguageExt.Pipes/Concurrent/Mailbox/Mailbox.Module.cs index 9842b9e29..9d88b2928 100644 --- a/Samples/PipesExamples/Concurrent/Mailbox/Mailbox.Module.cs +++ b/LanguageExt.Pipes/Concurrent/Mailbox/Mailbox.Module.cs @@ -1,5 +1,6 @@ +using System; using Ch = System.Threading.Channels; -namespace LanguageExt.Pipes2.Concurrent; +namespace LanguageExt.Pipes.Concurrent; public static class Mailbox { diff --git a/Samples/PipesExamples/Concurrent/Mailbox/Mailbox.cs b/LanguageExt.Pipes/Concurrent/Mailbox/Mailbox.cs similarity index 99% rename from Samples/PipesExamples/Concurrent/Mailbox/Mailbox.cs rename to LanguageExt.Pipes/Concurrent/Mailbox/Mailbox.cs index 61e6f2112..621b8a10f 100644 --- a/Samples/PipesExamples/Concurrent/Mailbox/Mailbox.cs +++ b/LanguageExt.Pipes/Concurrent/Mailbox/Mailbox.cs @@ -1,7 +1,8 @@ +using System; using LanguageExt.Common; using LanguageExt.Traits; -namespace LanguageExt.Pipes2.Concurrent; +namespace LanguageExt.Pipes.Concurrent; /// /// Represents a channel. A channel has: diff --git a/Samples/PipesExamples/Concurrent/Outbox/Outbox.DSL.cs b/LanguageExt.Pipes/Concurrent/Outbox/Outbox.DSL.cs similarity index 97% rename from Samples/PipesExamples/Concurrent/Outbox/Outbox.DSL.cs rename to LanguageExt.Pipes/Concurrent/Outbox/Outbox.DSL.cs index ed047035f..a0a2801e2 100644 --- a/Samples/PipesExamples/Concurrent/Outbox/Outbox.DSL.cs +++ b/LanguageExt.Pipes/Concurrent/Outbox/Outbox.DSL.cs @@ -1,7 +1,10 @@ +using System; +using System.Threading; using System.Threading.Channels; +using System.Threading.Tasks; using LanguageExt.Common; -namespace LanguageExt.Pipes2.Concurrent; +namespace LanguageExt.Pipes.Concurrent; record OutboxPure(A Value) : Outbox { diff --git a/Samples/PipesExamples/Concurrent/Outbox/Outbox.Extensions.cs b/LanguageExt.Pipes/Concurrent/Outbox/Outbox.Extensions.cs similarity index 83% rename from Samples/PipesExamples/Concurrent/Outbox/Outbox.Extensions.cs rename to LanguageExt.Pipes/Concurrent/Outbox/Outbox.Extensions.cs index 3aac2c4e1..7f6ce7d2e 100644 --- a/Samples/PipesExamples/Concurrent/Outbox/Outbox.Extensions.cs +++ b/LanguageExt.Pipes/Concurrent/Outbox/Outbox.Extensions.cs @@ -1,6 +1,6 @@ using LanguageExt.Traits; -namespace LanguageExt.Pipes2.Concurrent; +namespace LanguageExt.Pipes.Concurrent; public static class OutboxExtensions { diff --git a/Samples/PipesExamples/Concurrent/Outbox/Outbox.Internal.cs b/LanguageExt.Pipes/Concurrent/Outbox/Outbox.Internal.cs similarity index 97% rename from Samples/PipesExamples/Concurrent/Outbox/Outbox.Internal.cs rename to LanguageExt.Pipes/Concurrent/Outbox/Outbox.Internal.cs index a2e2246e5..30932b5f2 100644 --- a/Samples/PipesExamples/Concurrent/Outbox/Outbox.Internal.cs +++ b/LanguageExt.Pipes/Concurrent/Outbox/Outbox.Internal.cs @@ -1,6 +1,8 @@ +using System.Threading; +using System.Threading.Tasks; using LanguageExt.Common; -namespace LanguageExt.Pipes2.Concurrent; +namespace LanguageExt.Pipes.Concurrent; internal class OutboxInternal { diff --git a/LanguageExt.Pipes/Concurrent/Outbox/Outbox.Module.cs b/LanguageExt.Pipes/Concurrent/Outbox/Outbox.Module.cs new file mode 100644 index 000000000..ab5748c1c --- /dev/null +++ b/LanguageExt.Pipes/Concurrent/Outbox/Outbox.Module.cs @@ -0,0 +1,6 @@ +namespace LanguageExt.Pipes.Concurrent; + +public partial class Outbox +{ + +} diff --git a/Samples/PipesExamples/Concurrent/Outbox/Outbox.Monad.cs b/LanguageExt.Pipes/Concurrent/Outbox/Outbox.Monad.cs similarity index 94% rename from Samples/PipesExamples/Concurrent/Outbox/Outbox.Monad.cs rename to LanguageExt.Pipes/Concurrent/Outbox/Outbox.Monad.cs index e2c6215d7..e2725f21c 100644 --- a/Samples/PipesExamples/Concurrent/Outbox/Outbox.Monad.cs +++ b/LanguageExt.Pipes/Concurrent/Outbox/Outbox.Monad.cs @@ -1,6 +1,7 @@ +using System; using LanguageExt.Traits; -namespace LanguageExt.Pipes2.Concurrent; +namespace LanguageExt.Pipes.Concurrent; public partial class Outbox : Monad, diff --git a/Samples/PipesExamples/Concurrent/Outbox/Outbox.cs b/LanguageExt.Pipes/Concurrent/Outbox/Outbox.cs similarity index 97% rename from Samples/PipesExamples/Concurrent/Outbox/Outbox.cs rename to LanguageExt.Pipes/Concurrent/Outbox/Outbox.cs index c0787d48d..f5d5a8718 100644 --- a/Samples/PipesExamples/Concurrent/Outbox/Outbox.cs +++ b/LanguageExt.Pipes/Concurrent/Outbox/Outbox.cs @@ -1,7 +1,10 @@ +using System; +using System.Threading; +using System.Threading.Tasks; using LanguageExt.Traits; using static LanguageExt.Prelude; -namespace LanguageExt.Pipes2.Concurrent; +namespace LanguageExt.Pipes.Concurrent; public abstract record Outbox : K, diff --git a/LanguageExt.Pipes/Consumer/Consumer.cs b/LanguageExt.Pipes/Consumer/Consumer.cs deleted file mode 100644 index 16c508331..000000000 --- a/LanguageExt.Pipes/Consumer/Consumer.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using LanguageExt.Traits; -using System.Diagnostics.Contracts; -using System.Runtime.CompilerServices; -using static LanguageExt.Pipes.Proxy; -using static LanguageExt.Prelude; - -namespace LanguageExt.Pipes; - -/// -/// Consumers both can only be `awaiting` -/// -/// -/// -/// Upstream | Downstream -/// +---------+ -/// | | -/// Unit〈== 〈== Unit -/// | | -/// IN ==〉 ==〉Void -/// | | | -/// +----|----+ -/// | -/// A -/// -public static class Consumer -{ - /// - /// Monad return / pure - /// - [Pure, MethodImpl(mops)] - public static Consumer Pure(R value) - where M : Monad => - new Pure(value).ToConsumer(); - - /// - /// Wait for a value from upstream (whilst in a consumer) - /// - [Pure, MethodImpl(mops)] - public static Consumer awaiting() - where M : Monad => - request(unit).ToConsumer(); - - /// - /// Lift the IO monad into the Consumer monad transformer (a specialism of the Proxy monad transformer) - /// - [Pure, MethodImpl(mops)] - public static Consumer lift(K ma) - where M : Monad => - lift(ma).ToConsumer(); - - /// - /// Lift the IO monad into the Consumer monad transformer (a specialism of the Proxy monad transformer) - /// - [Pure, MethodImpl(mops)] - public static Consumer liftIO(IO ma) - where M : Monad => - liftIO(ma).ToConsumer(); - - /// - /// Consume all values using a monadic function - /// - [Pure, MethodImpl(mops)] - public static Consumer mapM(Func> f) - where M : Monad => - cat().ForEach(a => lift(f(a))); - - /// - /// Consume all values using a monadic function - /// - [Pure, MethodImpl(mops)] - public static Consumer mapM(Func> f) - where M : Monad => - cat().ForEach(a => lift(M.LiftIO(f(a)))); - -} diff --git a/LanguageExt.Pipes/Consumer/CoreTypes.cs b/LanguageExt.Pipes/Consumer/CoreTypes.cs deleted file mode 100644 index 3803c09ff..000000000 --- a/LanguageExt.Pipes/Consumer/CoreTypes.cs +++ /dev/null @@ -1,272 +0,0 @@ -using System; -using System.Diagnostics.Contracts; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -/// -/// Consumers both can only be `awaiting` -/// -/// -/// Upstream | Downstream -/// +---------+ -/// | | -/// Unit〈== 〈== Unit -/// | | -/// IN ==〉 ==〉Void -/// | | | -/// +----|----+ -/// | -/// A -/// -public record Consumer : Proxy - where M : Monad -{ - public readonly Proxy Value; - - /// - /// Constructor - /// - /// Correctly shaped `Proxy` that represents a `Consumer` - public Consumer(Proxy value) => - Value = value; - - /// - /// Calling this will effectively cast the sub-type to the base. - /// - /// This type wraps up a `Proxy` for convenience, and so it's a `Proxy` proxy. So calling this method - /// isn't exactly the same as a cast operation, as it unwraps the `Proxy` from within. It has the same effect - /// however, and removes a level of indirection - /// A general `Proxy` type from a more specialised type - [Pure] - public override Proxy ToProxy() => - Value.ToProxy(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public override Proxy Bind(Func> f) => - Value.Bind(f); - - /// - /// Map the lifted monad - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy MapM(Func, K> f) => - Value.MapM(f); - - /// - /// Extract the lifted IO monad (if there is one) - /// - /// The map function - /// A new `Proxy` that represents the innermost IO monad, if it exists. - /// `Errors.UnliftIONotSupported` if there's no IO monad in the stack - [Pure] - public override Proxy> ToIO() => - Value.ToIO(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Consumer Bind(Func> f) => - Value.Bind(f).ToConsumer(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Consumer Bind(Func> f) => - Value.Bind(x => Consumer.lift(f(x))).ToConsumer(); - - /// - /// Lifts a pure function into the `Proxy` domain, causing it to map the bound value within - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy Map(Func f) => - Value.Map(f); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Consumer SelectMany(Func> f, Func project) => - Value.Bind(a => f(a).Map(b => project(a, b))).ToConsumer(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Consumer SelectMany(Func> f, Func project) => - Value.Bind(x => Consumer.lift(M.Map(y => project(x, y), f(x)))).ToConsumer(); - - /// - /// Lifts a pure function into the `Proxy` domain, causing it to map the bound value within - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public new Consumer Select(Func f) => - Value.Map(f).ToConsumer(); - - /// - /// `For(body)` loops over the `Proxy p` replacing each `yield` with `body` - /// - /// Any `yield` found in the `Proxy` will be replaced with this function. It will be composed so - /// that the value yielded will be passed to the argument of the function. That returns a `Proxy` to continue the - /// processing of the computation - /// A new `Proxy` that represents the composition of this `Proxy` and the function provided - [Pure] - public override Proxy For(Func> body) => - Value.For(body); - - /// - /// Applicative action - /// - /// Invokes this `Proxy`, then the `Proxy r` - /// - /// `Proxy` to run after this one - [Pure] - public override Proxy Action(Proxy r) => - Value.Action(r); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - /// - /// (f +>> p) pairs each 'request' in `this` with a 'respond' in `lhs`. - /// - [Pure] - public override Proxy PairEachRequestWithRespond( - Func> lhs) => - Value.PairEachRequestWithRespond(lhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy ReplaceRequest( - Func> lhs) => - Value.ReplaceRequest(lhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy PairEachRespondWithRequest( - Func> rhs) => - Value.PairEachRespondWithRequest(rhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy ReplaceRespond( - Func> rhs) => - Value.ReplaceRespond(rhs); - - /// - /// Reverse the arrows of the `Proxy` to find its dual. - /// - /// The dual of `this` - [Pure] - public override Proxy Reflect() => - Value.Reflect(); - - /// - /// - /// Observe(lift (Pure(r))) = Observe(Pure(r)) - /// Observe(lift (m.Bind(f))) = Observe(lift(m.Bind(x => lift(f(x))))) - /// - /// This correctness comes at a small cost to performance, so use this function sparingly. - /// This function is a convenience for low-level pipes implementers. You do not need to - /// use observe if you stick to the safe API. - /// - [Pure] - public override Proxy Observe() => - Value.Observe(); - - [Pure] - public void Deconstruct(out Proxy value) => - value = Value; - - /// - /// Conversion operator from the _pure_ `Consumer` type, to the monad transformer version of the `Consumer` - /// - /// Pure `Consumer` - /// Monad transformer version of the `Consumer` - [Pure] - public static implicit operator Consumer(Consumer c) => - c.Interpret(); - - /// - /// Conversion operator from the `Pure` type, to the monad transformer version of the `Consumer` - /// - /// `Pure` value - /// Monad transformer version of the `Consumer` - [Pure] - public static implicit operator Consumer(Pure p) => - Consumer.Pure(p.Value); - - /// - /// Compose an `IN` and a `Consumer` together into an `Effect`. This effectively creates a singleton `Producer` - /// from the `IN` value, and composes it with the `Consumer` into an `Effect` that can be run. - /// - /// Single input value - /// `Consumer` - /// `Effect` - [Pure] - public static Effect operator |(IN p1, Consumer p2) => - Proxy.compose(Producer.yield(p1).Map(_ => default(A)), p2).ToEffect(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Consumer SelectMany(Func> bind, Func project) => - Value.Bind(a => bind(a).Interpret().Map(b => project(a, b))).ToConsumer(); - - /// - /// Chain one consumer's set of awaits after another - /// - [Pure] - public static Consumer operator &( - Consumer lhs, - Consumer rhs) => - lhs.Bind(_ => rhs); - - [Pure] - public override string ToString() => - "consumer"; -} diff --git a/Samples/PipesExamples/ConsumerT/ConsumerT.Extensions.cs b/LanguageExt.Pipes/ConsumerT/ConsumerT.Extensions.cs similarity index 98% rename from Samples/PipesExamples/ConsumerT/ConsumerT.Extensions.cs rename to LanguageExt.Pipes/ConsumerT/ConsumerT.Extensions.cs index 07debd41f..9c8a95e57 100644 --- a/Samples/PipesExamples/ConsumerT/ConsumerT.Extensions.cs +++ b/LanguageExt.Pipes/ConsumerT/ConsumerT.Extensions.cs @@ -1,6 +1,7 @@ +using System; using LanguageExt.Traits; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; public static class ConsumerTExtensions { diff --git a/Samples/PipesExamples/ConsumerT/ConsumerT.Module.cs b/LanguageExt.Pipes/ConsumerT/ConsumerT.Module.cs similarity index 99% rename from Samples/PipesExamples/ConsumerT/ConsumerT.Module.cs rename to LanguageExt.Pipes/ConsumerT/ConsumerT.Module.cs index 7f2a4c9dc..76f97195f 100644 --- a/Samples/PipesExamples/ConsumerT/ConsumerT.Module.cs +++ b/LanguageExt.Pipes/ConsumerT/ConsumerT.Module.cs @@ -1,7 +1,9 @@ +using System; +using System.Threading.Tasks; using LanguageExt.Common; using LanguageExt.Traits; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; /// /// `ConsumerT` streaming consumer monad-transformer diff --git a/Samples/PipesExamples/ConsumerT/ConsumerT.Monad.cs b/LanguageExt.Pipes/ConsumerT/ConsumerT.Monad.cs similarity index 95% rename from Samples/PipesExamples/ConsumerT/ConsumerT.Monad.cs rename to LanguageExt.Pipes/ConsumerT/ConsumerT.Monad.cs index 357b2957f..cdf36cdfb 100644 --- a/Samples/PipesExamples/ConsumerT/ConsumerT.Monad.cs +++ b/LanguageExt.Pipes/ConsumerT/ConsumerT.Monad.cs @@ -1,7 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Linq; using LanguageExt.Async.Linq; using LanguageExt.Traits; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; public class ConsumerT : MonadT, M> where M : Monad diff --git a/Samples/PipesExamples/ConsumerT/ConsumerT.cs b/LanguageExt.Pipes/ConsumerT/ConsumerT.cs similarity index 98% rename from Samples/PipesExamples/ConsumerT/ConsumerT.cs rename to LanguageExt.Pipes/ConsumerT/ConsumerT.cs index cc231362b..ac6e1aa81 100644 --- a/Samples/PipesExamples/ConsumerT/ConsumerT.cs +++ b/LanguageExt.Pipes/ConsumerT/ConsumerT.cs @@ -1,7 +1,8 @@ +using System; using System.Diagnostics.Contracts; using LanguageExt.Traits; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; /// /// `ConsumerT` streaming consumer monad-transformer instance diff --git a/LanguageExt.Pipes/Effect/CoreTypes.cs b/LanguageExt.Pipes/Effect/CoreTypes.cs deleted file mode 100644 index a18d275f4..000000000 --- a/LanguageExt.Pipes/Effect/CoreTypes.cs +++ /dev/null @@ -1,238 +0,0 @@ -using System; -using System.Diagnostics.Contracts; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -/// -/// Effects represent a 'fused' set of producer, pipes, and consumer into one type. -/// -/// It neither can neither `yield` nor be `awaiting`, it represents an entirely closed effect system. -/// -/// -/// -/// Upstream | Downstream -/// +---------+ -/// | | -/// Void〈== 〈== Unit -/// | | -/// Unit ==〉 ==〉Void -/// | | | -/// +----|----+ -/// | -/// A -/// -/// -public record Effect : Proxy - where M : Monad -{ - public readonly Proxy Value; - - /// - /// Constructor - /// - /// Correctly shaped `Proxy` that represents an `Effect` - public Effect(Proxy value) => - Value = value; - - /// - /// Calling this will effectively cast the sub-type to the base. - /// - /// This type wraps up a `Proxy` for convenience, and so it's a `Proxy` proxy. So calling this method - /// isn't exactly the same as a cast operation, as it unwraps the `Proxy` from within. It has the same effect - /// however, and removes a level of indirection - /// A general `Proxy` type from a more specialised type - [Pure] - public override Proxy ToProxy() => - Value.ToProxy(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public override Proxy Bind( - Func> f) => - Value.Bind(f); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Effect Bind(Func> f) => - Value.Bind(f).ToEffect(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Effect Bind(Func> f) => - Value.Bind(x => Effect.lift(f(x))).ToEffect(); - - /// - /// Lifts a pure function into the `Proxy` domain, causing it to map the bound value within - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy Map(Func f) => - Value.Map(f); - - /// - /// Map the lifted monad - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy MapM(Func, K> f) => - Value.MapM(f); - - /// - /// Extract the lifted IO monad (if there is one) - /// - /// The map function - /// A new `Proxy` that represents the innermost IO monad, if it exists. - /// `Errors.UnliftIONotSupported` if there's no IO monad in the stack - [Pure] - public override Proxy> ToIO() => - Value.ToIO(); - - /// - /// `For(body)` loops over the `Proxy p` replacing each `yield` with `body` - /// - /// Any `yield` found in the `Proxy` will be replaced with this function. It will be composed so - /// that the value yielded will be passed to the argument of the function. That returns a `Proxy` to continue the - /// processing of the computation - /// A new `Proxy` that represents the composition of this `Proxy` and the function provided - [Pure] - public override Proxy For(Func> body) => - Value.For(body); - - /// - /// Applicative action - /// - /// Invokes this `Proxy`, then the `Proxy r` - /// - /// `Proxy` to run after this one - [Pure] - public override Proxy Action(Proxy r) => - Value.Action(r); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - /// - /// (f +>> p) pairs each 'request' in `this` with a 'respond' in `lhs`. - /// - [Pure] - public override Proxy PairEachRequestWithRespond( - Func> lhs) => - Value.PairEachRequestWithRespond(lhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy ReplaceRequest( - Func> lhs) => - Value.ReplaceRequest(lhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy PairEachRespondWithRequest( - Func> rhs) => - Value.PairEachRespondWithRequest(rhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy ReplaceRespond( - Func> rhs) => - Value.ReplaceRespond(rhs); - - /// - /// Reverse the arrows of the `Proxy` to find its dual. - /// - /// The dual of `this` - [Pure] - public override Proxy Reflect() => - Value.Reflect(); - - /// - /// - /// Observe(lift (Pure(r))) = Observe(Pure(r)) - /// Observe(lift (m.Bind(f))) = Observe(lift(m.Bind(x => lift(f(x))))) - /// - /// This correctness comes at a small cost to performance, so use this function sparingly. - /// This function is a convenience for low-level pipes implementers. You do not need to - /// use observe if you stick to the safe API. - /// - [Pure] - public override Proxy Observe() => - Value.Observe(); - - [Pure] - public void Deconstruct(out Proxy value) => - value = Value; - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Effect SelectMany(Func> f, Func project) => - Value.Bind(x => f(x).Map(y => project(x, y))).ToEffect(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Effect SelectMany(Func> f, Func project) => - SelectMany(a => Effect.liftIO(f(a)), project); - - /// - /// Monadic bind operation, for chaining `Effect` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Eff` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public K SelectMany(Func> bind, Func project) => - M.Bind(this.RunEffect(), a => M.Map(b => project(a, b), bind(a))); - - /// - /// Chain one effect after another - /// - [Pure] - public static Effect operator &( - Effect lhs, - Effect rhs) => - lhs.Bind(_ => rhs).ToEffect(); - - [Pure] - public override string ToString() => - "effect"; -} diff --git a/LanguageExt.Pipes/Effect/Effect.cs b/LanguageExt.Pipes/Effect/Effect.cs deleted file mode 100644 index bd591fb27..000000000 --- a/LanguageExt.Pipes/Effect/Effect.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using System.Diagnostics.Contracts; -using System.Linq; -using static LanguageExt.Pipes.Proxy; -using System.Runtime.CompilerServices; -using LanguageExt.Async.Linq; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -/// -/// Effects represent a 'fused' set of producer, pipes, and consumer into one type. -/// -/// It neither can neither `yield` nor be `awaiting`, it represents an entirely closed effect system. -/// -/// -/// Upstream | Downstream -/// +---------+ -/// | | -/// Void〈== 〈== Unit -/// | | -/// Unit ==〉 ==〉Void -/// | | | -/// +----|----+ -/// | -/// A -/// -public static class Effect -{ - [Pure] - public static K RunEffect(this K, R> ma) - where M : Monad - { - return Go(ma.As()); - - K Go(Proxy p) => - p.ToProxy() switch - { - ProxyM (var mx) => M.Bind(mx, Go), - Pure (var r) => M.Pure(r), - Iterator iter => runIterator(iter, Go), - IteratorAsync iter => runAsyncIterator(iter, Go), - Request (var v, _) => closed>(v), - Respond (var v, _) => closed>(v), - _ => throw new NotSupportedException() - }; - } - - static K runIterator( - Iterator iter, - Func, K> go) - where M : Monad => - from _ in iter.Run().Select(e => e.RunEffect()).Actions() - from r in go(iter.Next()) - select r; - - static K runAsyncIterator( - IteratorAsync iter, - Func, K> go) - where M : Monad => - from _ in iter.Run().Select(e => e.RunEffect()).Actions() - from r in go(iter.Next()) - select r; - - [Pure] - static Proxy HoistX( - this Proxy ma, - Func>, K>> nat) - where M : Monad - where N : Monad - { - return Go(ma); - - Proxy Go(Proxy p) => - p.ToProxy() switch - { - ProxyM (var mx) => new ProxyM(nat(mx.Map(Go))), - Pure (var r) => new Pure (r), - Request (var a1, var fa) => new Request(a1, a =>Go(fa(a))), - Respond (var b, var fb1) => new Respond (b, b1 => Go(fb1(b1))), - _ => throw new NotSupportedException() - }; - } - - [Pure, MethodImpl(mops)] - public static Effect lift(K ma) - where M : Monad => - lift(ma).ToEffect(); - - [Pure, MethodImpl(mops)] - public static Effect liftIO(IO ma) - where M : Monad => - liftIO(ma).ToEffect(); - - [Pure, MethodImpl(mops)] - public static Effect SelectMany( - this K ma, - Func> bind, - Func project) - where M : Monad => - lift(ma).SelectMany(bind, project); -} diff --git a/Samples/PipesExamples/EffectT/EffectT.Extensions.cs b/LanguageExt.Pipes/EffectT/EffectT.Extensions.cs similarity index 98% rename from Samples/PipesExamples/EffectT/EffectT.Extensions.cs rename to LanguageExt.Pipes/EffectT/EffectT.Extensions.cs index da8afe615..573e82df2 100644 --- a/Samples/PipesExamples/EffectT/EffectT.Extensions.cs +++ b/LanguageExt.Pipes/EffectT/EffectT.Extensions.cs @@ -1,6 +1,7 @@ +using System; using LanguageExt.Traits; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; public static class EffectTExtensions { diff --git a/Samples/PipesExamples/EffectT/EffectT.Module.cs b/LanguageExt.Pipes/EffectT/EffectT.Module.cs similarity index 98% rename from Samples/PipesExamples/EffectT/EffectT.Module.cs rename to LanguageExt.Pipes/EffectT/EffectT.Module.cs index 679977837..ca28e4b64 100644 --- a/Samples/PipesExamples/EffectT/EffectT.Module.cs +++ b/LanguageExt.Pipes/EffectT/EffectT.Module.cs @@ -1,7 +1,9 @@ +using System; +using System.Threading.Tasks; using LanguageExt.Common; using LanguageExt.Traits; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; /// /// `EffectT` streaming effect monad-transformer diff --git a/Samples/PipesExamples/EffectT/EffectT.Monad.cs b/LanguageExt.Pipes/EffectT/EffectT.Monad.cs similarity index 94% rename from Samples/PipesExamples/EffectT/EffectT.Monad.cs rename to LanguageExt.Pipes/EffectT/EffectT.Monad.cs index eb04598de..3e07491f0 100644 --- a/Samples/PipesExamples/EffectT/EffectT.Monad.cs +++ b/LanguageExt.Pipes/EffectT/EffectT.Monad.cs @@ -1,7 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Linq; using LanguageExt.Async.Linq; using LanguageExt.Traits; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; public class EffectT : MonadT, M> where M : Monad diff --git a/Samples/PipesExamples/EffectT/EffectT.cs b/LanguageExt.Pipes/EffectT/EffectT.cs similarity index 96% rename from Samples/PipesExamples/EffectT/EffectT.cs rename to LanguageExt.Pipes/EffectT/EffectT.cs index 38bed4948..4ff378cf1 100644 --- a/Samples/PipesExamples/EffectT/EffectT.cs +++ b/LanguageExt.Pipes/EffectT/EffectT.cs @@ -1,7 +1,9 @@ +using System; using System.Diagnostics.Contracts; +using System.Threading.Tasks; using LanguageExt.Traits; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; public readonly record struct EffectT(PipeT Proxy) : K, A> where M : Monad diff --git a/LanguageExt.Pipes/Extensions/Extensions.MapApply.cs b/LanguageExt.Pipes/Extensions/Extensions.MapApply.cs deleted file mode 100644 index 61a43a2b1..000000000 --- a/LanguageExt.Pipes/Extensions/Extensions.MapApply.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using LanguageExt.Traits; -using LanguageExt.Pipes; - -namespace LanguageExt; - -public static partial class ProxyExtensions -{ - /// - /// Functor map operation - /// - /// - /// Unwraps the value within the functor, passes it to the map function `f` provided, and - /// then takes the mapped value and wraps it back up into a new functor. - /// - /// Functor to map - /// Mapping function - /// Mapped functor - public static Proxy Map( - this Func f, - K, A> ma) - where M : Monad => - Functor.map(f, ma).As(); - - /// - /// Functor map operation - /// - /// - /// Unwraps the value within the functor, passes it to the map function `f` provided, and - /// then takes the mapped value and wraps it back up into a new functor. - /// - /// Functor to map - /// Mapping function - /// Mapped functor - public static Proxy Map( - this Func f, - Proxy ma) - where M : Monad => - Functor.map(f, ma).As(); - - /// - /// Applicative action: runs the first applicative, ignores the result, and returns the second applicative - /// - public static Proxy Action( - this Proxy ma, - K, B> mb) - where M : Monad => - Applicative.action(ma, mb).As(); - - /// - /// Applicative action: runs the first applicative, ignores the result, and returns the second applicative - /// - public static Proxy Action( - this K, A> ma, - K, B> mb) - where M : Monad => - Applicative.action(ma, mb).As(); - - /// - /// Applicative functor apply operation - /// - /// - /// Unwraps the value within the `ma` applicative-functor, passes it to the unwrapped function(s) within `mf`, and - /// then takes the resulting value and wraps it back up into a new applicative-functor. - /// - /// Value(s) applicative functor - /// Mapping function(s) - /// Mapped applicative functor - public static Proxy Apply( - this Proxy> mf, - K, A> ma) - where M : Monad => - Applicative.apply(mf, ma).As(); - - /// - /// Applicative functor apply operation - /// - /// - /// Unwraps the value within the `ma` applicative-functor, passes it to the unwrapped function(s) within `mf`, and - /// then takes the resulting value and wraps it back up into a new applicative-functor. - /// - /// Value(s) applicative functor - /// Mapping function(s) - /// Mapped applicative functor - public static Proxy Apply( - this K, Func> mf, - K, A> ma) - where M : Monad => - Applicative.apply(mf, ma).As(); -} diff --git a/LanguageExt.Pipes/Extensions/Extensions.cs b/LanguageExt.Pipes/Extensions/Extensions.cs deleted file mode 100644 index 9146a9874..000000000 --- a/LanguageExt.Pipes/Extensions/Extensions.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using LanguageExt.Pipes; -using System.Diagnostics.Contracts; -using System.Runtime.CompilerServices; -using LanguageExt.Traits; - -namespace LanguageExt; - -public static partial class ProxyExtensions -{ - public static Proxy As( - this K, A> ma) - where M : Monad => - (Proxy)ma; - - [Pure] - public static Effect As( - this K, A> ma) - where M : Monad => - ma switch - { - Effect e => e, - Proxy p => new Effect(p), - _ => throw new InvalidCastException($"Expected an Effect or Proxy, but got: {ma.GetType()}") - }; - - public static Producer As( - this K, A> ma) - where M : Monad => - ma switch - { - Producer p => p, - Proxy p => new Producer(p), - _ => throw new InvalidCastException($"Expected a Producer or Proxy, but got: {ma.GetType()}") - }; - - public static Consumer As( - this K, A> ma) - where M : Monad => - ma switch - { - Consumer c => c, - Proxy p => new Consumer(p), - _ => throw new InvalidCastException($"Expected a Consumer or Proxy, but got: {ma.GetType()}") - }; - - public static Pipe As( - this K, A> ma) - where M : Monad => - ma switch - { - Pipe p => p, - Proxy p => new Pipe(p), - _ => throw new InvalidCastException($"Expected a Pipe or Proxy, but got: {ma.GetType()}") - }; - - public static Client As( - this K, A> ma) - where M : Monad => - ma switch - { - Client c => c, - Proxy p => new Client(p), - _ => throw new InvalidCastException($"Expected a Client or Proxy, but got: {ma.GetType()}") - }; - - public static Server As( - this K, A> ma) - where M : Monad => - ma switch - { - Server s => s, - Proxy p => new Server(p), - _ => throw new InvalidCastException($"Expected a Server Proxy, but got: {ma.GetType()}") - }; - - /// - /// Converts a `Proxy` with the correct _shape_ into an `Effect` - /// - [Pure] - public static Effect ToEffect(this Proxy ma) - where M : Monad => - ma as Effect ?? new Effect(ma); - - /// - /// Converts a `Proxy` with the correct _shape_ into a `Producer` - /// - [Pure] - public static Producer ToProducer(this Proxy ma) - where M : Monad => - ma as Producer ?? new Producer(ma); - - /// - /// Converts a `Proxy` with the correct _shape_ into a `Consumer` - /// - [Pure] - public static Consumer ToConsumer(this Proxy ma) - where M : Monad => - ma as Consumer ?? new Consumer(ma); - - /// - /// Converts a `Proxy` with the correct _shape_ into n `Pipe` - /// - [Pure] - public static Pipe ToPipe(this Proxy ma) - where M : Monad => - ma as Pipe ?? new Pipe(ma); - - /// - /// Converts a `Proxy` with the correct _shape_ into a `Client` - /// - [Pure] - public static Client ToClient(this Proxy ma) - where M : Monad => - ma as Client ?? new Client(ma); - - /// - /// Converts a `Proxy` with the correct _shape_ into a `Server` - /// - [Pure] - public static Server ToServer(this Proxy ma) - where M : Monad => - ma as Server ?? new Server(ma); -} diff --git a/LanguageExt.Pipes/Extensions/LINQ.cs b/LanguageExt.Pipes/Extensions/LINQ.cs deleted file mode 100644 index 9b107aace..000000000 --- a/LanguageExt.Pipes/Extensions/LINQ.cs +++ /dev/null @@ -1,162 +0,0 @@ -using System; -using System.Diagnostics.Contracts; -using LanguageExt.Pipes; -using LanguageExt.Traits; - -namespace LanguageExt; - -public static partial class ProxyExtensions -{ - /// - /// Monad bind (specialised) - /// - [Pure] - public static Producer Bind( - this Proxy ma, - Func> f) - where M : Monad => - ma.Bind(f).ToProducer(); - - /// - /// Monad bind (specialised) - /// - [Pure] - public static Consumer Bind( - this Proxy ma, - Func> f) - where M : Monad => - ma.Bind(f).ToConsumer(); - - /// - /// Monad bind (specialised) - /// - [Pure] - public static Pipe Bind( - this Proxy ma, - Func> f) - where M : Monad => - ma.Bind(f).ToPipe(); - - /// - /// Monad bind (specialised) - /// - [Pure] - public static Client Bind( - this Proxy ma, - Func> f) - where M : Monad => - ma.Bind(f).ToClient(); - - /// - /// Monad bind (specialised) - /// - [Pure] - public static Server Bind( - this Proxy ma, - Func> f) - where M : Monad => - ma.Bind(f).ToServer(); - - - /// - /// Monad bind (specialised) - /// - [Pure] - public static Producer SelectMany( - this Proxy ma, - Func> f) - where M : Monad => - ma.Bind(f).ToProducer(); - - /// - /// Monad bind (specialised) - /// - [Pure] - public static Consumer SelectMany( - this Proxy ma, - Func> f) - where M : Monad => - ma.Bind(f).ToConsumer(); - - /// - /// Monad bind (specialised) - /// - [Pure] - public static Pipe SelectMany( - this Proxy ma, - Func> f) - where M : Monad => - ma.Bind(f).ToPipe(); - - /// - /// Monad bind (specialised) - /// - [Pure] - public static Client SelectMany( - this Proxy ma, - Func> f) - where M : Monad => - ma.Bind(f).ToClient(); - - /// - /// Monad bind (specialised) - /// - [Pure] - public static Server SelectMany( - this Proxy ma, Func> f) - where M : Monad => - ma.Bind(f).ToServer(); - - - /// - /// Monad bind (specialised) - /// - [Pure] - public static Producer SelectMany( - this Proxy ma, Func> f, - Func project) - where M : Monad => - ma.Bind(a => f(a).Map(b => project(a, b))).ToProducer(); - - /// - /// Monad bind (specialised) - /// - [Pure] - public static Consumer SelectMany( - this Proxy ma, - Func> f, Func project) - where M : Monad => - ma.Bind(a => f(a).Map(b => project(a, b))).ToConsumer(); - - /// - /// Monad bind (specialised) - /// - [Pure] - public static Pipe SelectMany( - this Proxy ma, - Func> f, - Func project) - where M : Monad => - ma.Bind(a => f(a).Map(b => project(a, b))).ToPipe(); - - /// - /// Monad bind (specialised) - /// - [Pure] - public static Client SelectMany( - this Proxy ma, - Func> f, - Func project) - where M : Monad => - ma.Bind(a => f(a).Map(b => project(a, b))).ToClient(); - - /// - /// Monad bind (specialised) - /// - [Pure] - public static Server SelectMany( - this Proxy ma, - Func> f, Func project) - where M : Monad => - ma.Bind(a => f(a).Map(b => project(a, b))).ToServer(); -} diff --git a/LanguageExt.Pipes/Iterator/CoreTypes.cs b/LanguageExt.Pipes/Iterator/CoreTypes.cs deleted file mode 100644 index c3cfd5986..000000000 --- a/LanguageExt.Pipes/Iterator/CoreTypes.cs +++ /dev/null @@ -1,229 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.Contracts; -using System.Linq; -using System.Threading.Tasks; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -public abstract record Iterator( - Func> Next) - : Proxy - where M : Monad -{ - public abstract IEnumerable> Run(); -} - -public abstract record IteratorAsync( - Func> Next) - : Proxy - where M : Monad -{ - public abstract IAsyncEnumerable> Run(); -} - -public record IteratorFoldable( - K Items, - Func> Yield, - Func> Next) - : Iterator(Next) - where M : Monad - where F : Foldable -{ - public override Proxy ToProxy() => - this; - - public override IEnumerable> Run() - { - foreach (var item in Items.ToIterable()) - { - yield return Yield(item); - } - } - - public override Proxy Bind( - Func> f) => - new IteratorFoldable( - Items, - Yield, - () => Next().Bind(f)); - - public override Proxy Map( - Func f) => - new IteratorFoldable( - Items, - Yield, - () => Next().Map(f)); - - public override Proxy MapM( - Func, K> f) => - new IteratorFoldable( - Items, - Yield, - () => Next().MapM(f)); - - /// - /// Extract the lifted IO monad (if there is one) - /// - /// The map function - /// A new `Proxy` that represents the innermost IO monad, if it exists. - /// `Errors.UnliftIONotSupported` if there's no IO monad in the stack - [Pure] - public override Proxy> ToIO() => - new IteratorFoldable>( - Items, - Yield, - () => Next().ToIO()); - - public override Proxy For( - Func> body) => - ReplaceRespond(body); - - public override Proxy Action( - Proxy r) => - new IteratorFoldable( - Items, - Yield, - () => Next().Action(r)); - - public override Proxy PairEachRequestWithRespond( - Func> lhs) => - new IteratorFoldable( - Items, - c1 => Yield(c1).PairEachRequestWithRespond(x => lhs(x).Map(_ => Prelude.unit)), - () => Next().PairEachRequestWithRespond(lhs)); - - public override Proxy ReplaceRequest( - Func> lhs) => - new IteratorFoldable( - Items, - c1 => Yield(c1).ReplaceRequest(lhs), - () => Next().ReplaceRequest(lhs)); - - public override Proxy PairEachRespondWithRequest( - Func> rhs) => - new IteratorFoldable( - Items, - c1 => Yield(c1).PairEachRespondWithRequest(x => rhs(x).Map(_ => Prelude.unit)), - () => Next().PairEachRespondWithRequest(rhs)); - - public override Proxy ReplaceRespond( - Func> rhs) => - new IteratorFoldable( - Items, - c1 => Yield(c1).ReplaceRespond(rhs), - () => Next().ReplaceRespond(rhs)); - - public override Proxy Reflect() => - new IteratorFoldable( - Items, - x => Yield(x).Reflect(), - () => Next().Reflect()); - - public override Proxy Observe() => - new ProxyM(M.Pure>(this)); -} - -public record IteratorAsyncEnumerable( - IAsyncEnumerable Items, - Func> Yield, - Func> Next) - : IteratorAsync(Next) - where M : Monad - where F : Foldable -{ - public override Proxy ToProxy() => - this; - - public override async IAsyncEnumerable> Run() - { - await foreach (var item in Items) - { - yield return Yield(item); - } - } - - public override Proxy Bind( - Func> f) => - new IteratorAsyncEnumerable( - Items, - Yield, - () => Next().Bind(f)); - - public override Proxy Map( - Func f) => - new IteratorAsyncEnumerable( - Items, - Yield, - () => Next().Map(f)); - - public override Proxy MapM( - Func, K> f) => - new IteratorAsyncEnumerable( - Items, - Yield, - () => Next().MapM(f)); - - /// - /// Extract the lifted IO monad (if there is one) - /// - /// The map function - /// A new `Proxy` that represents the innermost IO monad, if it exists. - /// `Errors.UnliftIONotSupported` if there's no IO monad in the stack - [Pure] - public override Proxy> ToIO() => - new IteratorAsyncEnumerable>( - Items, - Yield, - () => Next().ToIO()); - - public override Proxy For( - Func> body) => - ReplaceRespond(body); - - public override Proxy Action( - Proxy r) => - new IteratorAsyncEnumerable( - Items, - Yield, - () => Next().Action(r)); - - public override Proxy PairEachRequestWithRespond( - Func> lhs) => - new IteratorAsyncEnumerable( - Items, - c1 => Yield(c1).PairEachRequestWithRespond(x => lhs(x).Map(_ => Prelude.unit)), - () => Next().PairEachRequestWithRespond(lhs)); - - public override Proxy ReplaceRequest( - Func> lhs) => - new IteratorAsyncEnumerable( - Items, - c1 => Yield(c1).ReplaceRequest(lhs), - () => Next().ReplaceRequest(lhs)); - - public override Proxy PairEachRespondWithRequest( - Func> rhs) => - new IteratorAsyncEnumerable( - Items, - c1 => Yield(c1).PairEachRespondWithRequest(x => rhs(x).Map(_ => Prelude.unit)), - () => Next().PairEachRespondWithRequest(rhs)); - - public override Proxy ReplaceRespond( - Func> rhs) => - new IteratorAsyncEnumerable( - Items, - c1 => Yield(c1).ReplaceRespond(rhs), - () => Next().ReplaceRespond(rhs)); - - public override Proxy Reflect() => - new IteratorAsyncEnumerable( - Items, - x => Yield(x).Reflect(), - () => Next().Reflect()); - - public override Proxy Observe() => - new ProxyM(M.Pure>(this)); -} diff --git a/LanguageExt.Pipes/Pipe/CoreTypes.cs b/LanguageExt.Pipes/Pipe/CoreTypes.cs deleted file mode 100644 index 0ba85b53a..000000000 --- a/LanguageExt.Pipes/Pipe/CoreTypes.cs +++ /dev/null @@ -1,368 +0,0 @@ -using System; -using System.Diagnostics.Contracts; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -/// -/// Pipes both can both be `await` and can `yield` -/// -/// -/// Upstream | Downstream -/// +---------+ -/// | | -/// Unit〈== 〈== Unit -/// | | -/// IN ==〉 ==〉OUT -/// | | | -/// +----|----+ -/// | -/// A -/// -public record Pipe : Proxy - where M : Monad -{ - public readonly Proxy Value; - - /// - /// Constructor - /// - /// Correctly shaped `Proxy` that represents a `Pipe` - public Pipe(Proxy value) => - Value = value; - - /// - /// Calling this will effectively cast the sub-type to the base. - /// - /// This type wraps up a `Proxy` for convenience, and so it's a `Proxy` proxy. So calling this method - /// isn't exactly the same as a cast operation, as it unwraps the `Proxy` from within. It has the same effect - /// however, and removes a level of indirection - /// A general `Proxy` type from a more specialised type - [Pure] - public override Proxy ToProxy() => - Value.ToProxy(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public override Proxy Bind( - Func> f) => - Value.Bind(f); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Pipe Bind(Func> f) => - Value.Bind(x => Pipe.lift(f(x))).ToPipe(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Pipe Bind(Func> f) => - Value.Bind(x => Pipe.liftIO(f(x))).ToPipe(); - - /// - /// Lifts a pure function into the `Proxy` domain, causing it to map the bound value within - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy Map(Func f) => - Value.Map(f); - - /// - /// Map the lifted monad - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy MapM(Func, K> f) => - Value.MapM(f); - - /// - /// Extract the lifted IO monad (if there is one) - /// - /// The map function - /// A new `Proxy` that represents the innermost IO monad, if it exists. - /// `Errors.UnliftIONotSupported` if there's no IO monad in the stack - [Pure] - public override Proxy> ToIO() => - Value.ToIO(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Pipe Bind(Func> f) => - Value.Bind(f).ToPipe(); - - /// - /// Lifts a pure function into the `Proxy` domain, causing it to map the bound value within - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public new Pipe Select(Func f) => - Value.Map(f).ToPipe(); - - /// - /// `For(body)` loops over the `Proxy p` replacing each `yield` with `body` - /// - /// Any `yield` found in the `Proxy` will be replaced with this function. It will be composed so - /// that the value yielded will be passed to the argument of the function. That returns a `Proxy` to continue the - /// processing of the computation - /// A new `Proxy` that represents the composition of this `Proxy` and the function provided - [Pure] - public override Proxy For( - Func> body) => - Value.For(body); - - /// - /// Applicative action - /// - /// Invokes this `Proxy`, then the `Proxy r` - /// - /// `Proxy` to run after this one - [Pure] - public override Proxy Action(Proxy r) => - Value.Action(r); - - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - /// - /// (f +>> p) pairs each 'request' in `this` with a 'respond' in `lhs`. - /// - [Pure] - public override Proxy PairEachRequestWithRespond( - Func> lhs) => - Value.PairEachRequestWithRespond(lhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy ReplaceRequest( - Func> lhs) => - Value.ReplaceRequest(lhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy PairEachRespondWithRequest( - Func> rhs) => - Value.PairEachRespondWithRequest(rhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy ReplaceRespond( - Func> rhs) => - Value.ReplaceRespond(rhs); - - /// - /// Reverse the arrows of the `Proxy` to find its dual. - /// - /// The dual of `this` - [Pure] - public override Proxy Reflect() => - Value.Reflect(); - - /// - /// - /// Observe(lift (Pure(r))) = Observe(Pure(r)) - /// Observe(lift (m.Bind(f))) = Observe(lift(m.Bind(x => lift(f(x))))) - /// - /// This correctness comes at a small cost to performance, so use this function sparingly. - /// This function is a convenience for low-level pipes implementers. You do not need to - /// use observe if you stick to the safe API. - /// - [Pure] - public override Proxy Observe() => - Value.Observe(); - - [Pure] - public void Deconstruct(out Proxy value) => - value = Value; - - /// - /// Compose a `Producer` and a `Pipe` together into a `Producer`. - /// - /// `Producer` - /// `Pipe` - /// `Producer` - [Pure] - public static Producer operator |(Producer p1, Pipe p2) => - Proxy.compose(p1, p2); - - /// - /// Compose a `Producer` and a `Pipe` together into a `Producer`. - /// - /// `Producer` - /// `Pipe` - /// `Producer` - [Pure] - public static Producer operator |(Producer p1, Pipe p2) => - Proxy.compose(p1, p2); - - /// - /// Compose a `Producer` and a `Pipe` together into a `Producer`. - /// - /// `Producer` - /// `Pipe` - /// `Producer` - [Pure] - public static Producer operator |(Producer p1, Pipe p2) => - Proxy.compose(p1, p2); - - /// - /// Compose a `Pipe` and a `Consumer` together into a `Consumer`. - /// - /// `Pipe` - /// `Consumer` - /// `Consumer` - [Pure] - public static Consumer operator |(Pipe p1, Consumer p2) => - Proxy.compose(p1, p2); - - /// - /// Compose a `Pipe` and a `Consumer` together into a `Consumer`. - /// - /// `Pipe` - /// `Consumer` - /// `Consumer` - [Pure] - public static Consumer operator |(Pipe p1, Consumer p2) => - Proxy.compose(p1, p2); - - /// - /// Composition chaining of two pipes. - /// - /// - /// We can't provide the operator overloading to chain two pipes together, because operators don't have - /// generics of their own. And so we can use this method to chain to pipes together. - /// - /// Right hand side `Pipe` - /// Type of value that the right hand side pipe yields - /// A composition of this pipe and the `Pipe` provided - [Pure] - public Pipe Then(Pipe pipe) => - Proxy.compose(this, pipe); - - /// - /// Conversion operator from the _pure_ `Pipe` type, to the monad transformer version of the `Pipe` - /// - /// Pure `Pipe` - /// Monad transformer version of the `Pipe` - [Pure] - public static implicit operator Pipe(Pipe p) => - p.Interpret(); - - /// - /// Conversion operator from the `Pure` type, to the monad transformer version of the `Pipe` - /// - /// `Pure` value - /// Monad transformer version of the `Pipe` - [Pure] - public static implicit operator Pipe(Pure p) => - Pipe.Pure(p.Value); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Pipe SelectMany(Func> bind) => - Value.Bind(a => bind(a).Interpret()).ToPipe(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Pipe SelectMany(Func> bind, Func project) => - SelectMany(a => bind(a).Select(b => project(a, b))); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Pipe SelectMany(Func> f) => - Value.Bind(f).ToPipe(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Pipe SelectMany(Func> f, Func project) => - Value.Bind(a => f(a).Map(b => project(a, b))).ToPipe(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Pipe SelectMany(Func> bind, Func project) => - Bind(x => M.Map(y => project(x, y), bind(x))); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Pipe SelectMany(Func> bind, Func project) => - Bind(x => bind(x).Map(y => project(x, y))); - - /// - /// Chain one pipe's set of awaits and yields after another - /// - [Pure] - public static Pipe operator &( - Pipe lhs, - Pipe rhs) => - lhs.Bind(_ => rhs); - - [Pure] - public override string ToString() => - "pipe"; -} diff --git a/LanguageExt.Pipes/Pipe/Pipe.cs b/LanguageExt.Pipes/Pipe/Pipe.cs deleted file mode 100644 index 5cbe5eb12..000000000 --- a/LanguageExt.Pipes/Pipe/Pipe.cs +++ /dev/null @@ -1,219 +0,0 @@ -using System; -using static LanguageExt.Prelude; -using System.Diagnostics.Contracts; -using static LanguageExt.Pipes.Proxy; -using System.Runtime.CompilerServices; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -/// -/// Pipes both can both be `await` and can `yield` -/// -/// -/// Upstream | Downstream -/// +---------+ -/// | | -/// Unit〈== 〈== Unit -/// | | -/// IN ==〉 ==〉OUT -/// | | | -/// +----|----+ -/// | -/// A -/// -public static class Pipe -{ - /// - /// Monad return / pure - /// - [Pure, MethodImpl(mops)] - public static Pipe Pure(R value) where M : Monad => - new Pure(value).ToPipe(); - - /// - /// Wait for a value from upstream (whilst in a pipe) - /// - /// - /// This is the version of `await` that works for pipes. In consumers, use `Consumer.await` - /// - [Pure, MethodImpl(mops)] - public static Pipe awaiting() - where M : Monad => - request(unit).ToPipe(); - - /// - /// Send a value downstream (whilst in a pipe) - /// - /// - /// This is the version of `yield` that works for pipes. In producers, use `Producer.yield` - /// - [Pure, MethodImpl(mops)] - public static Pipe yield(OUT value) - where M : Monad => - respond(value).ToPipe(); - - /// - /// Only forwards values that satisfy the predicate. - /// - public static Pipe filter(Func f) - where M : Monad => - cat().For(a => f(a) - ? yield(a) - : Pure(default)) - .ToPipe(); - - /// - /// Map the output of the pipe (not the bound value as is usual with Map) - /// - public static Pipe map(Func f) - where M : Monad => - cat().For(a => yield(f(a))).ToPipe(); - - /// - /// Map the output of the pipe (not the bound value as is usual with Map) - /// - public static Pipe map(Func f) - where M : Monad => - cat().For(a => yield(f(a))).ToPipe(); - - /// - /// Map the output of the pipe (not the bound value as is usual with Map) - /// - public static Pipe map(Func f) => - new Pipe.Await(x => new Pipe.Yield(f(x), PureProxy.PipePure)); - - /// - /// Apply a monadic function to all values flowing downstream (not the bound value as is usual with Map) - /// - [Pure, MethodImpl(mops)] - public static Pipe mapM(Func> f) where M : Monad => - cat() - .ForEach(a => lift(f(a)).Bind(x => yield(x)).ToPipe()); - - /// - /// Lift the IO monad into the Pipe monad transformer (a specialism of the Proxy monad transformer) - /// - [Pure, MethodImpl(mops)] - public static Pipe lift(K ma) - where M : Monad => - lift(ma).ToPipe(); - - /// - /// Lift the IO monad into the Pipe monad transformer (a specialism of the Proxy monad transformer) - /// - [Pure, MethodImpl(mops)] - public static Pipe liftIO(IO ma) - where M : Monad => - liftIO(ma).ToPipe(); - - /// - /// Folds values coming down-stream, when the predicate returns false the folded value is yielded - /// - /// Initial state - /// Fold operation - /// Predicate - /// A pipe that folds - [Pure, MethodImpl(mops)] - public static Pipe foldWhile( - OUT Initial, - Func Fold, - Func WhileState) - where M : Monad => - foldUntil(Initial, Fold, x => !WhileState(x)); - - /// - /// Folds values coming down-stream, when the predicate returns true the folded value is yielded - /// - /// Initial state - /// Fold operation - /// Predicate - /// A pipe that folds - public static Pipe foldUntil( - OUT Initial, - Func Fold, - Func UntilState) - where M : Monad - { - var state = Initial; - return awaiting() - .Bind(x => - { - state = Fold(state, x); - if (UntilState(state)) - { - var nstate = state; - state = Initial; - return yield(nstate); - } - else - { - return Pure(unit); - } - }) - .ToPipe(); - } - - /// - /// Folds values coming down-stream, when the predicate returns false the folded value is yielded - /// - /// Initial state - /// Fold operation - /// Predicate - /// A pipe that folds - [Pure, MethodImpl(mops)] - public static Pipe foldWhile( - OUT Initial - , Func Fold, - Func WhileValue) - where M : Monad => - foldUntil(Initial, Fold, x => !WhileValue(x)); - - /// - /// Folds values coming down-stream, when the predicate returns true the folded value is yielded - /// - /// Initial state - /// Fold operation - /// Predicate - /// A pipe that folds - public static Pipe foldUntil( - OUT Initial, - Func Fold, - Func UntilValue) - where M : Monad - { - var state = Initial; - return awaiting() - .Bind(x => - { - if (UntilValue(x)) - { - var nstate = state; - state = Initial; - return yield(nstate); - } - else - { - state = Fold(state, x); - return Pure(unit); - } - }) - .ToPipe(); - } - - /// - /// Strict left scan - /// - public static Pipe scan(Func Step, S Begin, Func Done) - where M : Monad - { - return go(Begin); - - Pipe go(S x) => - from _ in yield(Done(x)) - from a in awaiting() - let x1 = Step(x, a) - from r in go(x1) - select r; - } -} diff --git a/Samples/PipesExamples/PipeT/PipeT.Cached.cs b/LanguageExt.Pipes/PipeT/PipeT.Cached.cs similarity index 86% rename from Samples/PipesExamples/PipeT/PipeT.Cached.cs rename to LanguageExt.Pipes/PipeT/PipeT.Cached.cs index b87162ef8..0cabfcaf3 100644 --- a/Samples/PipesExamples/PipeT/PipeT.Cached.cs +++ b/LanguageExt.Pipes/PipeT/PipeT.Cached.cs @@ -1,6 +1,6 @@ using LanguageExt.Traits; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; class PipeTCached where M : Monad diff --git a/Samples/PipesExamples/PipeT/PipeT.DSL.cs b/LanguageExt.Pipes/PipeT/PipeT.DSL.cs similarity index 99% rename from Samples/PipesExamples/PipeT/PipeT.DSL.cs rename to LanguageExt.Pipes/PipeT/PipeT.DSL.cs index d1f390791..4b1201cde 100644 --- a/Samples/PipesExamples/PipeT/PipeT.DSL.cs +++ b/LanguageExt.Pipes/PipeT/PipeT.DSL.cs @@ -1,7 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; using LanguageExt.Async.Linq; using LanguageExt.Traits; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; record PipeTEmpty : PipeT where M : Monad, MonoidK diff --git a/Samples/PipesExamples/PipeT/PipeT.Extensions.cs b/LanguageExt.Pipes/PipeT/PipeT.Extensions.cs similarity index 98% rename from Samples/PipesExamples/PipeT/PipeT.Extensions.cs rename to LanguageExt.Pipes/PipeT/PipeT.Extensions.cs index 83b51186b..a8062e9fe 100644 --- a/Samples/PipesExamples/PipeT/PipeT.Extensions.cs +++ b/LanguageExt.Pipes/PipeT/PipeT.Extensions.cs @@ -1,6 +1,7 @@ +using System; using LanguageExt.Traits; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; public static class PipeTExtensions { diff --git a/Samples/PipesExamples/PipeT/PipeT.Module.cs b/LanguageExt.Pipes/PipeT/PipeT.Module.cs similarity index 99% rename from Samples/PipesExamples/PipeT/PipeT.Module.cs rename to LanguageExt.Pipes/PipeT/PipeT.Module.cs index 39457cb64..0f987b858 100644 --- a/Samples/PipesExamples/PipeT/PipeT.Module.cs +++ b/LanguageExt.Pipes/PipeT/PipeT.Module.cs @@ -1,9 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; using LanguageExt.Async.Linq; using LanguageExt.Common; using LanguageExt.Traits; using static LanguageExt.Prelude; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; /// /// `PipeT` streaming producer monad-transformer diff --git a/Samples/PipesExamples/PipeT/PipeT.Monad.cs b/LanguageExt.Pipes/PipeT/PipeT.Monad.cs similarity index 95% rename from Samples/PipesExamples/PipeT/PipeT.Monad.cs rename to LanguageExt.Pipes/PipeT/PipeT.Monad.cs index ff6e88487..b4264e878 100644 --- a/Samples/PipesExamples/PipeT/PipeT.Monad.cs +++ b/LanguageExt.Pipes/PipeT/PipeT.Monad.cs @@ -1,8 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; using LanguageExt.Async.Linq; using LanguageExt.Common; using LanguageExt.Traits; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; public class PipeT : MonadT, M> where M : Monad diff --git a/Samples/PipesExamples/PipeT/PipeT.cs b/LanguageExt.Pipes/PipeT/PipeT.cs similarity index 99% rename from Samples/PipesExamples/PipeT/PipeT.cs rename to LanguageExt.Pipes/PipeT/PipeT.cs index 59a8ce26b..c6d0e4d10 100644 --- a/Samples/PipesExamples/PipeT/PipeT.cs +++ b/LanguageExt.Pipes/PipeT/PipeT.cs @@ -1,7 +1,9 @@ +using System; using System.Diagnostics.Contracts; +using System.Threading.Tasks; using LanguageExt.Traits; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; /// /// `PipeT` monad-transformer base-type for Pipes streaming components: diff --git a/LanguageExt.Pipes/Producer/CoreTypes.cs b/LanguageExt.Pipes/Producer/CoreTypes.cs deleted file mode 100644 index a218a6d38..000000000 --- a/LanguageExt.Pipes/Producer/CoreTypes.cs +++ /dev/null @@ -1,312 +0,0 @@ -using System; -using System.Diagnostics.Contracts; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -/// -/// Producers can only `yield` -/// -/// -/// Upstream | Downstream -/// +---------+ -/// | | -/// Void〈== 〈== Unit -/// | | -/// Unit ==〉 ==〉OUT -/// | | | -/// +----|----+ -/// | -/// A -/// -public record Producer : Proxy - where M : Monad -{ - public readonly Proxy Value; - - /// - /// Constructor - /// - /// Correctly shaped `Proxy` that represents a `Producer` - public Producer(Proxy value) => - Value = value; - - /// - /// Calling this will effectively cast the sub-type to the base. - /// - /// This type wraps up a `Proxy` for convenience, and so it's a `Proxy` proxy. So calling this method - /// isn't exactly the same as a cast operation, as it unwraps the `Proxy` from within. It has the same effect - /// however, and removes a level of indirection - /// A general `Proxy` type from a more specialised type - [Pure] - public override Proxy ToProxy() => - Value.ToProxy(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public override Proxy Bind( - Func> f) => - Value.Bind(f); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Producer Bind(Func> f) => - Value.Bind(x => Producer.lift(f(x))).ToProducer(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Producer Bind(Func> f) => - Value.Bind(x => Producer.liftIO(f(x))).ToProducer(); - - /// - /// Lifts a pure function into the `Proxy` domain, causing it to map the bound value within - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy Map(Func f) => - Value.Map(f); - - /// - /// Map the lifted monad - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy MapM(Func, K> f) => - Value.MapM(f); - - /// - /// Extract the lifted IO monad (if there is one) - /// - /// The map function - /// A new `Proxy` that represents the innermost IO monad, if it exists. - /// `Errors.UnliftIONotSupported` if there's no IO monad in the stack - [Pure] - public override Proxy> ToIO() => - Value.ToIO(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Producer Bind(Func> f) => - Value.Bind(f).ToProducer(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Producer SelectMany(Func> f) => - Value.Bind(f).ToProducer(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Producer SelectMany(Func> f, Func project) => - Value.Bind(a => f(a).Map(b => project(a, b))).ToProducer(); - - /// - /// Lifts a pure function into the `Proxy` domain, causing it to map the bound value within - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public new Producer Select(Func f) => - Value.Map(f).ToProducer(); - - /// - /// `For(body)` loops over the `Proxy p` replacing each `yield` with `body` - /// - /// Any `yield` found in the `Proxy` will be replaced with this function. It will be composed so - /// that the value yielded will be passed to the argument of the function. That returns a `Proxy` to continue the - /// processing of the computation - /// A new `Proxy` that represents the composition of this `Proxy` and the function provided - [Pure] - public override Proxy For(Func> body) => - Value.ReplaceRespond(body); - - /// - /// Applicative action - /// - /// Invokes this `Proxy`, then the `Proxy r` - /// - /// `Proxy` to run after this one - [Pure] - public override Proxy Action(Proxy r) => - Value.Action(r); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - /// - /// (f +>> p) pairs each 'request' in `this` with a 'respond' in `lhs`. - /// - [Pure] - public override Proxy PairEachRequestWithRespond( - Func> lhs) => - Value.PairEachRequestWithRespond(lhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy ReplaceRequest( - Func> lhs) => - Value.ReplaceRequest(lhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy PairEachRespondWithRequest( - Func> rhs) => - Value.PairEachRespondWithRequest(rhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy ReplaceRespond( - Func> rhs) => - Value.ReplaceRespond(rhs); - - /// - /// Reverse the arrows of the `Proxy` to find its dual. - /// - /// The dual of `this` - [Pure] - public override Proxy Reflect() => - Value.Reflect(); - - /// - /// - /// Observe(lift (Pure(r))) = Observe(Pure(r)) - /// Observe(lift (m.Bind(f))) = Observe(lift(m.Bind(x => lift(f(x))))) - /// - /// This correctness comes at a small cost to performance, so use this function sparingly. - /// This function is a convenience for low-level pipes implementers. You do not need to - /// use observe if you stick to the safe API. - /// - [Pure] - public override Proxy Observe() => - Value.Observe(); - - /// - /// Compose a `Producer` and a `Consumer` together into an `Effect`. - /// - /// `Producer` - /// `Consumer` - /// `Effect` - [Pure] - public static Effect operator |(Producer p1, Consumer p2) => - Proxy.compose(p1, p2); - - /// - /// Compose a `Producer` and a `Consumer` together into an `Effect`. - /// - /// `Producer` - /// `Consumer` - /// `Effect` - [Pure] - public static Effect operator |(Producer p1, Consumer p2) => - Proxy.compose(p1, p2); - - [Pure] - public void Deconstruct(out Proxy value) => - value = Value; - - /// - /// Conversion operator from the _pure_ `Producer` type, to the monad transformer version of the `Producer` - /// - /// Pure `Producer` - /// Monad transformer version of the `Producer` - [Pure] - public static implicit operator Producer(Producer p) => - p.Interpret(); - - /// - /// Conversion operator from the `Pure` type, to the monad transformer version of the `Producer` - /// - /// `Pure` value - /// Monad transformer version of the `Producer` - [Pure] - public static implicit operator Producer(Pure p) => - Producer.Pure(p.Value); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Producer SelectMany(Func> bind) => - Value.Bind(a => bind(a).Interpret()).ToProducer(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Producer SelectMany(Func> bind, Func project) => - SelectMany(a => bind(a).Select(b => project(a, b))); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Producer SelectMany(Func> bind, Func project) => - Bind(x => M.Map(y => project(x, y), bind(x))); - - /// - /// Chain one producer's set of yields after another - /// - [Pure] - public static Producer operator &( - Producer lhs, - Producer rhs) => - lhs.Bind(_ => rhs); - - [Pure] - public override string ToString() => - "producer"; -} diff --git a/LanguageExt.Pipes/Producer/Producer.cs b/LanguageExt.Pipes/Producer/Producer.cs deleted file mode 100644 index 2fa6b49ab..000000000 --- a/LanguageExt.Pipes/Producer/Producer.cs +++ /dev/null @@ -1,355 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics.Contracts; -using System.Runtime.CompilerServices; -using System.Threading; -using LanguageExt.Traits; -using LanguageExt.UnsafeValueAccess; -using static LanguageExt.Pipes.Proxy; -using static LanguageExt.Prelude; - -namespace LanguageExt.Pipes; - -/// -/// Producers can only `yield` -/// -/// -/// Upstream | Downstream -/// +---------+ -/// | | -/// Void == == Unit -/// | | -/// Unit ==〉 ==〉OUT -/// | | | -/// +----|----+ -/// | -/// A -/// -public static class Producer -{ - /// - /// Monad return / pure - /// - [Pure, MethodImpl(mops)] - public static Producer Pure(R value) - where M : Monad => - new Pure(value).ToProducer(); - - /// - /// Send a value downstream (whilst in a producer) - /// - /// - /// This is the simpler version (fewer generic arguments required) of `yield` that works - /// for producers. - /// - [Pure, MethodImpl(mops)] - public static Producer yield(OUT value) - where M : Monad => - respond(value).ToProducer(); - - [Pure, MethodImpl(mops)] - public static Producer yieldAll(IEnumerable xs) - where M : Monad => - new IteratorFoldable( - xs.AsIterable(), - yield, - () => Pure(unit)) - .ToProducer(); - - [Pure, MethodImpl(mops)] - public static Producer yieldAll(IAsyncEnumerable xs) - where M : Monad => - new IteratorAsyncEnumerable( - xs, - yield, - () => Pure(unit)) - .ToProducer(); - - [Pure, MethodImpl(mops)] - public static Producer yieldAll(IObservable xs) - where M : Monad => - yieldAll(xs.ToAsyncEnumerable(new CancellationToken())); - - /// - /// Repeat a monadic action indefinitely, yielding each result - /// - [Pure, MethodImpl(mops)] - public static Producer repeatM(K ma) - where M : Monad => - repeat(lift(ma).Bind(x => yield(x))); - - /// - /// Lift the IO monad into the Producer monad transformer (a specialism of the Proxy monad transformer) - /// - [Pure, MethodImpl(mops)] - public static Producer lift(K ma) - where M : Monad => - lift(ma).ToProducer(); - - /// - /// Lift the IO monad into the Producer monad transformer (a specialism of the Proxy monad transformer) - /// - [Pure, MethodImpl(mops)] - public static Producer liftIO(IO ma) - where M : Monad => - liftIO(ma).ToProducer(); - - /// - /// Folds values coming down-stream, when the predicate returns true the folded value is yielded - /// - /// Initial state - /// Fold operation - /// Predicate - /// A pipe that folds - public static Producer FoldUntil( - this Producer ma, - S Initial, - Func Fold, - Func UntilValue) - where M : Monad - { - var state = Initial; - return ma.Bind( - x => - { - if (UntilValue(x)) - { - var nstate = state; - state = Initial; - return yield(nstate); - } - else - { - state = Fold(state, x); - return Pure(unit); - } - }); - } - - /// - /// Folds values coming down-stream, when the predicate returns true the folded value is yielded - /// - /// Initial state - /// Fold operation - /// Predicate - /// A pipe that folds - public static Producer FoldWhile( - this Producer ma, - S Initial, - Func Fold, - Func WhileValue) - where M : Monad - { - var state = Initial; - return ma.Bind( - x => - { - if (WhileValue(x)) - { - state = Fold(state, x); - return Pure(unit); - } - else - { - var nstate = state; - state = Initial; - return yield(nstate); - } - }); - } - - /// - /// Folds values coming down-stream, when the predicate returns true the folded value is yielded - /// - /// Initial state - /// Fold operation - /// Predicate - /// A pipe that folds - public static Producer FoldUntil( - this Producer ma, - S Initial, Func Fold, - Func UntilState) - where M : Monad - { - var state = Initial; - return ma.Bind( - x => - { - state = Fold(state, x); - if (UntilState(state)) - { - var nstate = state; - state = Initial; - return yield(nstate); - } - else - { - return Pure(unit); - } - }); - } - - /// - /// Folds values coming down-stream, when the predicate returns true the folded value is yielded - /// - /// Initial state - /// Fold operation - /// Predicate - /// A pipe that folds - public static Producer FoldWhile( - this Producer ma, - S Initial, - Func Fold, - Func WhileState) - where M : Monad - { - var state = Initial; - return ma.Bind( - x => - { - state = Fold(state, x); - if (WhileState(state)) - { - return Pure(unit); - } - else - { - var nstate = state; - state = Initial; - return yield(nstate); - } - }); - } - - /// - /// Merge a sequence of producers into a single producer - /// - /// The merged producer completes when all component producers have completed - /// Sequence of producers to merge - /// Merged producers - public static Producer merge_OLD(Seq> ms) - where M : Monad => - ms switch - { - { IsEmpty : true } => lift(M.Pure(unit)), - { Tail.IsEmpty: true } => ms[0], - { Head : var h, Tail: var t } => - from x in h.ValueUnsafe()! - from xs in merge(t) - select x - }; - - public static Producer merge(Seq> ms) - where M : Monad - { - if (ms.Count == 0) return Pure(unit); - var complete = new CountdownEvent(ms.Count); - var wait = new AutoResetEvent(false); - var queue = new ConcurrentQueue(); - var effects = ms.Traverse(runEffect); - - return from t in liftIO(cancelToken) - from _ in effects - from r in yieldAll(dequeue(t)) - select unit; - - async IAsyncEnumerable dequeue([EnumeratorCancellation] CancellationToken token) - { - try - { - while (true) - { - await wait.WaitOneAsync(50, token).ConfigureAwait(false); - if (complete.IsSet) yield break; - if (token.IsCancellationRequested) yield break; - while (queue.TryDequeue(out var item)) - { - yield return item; - } - } - } - finally - { - wait.Dispose(); - complete.Dispose(); - } - } - - Unit enqueue(OUT value) - { - queue?.Enqueue(value); - wait?.Set(); - return unit; - } - - Consumer receive() => - from x in Consumer.awaiting() - let _ = enqueue(x) - select unit; - - Unit countDown() - { - complete.Signal(); - return unit; - } - - K> runEffect(Producer p) => - (from _1 in p | receive() - let _2 = countDown() - select unit) - .ToEffect() - .RunEffect() - .ForkIO(); - } - - /// - /// Merge an array of queues into a single producer - /// - /// The merged producer completes when all component queues have completed - /// Sequence of queues to merge - /// Queues merged into a single producer - public static Producer merge(params Queue[] ms) - where M : Monad => - merge(ms.AsIterable().ToSeq().Map(m => (Producer)m)); - - /// - /// Merge an array of producers into a single producer - /// - /// The merged producer completes when all component producers have completed - /// Sequence of producers to merge - /// Merged producers - public static Producer merge(params Producer[] ms) - where M : Monad => - merge(toSeq(ms)); - - /// - /// Merge an array of producers into a single producer - /// - /// The merged producer completes when all component producers have completed - /// Sequence of producers to merge - /// Merged producers - public static Producer merge(params Proxy[] ms) - where M : Monad => - merge(toSeq(ms).Map(m => m.ToProducer())); - - /// - /// Merge a sequence of queues into a single producer - /// - /// The merged producer completes when all component queues have completed - /// Sequence of queues to merge - /// Queues merged into a single producer - public static Producer merge(Seq> ms) - where M : Monad => - merge(ms.Map(m => (Producer)m)); - - /// - /// Merge a sequence of producers into a single producer - /// - /// The merged producer completes when all component producers have completed - /// Sequence of producers to merge - /// Merged producers - public static Producer merge(Seq> ms) - where M : Monad => - merge(ms.Map(m => m.ToProducer())); -} diff --git a/Samples/PipesExamples/ProducerT/ProducerT.Extensions.cs b/LanguageExt.Pipes/ProducerT/ProducerT.Extensions.cs similarity index 98% rename from Samples/PipesExamples/ProducerT/ProducerT.Extensions.cs rename to LanguageExt.Pipes/ProducerT/ProducerT.Extensions.cs index bc84b4326..806d901f0 100644 --- a/Samples/PipesExamples/ProducerT/ProducerT.Extensions.cs +++ b/LanguageExt.Pipes/ProducerT/ProducerT.Extensions.cs @@ -1,6 +1,7 @@ +using System; using LanguageExt.Traits; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; public static class ProducerTExtensions { diff --git a/Samples/PipesExamples/ProducerT/ProducerT.Module.cs b/LanguageExt.Pipes/ProducerT/ProducerT.Module.cs similarity index 86% rename from Samples/PipesExamples/ProducerT/ProducerT.Module.cs rename to LanguageExt.Pipes/ProducerT/ProducerT.Module.cs index a3047d91e..972cc9a69 100644 --- a/Samples/PipesExamples/ProducerT/ProducerT.Module.cs +++ b/LanguageExt.Pipes/ProducerT/ProducerT.Module.cs @@ -1,11 +1,15 @@ +using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Runtime.CompilerServices; +using System.Threading.Tasks; using LanguageExt.Common; using LanguageExt.Pipes; +using LanguageExt.Pipes.Concurrent; using LanguageExt.Traits; using static LanguageExt.Prelude; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; /// /// `ProducerT` streaming producer monad-transformer @@ -301,72 +305,25 @@ public static ProducerT foldWhile( where M : Monad => PipeT.foldWhile(Time, Fold, Pred, Init, Item.Proxy); - /* /// /// Merge multiple producers /// - /// - /// - /// - /// - public static ProducerT merge(Seq> producers) + /// Producers to merge + /// Buffer settings + /// Stream value to produce + /// Lifted monad type + /// Merged producer + public static ProducerT merge( + Seq> producers, + Buffer? settings = null) where M : Monad { if (producers.Count == 0) return pure(default); - var complete = new CountdownEvent(producers.Count); - var wait = new AutoResetEvent(false); - var queue = new ConcurrentQueue(); - var effects = producers.Traverse(runEffect); - return from t in liftIO(cancelToken) - from _ in effects - from r in yieldAll(dequeue(t)) + return from mailbox in Pure(Mailbox.spawn(settings ?? Buffer.Unbounded)) + from forks in producers.Traverse(p => (p | mailbox.ToConsumer()).ForkIO()).As().Run() + from _ in mailbox.ToProducer() + from x in forks.Traverse(f => f.Cancel).As() select unit; - - async IAsyncEnumerable dequeue([EnumeratorCancellation] CancellationToken token) - { - try - { - while (true) - { - await wait.WaitOneAsync(50, token).ConfigureAwait(false); - if (complete.IsSet) yield break; - if (token.IsCancellationRequested) yield break; - while (queue.TryDequeue(out var item)) - { - yield return item; - } - } - } - finally - { - wait.Dispose(); - complete.Dispose(); - } - } - - Unit enqueue(OUT value) - { - queue?.Enqueue(value); - wait?.Set(); - return default; - } - - ConsumerT receive() => - ConsumerT.awaiting() - .Map(enqueue); - - Unit countDown() - { - complete.Signal(); - return default; - } - - K> runEffect(ProducerT p) => - (from _1 in p | receive() - let _2 = countDown() - select Unit.Default) - .Run() - .ForkIO(); - } */ + } } diff --git a/Samples/PipesExamples/ProducerT/ProducerT.Monad.cs b/LanguageExt.Pipes/ProducerT/ProducerT.Monad.cs similarity index 95% rename from Samples/PipesExamples/ProducerT/ProducerT.Monad.cs rename to LanguageExt.Pipes/ProducerT/ProducerT.Monad.cs index af84df26e..90eb7f0c2 100644 --- a/Samples/PipesExamples/ProducerT/ProducerT.Monad.cs +++ b/LanguageExt.Pipes/ProducerT/ProducerT.Monad.cs @@ -1,7 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Linq; using LanguageExt.Async.Linq; using LanguageExt.Traits; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; public class ProducerT : MonadT, M> where M : Monad diff --git a/Samples/PipesExamples/ProducerT/ProducerT.cs b/LanguageExt.Pipes/ProducerT/ProducerT.cs similarity index 99% rename from Samples/PipesExamples/ProducerT/ProducerT.cs rename to LanguageExt.Pipes/ProducerT/ProducerT.cs index 935d87976..5dfd5e77c 100644 --- a/Samples/PipesExamples/ProducerT/ProducerT.cs +++ b/LanguageExt.Pipes/ProducerT/ProducerT.cs @@ -1,7 +1,8 @@ +using System; using System.Diagnostics.Contracts; using LanguageExt.Traits; -namespace LanguageExt.Pipes2; +namespace LanguageExt.Pipes; /// /// `ProducerT` streaming producer monad-transformer instance diff --git a/LanguageExt.Pipes/Proxy.Monad.cs b/LanguageExt.Pipes/Proxy.Monad.cs deleted file mode 100644 index 42f8a2111..000000000 --- a/LanguageExt.Pipes/Proxy.Monad.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Collections.Generic; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -/// -/// Monad transformer trait implementation for `Proxy` -/// -public class Proxy : - MonadT, M> - where M : Monad -{ - static K, B> Monad>.Bind( - K, A> ma, - Func, B>> f) => - ma.As().Bind(x => f(x).As()); - - static K, B> Functor>.Map( - Func f, K, A> ma) => - ma.As().Map(f); - - static K, A> Applicative>.Pure(A value) => - Proxy.Pure(value); - - static K, B> Applicative>.Apply( - K, Func> mf, - K, A> ma) => - mf.As().Apply(ma.As()); - - static K, A> MonadT, M>.Lift(K ma) => - Proxy.lift(ma); - - static K, A> MonadIO>.LiftIO(IO ma) => - Proxy.lift(M.LiftIO(ma)); - - static K, IO> MonadIO>.ToIO(K, A> ma) => - ma.As().ToIO(); - - static K, A> Applicative>.Actions( - IEnumerable, A>> fas) => - fas.AsIterable().Map(fa => fa.ToIO()).Actions().Bind(io => io); -} diff --git a/LanguageExt.Pipes/Proxy.Prelude.cs b/LanguageExt.Pipes/Proxy.Prelude.cs deleted file mode 100644 index 06908854e..000000000 --- a/LanguageExt.Pipes/Proxy.Prelude.cs +++ /dev/null @@ -1,722 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.Contracts; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; -using LanguageExt.Traits; -using static LanguageExt.Prelude; - -namespace LanguageExt.Pipes; - -/// -/// The `static Proxy` class is the `Prelude` of the Pipes system. -/// -public static partial class Proxy -{ - internal const MethodImplOptions mops = MethodImplOptions.AggressiveInlining; - - /// - /// Wait for a value to flow from upstream (whilst in a `Pipe` or a `Consumer`) - /// - [Pure, MethodImpl(mops)] - public static Consumer awaiting() => - PureProxy.ConsumerAwait(); - - /// - /// Send a value flowing downstream (whilst in a `Producer` or a `Pipe`) - /// - [Pure, MethodImpl(mops)] - public static Producer yield(A value) => - PureProxy.ProducerYield(value); - - /// - /// Create a queue - /// - /// A `Queue` is a `Producer` with an `Enqueue`, and a `Done` to cancel the operation - [Pure, MethodImpl(mops)] - public static Queue Queue() - where M : Monad - { - var c = new Channel(); - var p = Producer.yieldAll(c); - return new Queue(p, c); - } - - /// - /// Create a `Producer` from an `IEnumerable`. This will automatically `yield` each value of the - /// `IEnumerable` down stream - /// - /// Items to `yield` - /// Type of the value to `yield` - /// `Producer` - [Pure, MethodImpl(mops)] - public static Producer yieldAll(K xs) where F : Foldable => - PureProxy.ProducerFold(xs); - - /// - /// Create a `Producer` from an `IAsyncEnumerable`. This will automatically `yield` each value of the - /// `IEnumerable` down stream - /// - /// Items to `yield` - /// Type of the value to `yield` - /// `Producer` - [Pure, MethodImpl(mops)] - public static Producer yieldAll(IAsyncEnumerable xs) => - yieldAll(xs.ToBlockingEnumerable().AsIterable()); - - /// - /// Create a `Producer` from an `IObservable`. This will automatically `yield` each value of the - /// `IObservable` down stream - /// - /// Items to `yield` - /// Type of the value to `yield` - /// `Producer` - [Pure, MethodImpl(mops)] - public static Producer yieldAll(IObservable xs) => - from t in PureProxy.ProducerLiftIO(IO.token) - from r in yieldAll(xs.ToAsyncEnumerable(t)) - select r; - - // TODO: IMPLEMENT TAIL CALLS - [Pure, MethodImpl(mops)] - public static Producer tail(Producer ma) - where M : Monad => - ma; - - // TODO: IMPLEMENT TAIL CALLS - [Pure, MethodImpl(mops)] - public static Consumer tail(Consumer ma) - where M : Monad => - ma; - - // TODO: IMPLEMENT TAIL CALLS - [Pure, MethodImpl(mops)] - public static Pipe tail(Pipe ma) - where M : Monad => - ma; - - /// - /// Repeat the `Producer` indefinitely - /// - [Pure, MethodImpl(mops)] - public static Producer repeat(Producer ma) - where M : Monad => - new IteratorFoldable( - Naturals.AsIterable().Map(_ => unit), - _ => ma.ToProxy().Map(_ => unit), - () => Producer.Pure(unit)) - .ToProducer(); - - /// - /// Repeat the `Consumer` indefinitely - /// - [Pure, MethodImpl(mops)] - public static Consumer repeat(Consumer ma) - where M : Monad => - new IteratorFoldable( - Naturals.AsIterable().Map(_ => unit), - _ => ma.ToProxy().Map(_ => unit), - () => Consumer.Pure(unit)) - .ToConsumer(); - - /// - /// Repeat the `Pipe` indefinitely - /// - [Pure, MethodImpl(mops)] - public static Pipe repeat(Pipe ma) - where M : Monad => - new IteratorFoldable( - Naturals.AsIterable().Map(_ => unit), - _ => ma.ToProxy().Map(_ => unit), - () => Pipe.Pure(unit)) - .ToPipe(); - - /// - /// Lift a monad into the `Proxy` monad transformer - /// - [Pure, MethodImpl(mops)] - public static Proxy lift(K ma) - where M : Monad => - new ProxyM(M.Map(Pure, ma)); - - /// - /// Lift an IO monad into the `Proxy` monad transformer - /// - [Pure, MethodImpl(mops)] - public static Proxy liftIO(K ma) - where M : Monad => - lift(M.LiftIO(ma)); - - internal static Unit dispose(A d) where A : IDisposable - { - d.Dispose(); - return default; - } - - internal static Unit anyDispose(A x) - { - if (x is IDisposable d) - { - d.Dispose(); - } - - return default; - } - - /// - /// The identity `Pipe`, simply replicates its upstream value and propagates it downstream - /// - [Pure, MethodImpl(mops)] - public static Pipe cat() - where M : Monad => - pull(default).ToPipe(); - - /// - /// Forward requests followed by responses - /// - /// pull = request | respond | pull - /// - /// - /// - /// `pull` is the identity of the pull category. - /// - [Pure, MethodImpl(mops)] - public static Proxy pull(UOut a1) - where M : Monad => - new Request( - a1, - a => new Respond( - a, - pull)); - - /// - /// `push = respond | request | push` - /// - /// - /// `push` is the identity of the push category. - /// - [Pure, MethodImpl(mops)] - public static Proxy push(UIn a) - where M : Monad => - new Respond( - a, - a1 => new Request( - a1, - push)); - - /// - /// Send a value of type `DOut` downstream and block waiting for a reply of type `DIn` - /// - /// - /// `respond` is the identity of the respond category. - /// - [Pure, MethodImpl(mops)] - public static Proxy respond(DOut value) - where M : Monad => - new Respond(value, r => new Pure(r)); - - /// - /// Send a value of type `UOut` upstream and block waiting for a reply of type `UIn` - /// - /// - /// `request` is the identity of the request category. - /// - [Pure, MethodImpl(mops)] - public static Proxy request(UOut value) - where M : Monad => - new Request(value, r => new Pure(r)); - - - /// - /// `reflect` transforms each streaming category into its dual: - /// - /// The request category is the dual of the respond category - /// - /// reflect . respond = request - /// reflect . (f | g) = reflect . f | reflect . g - /// reflect . request = respond - /// reflect . (f | g) = reflect . f | reflect . g - /// - /// The pull category is the dual of the push category - /// - /// reflect . push = pull - /// reflect . (f | g) = reflect . f | reflect . g - /// reflect . pull = push - /// reflect . (f | g) = reflect . f | reflect . g - /// - /// - [Pure, MethodImpl(mops)] - public static Proxy reflect( - Proxy p) - where M : Monad => - p.Reflect(); - - /// - /// `p.ForEach(body)` loops over the `Producer p` replacing each `yield` with `body` - /// - /// Producer b r -> (b -> Producer c ()) -> Producer c r - /// - [Pure, MethodImpl(mops)] - public static Producer ForEach( - this Producer p, - Func> body) - where M : Monad => - p.For(body).ToProducer(); - - /// - /// `p.ForEach(body)` loops over `Producer p` replacing each `yield` with `body` - /// - /// Producer b r -> (b -> Effect ()) -> Effect r - /// - [Pure, MethodImpl(mops)] - public static Effect ForEach( - this Producer p, - Func> fb) - where M : Monad => - p.For(fb).ToEffect(); - - /// - /// `p.ForEach(body)` loops over `Pipe p` replacing each `yield` with `body` - /// - /// Pipe x b r -> (b -> Consumer x ()) -> Consumer x r - /// - [Pure, MethodImpl(mops)] - public static Consumer ForEach( - this Pipe p0, - Func> fb) - where M : Monad => - p0.For(fb).ToConsumer(); - - /// - /// `p.ForEach(body)` loops over `Pipe p` replacing each `yield` with `body` - /// - /// Pipe x b r -> (b -> Pipe x c ()) -> Pipe x c r - /// - [Pure, MethodImpl(mops)] - public static Pipe ForEach( - this Pipe p0, - Func> fb) - where M : Monad => - p0.For(fb).ToPipe(); - - /// - /// `compose(draw, p)` loops over `p` replacing each `await` with `draw` - /// - [Pure, MethodImpl(mops)] - public static Proxy compose( - Proxy p1, - Proxy p2) - where M : Monad => - compose(_ => p1, p2); - - /// - /// `compose(draw, p)` loops over `p` replacing each `await` with `draw` - /// - /// Effect b -> Consumer b c -> Effect c - /// - [Pure, MethodImpl(mops)] - public static Effect compose( - Effect p1, - Consumer p2) - where M : Monad => - compose(_ => p1, p2).ToEffect(); - - /// - /// `compose(draw, p)` loops over `p` replacing each `await` with `draw` - /// - /// Consumer a b -> Consumer b c -> Consumer a c - /// - [Pure, MethodImpl(mops)] - public static Consumer compose( - Consumer p1, - Consumer p2) - where M : Monad => - compose(_ => p1, p2).ToConsumer(); - - /// - /// `compose(draw, p)` loops over `p` replacing each `await` with `draw` - /// - /// Producer y b -> Pipe b y m c -> Producer y c - /// - [Pure, MethodImpl(mops)] - public static Producer compose( - Producer p1, - Pipe p2) - where M : Monad => - compose(_ => p1, p2).ToProducer(); - - /// - /// `compose(draw, p)` loops over `p` replacing each `await` with `draw` - /// - /// Pipe a y b -> Pipe b y c -> Pipe a y c - /// - [Pure, MethodImpl(mops)] - public static Pipe compose( - Pipe p1, - Pipe p2) - where M : Monad => - compose(_ => p1, p2).ToPipe(); - - // fixAwaitDual - [Pure, MethodImpl(mops)] - public static Proxy compose( - Proxy p2, - Proxy p1) - where M : Monad => - compose(p1, p2); - - /// - /// Replaces each `request` or `respond` in `p0` with `fb1`. - /// - [Pure, MethodImpl(mops)] - public static Proxy compose( - Func> fb1, - Proxy p0) - where M : Monad => - p0.ReplaceRequest(fb1); - - /// - /// `compose(p, f)` pairs each `respond` in `p` with a `request` in `f`. - /// - [Pure, MethodImpl(mops)] - public static Proxy compose( - Proxy p, - Func> fb) - where M : Monad => - p.PairEachRespondWithRequest(fb); - - /// - /// `compose(f, p)` pairs each `request` in `p` with a `respond` in `f` - /// - [Pure, MethodImpl(mops)] - public static Proxy compose( - Func> fb1, - Proxy p) - where M : Monad => - p.PairEachRequestWithRespond(fb1); - - /// - /// Pipe composition - /// - [Pure, MethodImpl(mops)] - public static Proxy compose( - Proxy p1, - Proxy p2) - where M : Monad => - compose(_ => p1, p2); - - /// - /// Pipe composition - /// - /// Producer b r -> Consumer b r -> Effect m r - /// - /// - [Pure, MethodImpl(mops)] - public static Effect compose( - Producer p1, - Consumer p2) - where M : Monad => - compose(p1.ToProxy(), p2).ToEffect(); - - /// - /// Pipe composition - /// - /// Producer b r -> Pipe b c r -> Producer c r - /// - /// - [Pure, MethodImpl(mops)] - public static Producer compose( - Producer p1, - Pipe p2) - where M : Monad => - compose(p1.ToProxy(), p2).ToProducer(); - - /// - /// Pipe composition - /// - /// Pipe a b r -> Consumer b r -> Consumer a r - /// - /// - [Pure, MethodImpl(mops)] - public static Consumer compose( - Pipe p1, - Consumer p2) - where M : Monad => - compose(p1.ToProxy(), p2).ToConsumer(); - - /// - /// Pipe composition - /// - /// Pipe a b r -> Pipe b c r -> Pipe a c r - /// - /// - [Pure, MethodImpl(mops)] - public static Pipe compose( - Pipe p1, - Pipe p2) - where M : Monad => - compose(p1.ToProxy(), p2).ToPipe(); - - /// - /// Compose two unfolds, creating a new unfold - /// - /// - /// This is the composition operator of the respond category. - /// - [Pure, MethodImpl(mops)] - public static Func> compose( - Func> fa, - Func> fb) - where M : Monad => - a => compose(fa(a), fb); - - /// - /// Compose two unfolds, creating a new unfold - /// - /// - /// This is the composition operator of the respond category. - /// - [Pure, MethodImpl(mops)] - public static Func> Then( - this Func> fa, - Func> fb) - where M : Monad => - a => compose(fa(a), fb); - - /// - /// `compose(p, f)` replaces each `respond` in `p` with `f`. - /// - [Pure, MethodImpl(mops)] - public static Proxy compose( - Proxy p0, - Func> fb) - where M : Monad => - p0.ReplaceRespond(fb); - - /// - /// `compose(p, f)` replaces each `respond` in `p` with `f`. - /// - [Pure, MethodImpl(mops)] - public static Proxy Then( - this Proxy p0, - Func> fb) - where M : Monad => - compose(p0, fb); - - - /// - /// Compose two folds, creating a new fold - /// - /// (f | g) x = f | g x - /// - /// | is the composition operator of the request category. - /// - [Pure, MethodImpl(mops)] - public static Func> compose( - Func> fb1, - Func> fc1) - where M : Monad => - c1 => compose(fb1, fc1(c1)); - - /// - /// - /// observe(lift (Pure(r))) = observe(Pure(r)) - /// observe(lift (m.Bind(f))) = observe(lift(m.Bind(x => lift(f(x))))) - /// - /// This correctness comes at a small cost to performance, so use this function sparingly. - /// This function is a convenience for low-level pipes implementers. You do not need to - /// use observe if you stick to the safe API. - /// - [Pure, MethodImpl(mops)] - public static Proxy observe( - Proxy p0) - where M : Monad => - p0.Observe(); - - /// - /// `Absurd` function - /// - /// `Void` is supposed to represent `void`, nothing can be constructed from `void` and - /// so this method just throws `ApplicationException("closed")` - [Pure, MethodImpl(mops)] - public static A closed(Void value) => - throw new ApplicationException("closed"); - - /// - /// Applicative apply - /// - [Pure, MethodImpl(mops)] - public static Proxy apply( - Proxy> pf, - Proxy px) where M : Monad - { - return Go(pf); - - Proxy Go(Proxy> p) => - p.ToProxy() switch - { - Request> (var a1, var fa) => new Request(a1, a => Go(fa(a))), - Respond> (var b, var fb1) => new Respond(b, b1 => Go(fb1(b1))), - ProxyM> (var m) => new ProxyM(M.Map(Go, m)), - Pure> (var f) => px.Map(f), - _ => throw new NotSupportedException() - }; - } - - /// - /// Applicative apply - /// - [Pure, MethodImpl(mops)] - public static Proxy Apply( - this Proxy> pf, - Proxy px) - where M : Monad => - apply(pf, px); - - /// - /// Applicative action - /// - [Pure, MethodImpl(mops)] - public static Proxy Action( - this Proxy l, - Proxy r) - where M : Monad => - l.Action(r); - - /// - /// Monad return / pure - /// - [Pure, MethodImpl(mops)] - public static Proxy Pure(R value) - where M : Monad => - new Pure(value); - - /// - /// Creates a non-yielding producer that returns the result of the effects - /// - [Pure, MethodImpl(mops)] - public static K collect(Effect ma, Effect mb) - where M : Monad => - fun((A x, B y) => (x, y)).Map(ma.RunEffect()).Apply(mb.RunEffect()); - - /// - /// Creates a non-yielding producer that returns the result of the effects - /// - [Pure, MethodImpl(mops)] - public static K collect(Effect ma, Effect mb, Effect mc) - where M : Monad => - fun((A x, B y, C z) => (x, y, z)).Map(ma.RunEffect()).Apply(mb.RunEffect()).Apply(mc.RunEffect()); - - /// - /// Creates a non-yielding producer that returns the result of the effects - /// - [Pure, MethodImpl(mops)] - public static Producer<(A, B), M, Unit> yield(Effect ma, Effect mb) - where M : Monad => - from r in collect(ma, mb) - from _ in yield(r) - select unit; - - /// - /// Creates a non-yielding producer that returns the result of the effects - /// - [Pure, MethodImpl(mops)] - public static Producer<(A, B, C), M, Unit> yield(Effect ma, Effect mb, Effect mc) - where M : Monad => - from r in collect(ma, mb, mc) - from _ in yield(r) - select unit; - - /// - /// Only forwards values that satisfy the predicate. - /// - public static Pipe filter(Func f) => - from x in awaiting() - from r in f(x) ? yield(x) : Prelude.Pure(unit) - select r; - - /// - /// Map the output of the pipe (not the bound value as is usual with Map) - /// - public static Pipe map(Func f) => - from x in awaiting() - from r in yield(f(x)) - select r; - - /// - /// Folds values coming down-stream, when the predicate returns false the folded value is yielded - /// - /// Initial state - /// Fold operation - /// Predicate - /// A pipe that folds - [Pure, MethodImpl(mops)] - public static Pipe foldWhile(OUT Initial, Func Fold, Func State) => - foldUntil(Initial, Fold, x => !State(x)); - - /// - /// Folds values coming down-stream, when the predicate returns true the folded value is yielded - /// - /// Initial state - /// Fold operation - /// Predicate - /// A pipe that folds - public static Pipe foldUntil(OUT Initial, Func Fold, Func State) - { - var state = Initial; - return awaiting() - .Bind(x => - { - state = Fold(state, x); - if (State(state)) - { - var nstate = state; - state = Initial; - return yield(nstate); - } - else - { - return Prelude.Pure(unit); - } - }); - } - - /// - /// Folds values coming down-stream, when the predicate returns false the folded value is yielded - /// - /// Initial state - /// Fold operation - /// Predicate - /// A pipe that folds - [Pure, MethodImpl(mops)] - public static Pipe foldWhile(OUT Initial, Func Fold, Func Value) => - foldUntil(Initial, Fold, x => !Value(x)); - - /// - /// Folds values coming down-stream, when the predicate returns true the folded value is yielded - /// - /// Initial state - /// Fold operation - /// Predicate - /// A pipe that folds - public static Pipe foldUntil(OUT Initial, Func Fold, Func Value) - { - var state = Initial; - return awaiting() - .Bind(x => - { - if (Value(x)) - { - var nstate = state; - state = Initial; - return yield(nstate); - } - else - { - state = Fold(state, x); - return Prelude.Pure(unit); - } - }); - } -} diff --git a/LanguageExt.Pipes/Proxy.Prelude.mapapply.cs b/LanguageExt.Pipes/Proxy.Prelude.mapapply.cs deleted file mode 100644 index 814bd43f3..000000000 --- a/LanguageExt.Pipes/Proxy.Prelude.mapapply.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using LanguageExt.Traits; -using LanguageExt.Pipes; - -namespace LanguageExt.Pipes; - -public static partial class Proxy -{ - /// - /// Functor map operation - /// - /// - /// Unwraps the value within the functor, passes it to the map function `f` provided, and - /// then takes the mapped value and wraps it back up into a new functor. - /// - /// Functor to map - /// Mapping function - /// Mapped functor - public static Proxy map( - Func f, - K, A> ma) - where M : Monad => - Functor.map(f, ma).As(); - - /// - /// Applicative action: runs the first applicative, ignores the result, and returns the second applicative - /// - public static Proxy action( - K, A> ma, - K, B> mb) - where M : Monad => - Applicative.action(ma, mb).As(); - - /// - /// Applicative functor apply operation - /// - /// - /// Unwraps the value within the `ma` applicative-functor, passes it to the unwrapped function(s) within `mf`, and - /// then takes the resulting value and wraps it back up into a new applicative-functor. - /// - /// Value(s) applicative functor - /// Mapping function(s) - /// Mapped applicative functor - public static Proxy apply( - K, Func> mf, - K, A> ma) - where M : Monad => - Applicative.apply(mf, ma).As(); -} diff --git a/LanguageExt.Pipes/Proxy.ProxyM.cs b/LanguageExt.Pipes/Proxy.ProxyM.cs deleted file mode 100644 index 516626586..000000000 --- a/LanguageExt.Pipes/Proxy.ProxyM.cs +++ /dev/null @@ -1,160 +0,0 @@ -using System; -using System.Diagnostics.Contracts; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -/// -/// One of the algebraic cases of the `Proxy` type. This type lifts a `Transducer` computation into the -/// `Proxy` monad-transformer. This is how the `Proxy` system can cause real-world effects. -/// -/// Upstream out type -/// Upstream in type -/// Downstream in type -/// Downstream uut type -/// The monadic bound variable - it doesn't flow up or down stream, it works just like any bound -/// monadic variable. If the effect represented by the `Proxy` ends, then this will be the result value. -/// -/// When composing `Proxy` sub-types (like `Producer`, `Pipe`, `Consumer`, etc.) -internal record ProxyM(K> Value) : - Proxy - where M : Monad -{ - /// - /// When working with sub-types, like `Producer`, calling this will effectively cast the sub-type to the base. - /// - /// A general `Proxy` type from a more specialised type - [Pure] - public override Proxy ToProxy() => - this; - - /// - /// Monadic bind operation, for chaining `Proxy` computations together - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public override Proxy Bind(Func> f) => - new ProxyM(M.Map(p => p.Bind(f), Value)); - - /// - /// Lifts a pure function into the `Proxy` domain, causing it to map the bound value within - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy Map(Func f) => - new ProxyM(M.Map(p => p.Map(f), Value)); - - /// - /// Map the lifted monad - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy MapM(Func, K> f) => - new ProxyM(M.Map(p => p.MapM(f), Value)); - - /// - /// Extract the lifted IO monad (if there is one) - /// - /// The map function - /// A new `Proxy` that represents the innermost IO monad, if it exists. - /// `Errors.UnliftIONotSupported` if there's no IO monad in the stack - [Pure] - public override Proxy> ToIO() => - new ProxyM>(M.Map(p => p.ToIO(), Value)); - - /// - /// `For(body)` loops over the `Proxy p` replacing each `yield` with `body` - /// - /// Any `yield` found in the `Proxy` will be replaced with this function. It will be composed so - /// that the value yielded will be passed to the argument of the function. That returns a `Proxy` to continue the - /// processing of the computation - /// - [Pure] - public override Proxy For(Func> body) => - ReplaceRespond(body); - - /// - /// Applicative action - /// - /// Invokes this `Proxy`, then the `Proxy r` - /// - /// `Proxy` to run after this one - [Pure] - public override Proxy Action(Proxy r) => - new ProxyM(M.Map(p => p.Action(r), Value)); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - /// - /// (f +>> p) pairs each 'request' in `this` with a 'respond' in `fb1`. - /// - [Pure] - public override Proxy PairEachRequestWithRespond( - Func> fb1) => - new ProxyM(M.Map(p1 => p1.PairEachRequestWithRespond(fb1), Value)); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy ReplaceRequest( - Func> lhs) => - new ProxyM(M.Map(p => p.ReplaceRequest(lhs), Value)); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy PairEachRespondWithRequest( - Func> rhs) => - new ProxyM(M.Map(p1 => p1.PairEachRespondWithRequest(rhs), Value)); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy ReplaceRespond( - Func> rhs) => - new ProxyM(M.Map(p => p.ReplaceRespond(rhs), Value)); - - /// - /// Reverse the arrows of the `Proxy` to find its dual. - /// - /// The dual of `this1 - [Pure] - public override Proxy Reflect() => - new ProxyM(M.Map(p => p.Reflect(), Value)); - - /// - /// - /// Observe(lift (Pure(r))) = Observe(Pure(r)) - /// Observe(lift (m.Bind(f))) = Observe(lift(m.Bind(x => lift(f(x))))) - /// - /// This correctness comes at a small cost to performance, so use this function sparingly. - /// This function is a convenience for low-level pipes implementers. You do not need to - /// use observe if you stick to the safe API. - /// - [Pure] - public override Proxy Observe() => - new ProxyM(M.Map(p => p.Observe(), Value)); - - [Pure] - public void Deconstruct(out K> value) => - value = Value; - - [Pure] - public override string ToString() => - "proxyM"; -} diff --git a/LanguageExt.Pipes/Proxy.Pure.cs b/LanguageExt.Pipes/Proxy.Pure.cs deleted file mode 100644 index 2571a320f..000000000 --- a/LanguageExt.Pipes/Proxy.Pure.cs +++ /dev/null @@ -1,159 +0,0 @@ -using System; -using System.Diagnostics.Contracts; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -/// -/// One of the algebraic cases of the `Proxy` type. This type represents a pure value. It can be thought of as the -/// terminating value of the computation, as there's not continuation attached to this case. -/// -/// Upstream out type -/// Upstream in type -/// Downstream in type -/// Downstream uut type -/// The monadic bound variable - it doesn't flow up or down stream, it works just like any bound -/// monadic variable. If the effect represented by the `Proxy` ends, then this will be the result value. -/// -/// When composing `Proxy` subtypes (like `Producer`, `Pipe`, `Consumer`, etc.) -public record Pure(A Value) : Proxy - where M : Monad -{ - /// - /// When working with subtypes, like `Producer`, calling this will effectively cast the subtype to the base. - /// - /// A general `Proxy` type from a more specialised type - [Pure] - public override Proxy ToProxy() => this; - - /// - /// Monadic bind operation, for chaining `Proxy` computations together - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public override Proxy Bind(Func> f) => - f(Value); - - /// - /// Lifts a pure function into the `Proxy` domain, causing it to map the bound value within - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy Map(Func f) => - new Pure(f(Value)); - - /// - /// Map the lifted monad - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy MapM(Func, K> f) => - Proxy.lift(f(M.Pure(Value))); - - /// - /// Extract the lifted IO monad (if there is one) - /// - /// The map function - /// A new `Proxy` that represents the innermost IO monad, if it exists. - /// `Errors.UnliftIONotSupported` if there's no IO monad in the stack - [Pure] - public override Proxy> ToIO() => - new Pure>(IO.pure(Value)); - - /// - /// `For(body)` loops over the `Proxy p` replacing each `yield` with `body` - /// - /// Any `yield` found in the `Proxy` will be replaced with this function. It will be composed so - /// that the value yielded will be passed to the argument of the function. That returns a `Proxy` to continue the - /// processing of the computation - /// - [Pure] - public override Proxy For(Func> body) => - ReplaceRespond(body); - - /// - /// Applicative action - /// - /// Invokes this `Proxy`, then the `Proxy r` - /// - /// `Proxy` to run after this one - [Pure] - public override Proxy Action(Proxy r) => - r; - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - /// - /// (f +>> p) pairs each 'request' in `this` with a 'respond' in `lhs`. - /// - [Pure] - public override Proxy PairEachRequestWithRespond( - Func> _) => - new Pure(Value); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy ReplaceRequest( - Func> _) => - new Pure(Value).ToProxy(); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy PairEachRespondWithRequest( - Func> _) => - new Pure(Value); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy ReplaceRespond( - Func> _) => - new Pure(Value); - - /// - /// Reverse the arrows of the `Proxy` to find its dual. - /// - /// The dual of `this1 - [Pure] - public override Proxy Reflect() => - new Pure(Value); - - /// - /// - /// Observe(lift (Pure(r))) = Observe(Pure(r)) - /// Observe(lift (m.Bind(f))) = Observe(lift(m.Bind(x => lift(f(x))))) - /// - /// This correctness comes at a small cost to performance, so use this function sparingly. - /// This function is a convenience for low-level pipes implementers. You do not need to - /// use observe if you stick to the safe API. - /// - [Pure] - public override Proxy Observe() => - new ProxyM(M.Pure(Proxy.Pure(Value))); - - - [Pure] - public void Deconstruct(out A value) => - value = Value; - - [Pure] - public override string ToString() => - "pure"; -} diff --git a/LanguageExt.Pipes/Proxy.cs b/LanguageExt.Pipes/Proxy.cs deleted file mode 100644 index 12c4bd016..000000000 --- a/LanguageExt.Pipes/Proxy.cs +++ /dev/null @@ -1,181 +0,0 @@ -using System; -using System.Diagnostics.Contracts; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -/// -/// A `Proxy` is a monad transformer that receives and sends information on both -/// an upstream and downstream interface. It is the base type for all of the key -/// other important types in the Pipes ecosystem, like `Producer`, `Consumer`, -/// `Pipe`, etc. -/// -/// Diagrammatically, you can think of a `Proxy` as having the following shape: -/// -/// Upstream | Downstream -/// +---------+ -/// | | -/// UOut ◄-- ◄-- DIn -/// | | -/// UIn --► --► DOut -/// | | | -/// +----|----+ -/// A -/// -/// You can connect proxies together in five different ways: -/// -/// 1. Connect pull-based streams -/// 2. Connect push-based streams -/// 3. Chain folds -/// 4. Chain unfolds -/// 5. Sequence proxies -/// -/// The type variables signify: -/// -/// * `UOut` and `Uin` - The upstream interface, where `UOut` go out and `UIn` come in -/// * `DOut` and `DIn` - The downstream interface, where `DOut` go out and `DIn` come in -/// * `RT` - The runtime of the transformed effect monad -/// * `A` - The return value -/// -/// Upstream out type -/// Upstream in type -/// Downstream in type -/// Downstream uut type -/// The monadic bound variable - it doesn't flow up or down stream, it works just like any bound -/// monadic variable. If the effect represented by the `Proxy` ends, then this will be the result value. -/// -/// When composing `Proxy` subtypes (like `Producer`, `Pipe`, `Consumer`, etc.) -public abstract record Proxy : K, A> - where M : Monad -{ - /// - /// When working with subtypes, like `Producer`, calling this will effectively cast the sub-type to the base. - /// - /// A general `Proxy` type from a more specialised type - public abstract Proxy ToProxy(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - public abstract Proxy Bind(Func> f); - - /// - /// Lifts a pure function into the `Proxy` domain, causing it to map the bound value within - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - public abstract Proxy Map(Func f); - - /// - /// Map the lifted monad - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - public abstract Proxy MapM(Func, K> f); - - /// - /// Extract the lifted IO monad (if there is one) - /// - /// The map function - /// A new `Proxy` that represents the innermost IO monad, if it exists. - /// `Errors.UnliftIONotSupported` if there's no IO monad in the stack - public abstract Proxy> ToIO(); - - /// - /// `For(body)` loops over the `Proxy p` replacing each `yield` with `body` - /// - /// Any `yield` found in the `Proxy` will be replaced with this function. It will be composed so - /// that the value yielded will be passed to the argument of the function. That returns a `Proxy` to continue the - /// processing of the computation - /// A new `Proxy` that represents the composition of this `Proxy` and the function provided - public abstract Proxy For(Func> body); - - /// - /// Applicative action - /// - /// Invokes this `Proxy`, then the `Proxy r` - /// - /// `Proxy` to run after this one - public abstract Proxy Action(Proxy r); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - /// - /// (f +>> p) pairs each 'request' in `this` with a 'respond' in `lhs`. - /// - public abstract Proxy PairEachRequestWithRespond( - Func> lhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - public abstract Proxy ReplaceRequest( - Func> lhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - public abstract Proxy PairEachRespondWithRequest( - Func> rhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - public abstract Proxy ReplaceRespond( - Func> rhs); - - /// - /// Reverse the arrows of the `Proxy` to find its dual. - /// - /// The dual of `this` - public abstract Proxy Reflect(); - - /// - /// - /// Observe(lift (Pure(r))) = Observe(Pure(r)) - /// Observe(lift (m.Bind(f))) = Observe(lift(m.Bind(x => lift(f(x))))) - /// - /// This correctness comes at a small cost to performance, so use this function sparingly. - /// This function is a convenience for low-level pipes implementers. You do not need to - /// use observe if you stick to the safe API. - /// - public abstract Proxy Observe(); - - /// - /// Monadic bind operation, followed by a mapping projection, enables usage in LINQ expressions - /// - /// The bind function - /// The mapping projection function - /// The new bound value type - /// The result of the bind and mapping composition - [Pure] - public Proxy SelectMany( - Func> f, - Func project) => - Bind(a => f(a).Map(b => project(a, b))); - - /// - /// Functor map operation, enables usage in LINQ expressions - /// - /// Map function - /// The new bound value type - /// The result of the lifted function applied to the bound value - [Pure] - public Proxy Select(Func f) => - Map(f); - - [Pure] - public override string ToString() => - "proxy"; -} diff --git a/LanguageExt.Pipes/PureProxy/Consumer.cs b/LanguageExt.Pipes/PureProxy/Consumer.cs deleted file mode 100644 index a2b719fe2..000000000 --- a/LanguageExt.Pipes/PureProxy/Consumer.cs +++ /dev/null @@ -1,219 +0,0 @@ -// -// This file contains a number of micro-free-monads that allow for creation of pure producers, consumers, and pipes. -// They're used to facilitate the building of Proxy derived types without the need for typing the generic arguments endlessly -// The Haskell original could auto-infer the generic parameter types, the system here tries to replicate manually what -// Haskell can do automatically. Hence why there are so many implementations of SelectMany! -// - -using System; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -public abstract class Consumer -{ - public abstract Consumer Select(Func f); - - public abstract Consumer Bind(Func> f); - public abstract Consumer Bind(Func> f) where M : Monad; - public abstract Pipe Bind(Func> f); - - public Consumer Bind(Func> f) => - Map(x => f(x).Value); - - public Consumer Bind(Func> f) => - Bind(x => new Consumer.Fail(f(x).Value)); - - public Consumer Bind(Func> f) - where M : Monad => - Interpret().Bind(f); - - public Consumer Bind(Func> f) => - Bind(x => PureProxy.ConsumerLiftIO(f(x))); - - public abstract Consumer Interpret() - where M : Monad; - - public abstract Pipe ToPipe(); - - public Consumer Map(Func f) => Select(f); - - public Consumer SelectMany(Func> f, Func project) => - Map(x => project(x, f(x).Value)); - - public Consumer SelectMany(Func> f, Func project) => - Bind(f); - - public Consumer SelectMany(Func> f, Func project) => - Bind(x => f(x).Map(y => project(x, y))); - - public Consumer SelectMany(Func> f, Func project) - where M : Monad => - Bind(a => M.Map(b => project(a, b), f(a))); - - public Consumer SelectMany(Func> f, Func project) => - Bind(a => f(a).Select(b => project(a, b))); - - public Consumer SelectMany(Func> f, Func project) - where M : Monad => - Bind(a => f(a).Select(b => project(a, b))); - - public Pipe SelectMany(Func> f, Func project) => - Bind(a => f(a).Select(b => project(a, b))); - - public Consumer SelectMany(Func> bind, Func project ) => - Map(a => bind(a) switch - { - { Flag: true } => project(a, default), - var g => g.OnFalse().Throw() - }); - - public static implicit operator Consumer(Pure ma) => - new Pure(ma.Value); - - public static Consumer operator &( - Consumer lhs, - Consumer rhs) => - lhs.Bind(_ => rhs); - - public class Pure(A Value) : Consumer - { - public override Consumer Select(Func f) => - new Consumer.Pure(f(Value)); - - public override Consumer Bind(Func> f) => - f(Value); - - public override Consumer Bind(Func> f) => - f(Value); - - public override Pipe Bind(Func> f) => - f(Value).ToPipe(); - - public override Consumer Interpret() => - Consumer.Pure(Value); - - public override Pipe ToPipe() => - new Pipe.Pure(Value); - } - - public class Fail(Error Error) : Consumer - { - public override Consumer Select(Func _) => - new Consumer.Fail(Error); - - public override Consumer Bind(Func> _) => - new Consumer.Fail(Error); - - public override Consumer Bind(Func> f) => - PureProxy.ConsumerLift(Error.Throw).Bind(f); - - public override Pipe Bind(Func> _) => - new Pipe.Fail(Error); - - public override Consumer Interpret() => - PureProxy.ConsumerLift(Error.Throw); - - public override Pipe ToPipe() => - new Pipe.Fail(Error); - } - - public class Lift(Func Function, Func> Next) : Consumer - { - public override Consumer Select(Func f) => - new Consumer.Lift(Function, x => Next(x).Select(f)); - - public override Consumer Bind(Func> f) => - new Consumer.Lift(Function, x => Next(x).Bind(f)); - - public override Consumer Bind(Func> f) => - Consumer.lift(M.Pure(Function())).Bind(x => Next(x).Bind(f)).ToConsumer(); - - public override Pipe Bind(Func> f) => - new Pipe.Lift(Function, x => Next(x).Bind(f)); - - public override Consumer Interpret() => - Consumer.lift(M.Pure(Function())).Bind(x => Next(x).Interpret()); - - public override Pipe ToPipe() => - new Pipe.Lift(Function, x => Next(x).ToPipe()); - } - - public class LiftIO(IO Effect, Func> Next) : Consumer - { - public override Consumer Select(Func f) => - new Consumer.LiftIO(Effect, x => Next(x).Select(f)); - - public override Consumer Bind(Func> f) => - new Consumer.LiftIO(Effect, x => Next(x).Bind(f)); - - public override Consumer Bind(Func> f) => - Consumer.lift(M.LiftIO(Effect)).Bind(x => Next(x).Bind(f)).ToConsumer(); - - public override Pipe Bind(Func> f) => - new Pipe.LiftIO(Effect, x => Next(x).Bind(f)); - - public override Consumer Interpret() => - Consumer.lift(M.LiftIO(Effect)).Bind(x => Next(x).Interpret()); - - public override Pipe ToPipe() => - new Pipe.LiftIO(Effect, x => Next(x).ToPipe()); - } - - public class Await : Consumer - { - public readonly Func> Next; - public Await(Func> next) => - Next = next; - - public override Consumer Select(Func f) => - new Consumer.Await(x => Next(x).Select(f)); - - public override Consumer Bind(Func> f) => - new Consumer.Await(x => Next(x).Bind(f)); - - public override Consumer Bind(Func> f) => - Interpret().Bind(f).ToConsumer(); - - public override Pipe Bind(Func> f) => - new Pipe.Await(x => Next(x).Bind(f)); - - public override Consumer Interpret() => - Consumer.awaiting().Bind(x => Next(x).Interpret()).ToConsumer(); - - public override Pipe ToPipe() => - new Pipe.Await(x => Next(x).ToPipe()); - } - - public class Fold(K Items, Func> Yield, Func> Next) : Consumer - where F : Foldable - { - public override Consumer Select(Func f) => - new Consumer.Fold(Items, Yield, () => Next().Select(f)); - - public override Consumer Bind(Func> f) => - new Consumer.Fold(Items, Yield, () => Next().Bind(f)); - - public override Consumer Bind(Func> f) => - new(new IteratorFoldable( - Items, - x => Yield(x).Interpret(), - () => Next().Bind(f))); - - public override Pipe Bind(Func> f) => - new Pipe.Fold( - Items, - x => Yield(x).ToPipe(), - () => Next().Bind(f)); - - public override Consumer Interpret() => - new(new IteratorFoldable( - Items, - x => Yield(x).Interpret(), - () => Next().Interpret())); - - public override Pipe ToPipe() => - new Pipe.Fold(Items, x => Yield(x).ToPipe(), () => Next().ToPipe()); - } -} diff --git a/LanguageExt.Pipes/PureProxy/Pipe.cs b/LanguageExt.Pipes/PureProxy/Pipe.cs deleted file mode 100644 index 36db15db3..000000000 --- a/LanguageExt.Pipes/PureProxy/Pipe.cs +++ /dev/null @@ -1,247 +0,0 @@ -// -// This file contains a number of micro-free-monads that allow for creation of pure producers, consumers, and pipes. -// They're used to facilitate the building of Proxy derived types without the need for typing the generic arguments endlessly -// The Haskell original could auto-infer the generic parameter types, the system here tries to replicate manually what -// Haskell can do automatically. Hence why there are so many implementations of SelectMany! -// - -using System; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -public abstract class Pipe -{ - public abstract Pipe Select(Func f); - public abstract Pipe Interpret() where M : Monad; - - public abstract Pipe Bind(Func> f); - public abstract Pipe Bind(Func> f) where M : Monad; - public abstract Pipe Bind(Func> f); - public abstract Pipe Bind(Func> f); - - public Pipe Bind(Func> f) => - Map(x => f(x).Value); - - public Pipe Bind(Func> f) => - Bind(x => new Pipe.Fail(f(x).Value)); - - public Pipe Bind(Func> f) - where M : Monad => - Interpret().Bind(f); - - public Pipe Bind(Func> f) => - Bind(x => PureProxy.PipeLiftIO(f(x))); - - public Pipe Map(Func f) => - Select(f); - - public Pipe SelectMany(Func> f, Func project) => - Bind(a => f(a).Select(b => project(a, b))); - - public Pipe SelectMany(Func> f, Func project) => - Map(a => project(a, f(a).Value)); - - public Pipe SelectMany(Func> f, Func project) => - Bind(f); - - public Pipe SelectMany(Func> f, Func project) - where M : Monad => - Bind(a => M.Map(b => project(a, b), f(a))); - - public Pipe SelectMany(Func> f, Func project) => - Bind(x => f(x).Map(y => project(x, y))); - - public Pipe SelectMany(Func> f, Func project) where M : Monad => - Bind(a => f(a).Select(b => project(a, b))); - - public Pipe SelectMany(Func> f, Func project) => - Bind(a => f(a).Select(b => project(a, b))); - - public Pipe SelectMany(Func> f, Func project) => - Bind(a => f(a).Select(b => project(a, b))); - - public Pipe SelectMany(Func> bind, Func project ) => - Map(a => bind(a) switch - { - { Flag: true } => project(a, default), - var g => g.OnFalse().Throw() - }); - - public static implicit operator Pipe(Pure ma) => - new Pure(ma.Value); - - public static Pipe operator &( - Pipe lhs, - Pipe rhs) => - lhs.Bind(_ => rhs); - - public class Pure(A Value) : Pipe - { - public override Pipe Select(Func f) => - new Pipe.Pure(f(Value)); - - public override Pipe Bind(Func> f) => - f(Value); - - public override Pipe Bind(Func> f) => - f(Value); - - public override Pipe Interpret() => - Pipe.Pure(Value); - - public override Pipe Bind(Func> f) => - f(Value).ToPipe(); - - public override Pipe Bind(Func> f) => - f(Value).ToPipe(); - } - - public class Fail(Error Error) : Pipe - { - public override Pipe Select(Func _) => - new Pipe.Fail(Error); - - public override Pipe Interpret() => - PureProxy.PipeLift(Error.Throw); - - public override Pipe Bind(Func> f) => - new Pipe.Fail(Error); - - public override Pipe Bind(Func> f) => - PureProxy.PipeLift(Error.Throw).Bind(f); - - public override Pipe Bind(Func> _) => - new Pipe.Fail(Error); - - public override Pipe Bind(Func> f) => - new Pipe.Fail(Error); - } - - public class Lift(Func Function, Func> Next) : Pipe - { - public override Pipe Select(Func f) => - new Pipe.Lift(Function, x => Next(x).Select(f)); - - public override Pipe Interpret() => - Pipe.lift(M.Pure(Function())).Bind(x => Next(x).Interpret()); - - public override Pipe Bind(Func> f) => - new Pipe.Lift(Function, x => Next(x).Bind(f)); - - public override Pipe Bind(Func> f) => - Pipe.lift(M.Pure(Function())).SelectMany(x => Next(x).Bind(f)).ToPipe(); - - public override Pipe Bind(Func> f) => - new Pipe.Lift(Function, x => Next(x).Bind(y => f(y).ToPipe())); - - public override Pipe Bind(Func> f) => - new Pipe.Lift(Function, x => Next(x).Bind(y => f(y).ToPipe())); - } - - public class LiftIO(IO Effect, Func> Next) : Pipe - { - public override Pipe Select(Func f) => - new Pipe.LiftIO(Effect, x => Next(x).Select(f)); - - public override Pipe Interpret() => - Pipe.lift(M.LiftIO(Effect)).Bind(x => Next(x).Interpret()); - - public override Pipe Bind(Func> f) => - new Pipe.LiftIO(Effect, x => Next(x).Bind(f)); - - public override Pipe Bind(Func> f) => - Pipe.lift(M.LiftIO(Effect)).SelectMany(x => Next(x).Bind(f)).ToPipe(); - - public override Pipe Bind(Func> f) => - new Pipe.LiftIO(Effect, x => Next(x).Bind(y => f(y).ToPipe())); - - public override Pipe Bind(Func> f) => - new Pipe.LiftIO(Effect, x => Next(x).Bind(y => f(y).ToPipe())); - } - - public class Await(Func> Next) : Pipe - { - public override Pipe Select(Func f) => - new Pipe.Await(x => Next(x).Select(f)); - - public override Pipe Bind(Func> f) => - new Pipe.Await(x => Next(x).Bind(f)); - - public override Pipe Bind(Func> f) => - from x in Interpret() - from r in f(x) - select r; - - public override Pipe Interpret() => - from x in Pipe.awaiting() - from r in Next(x) - select r; - - public override Pipe Bind(Func> f) => - new Pipe.Await(x => Next(x).Bind(f)); - - public override Pipe Bind(Func> f) => - new Pipe.Await(x => Next(x).Bind(f)); - } - - public class Yield(OUT Value, Func> Next) : Pipe - { - public override Pipe Select(Func f) => - new Pipe.Yield(Value, x => Next(x).Select(f)); - - public override Pipe Bind(Func> f) => - new Pipe.Yield(Value, x => Next(x).Bind(f)); - - public override Pipe Bind(Func> f) => - from x in Interpret() - from r in f(x) - select r; - - public override Pipe Interpret() => - from x in Pipe.yield(Value) - from r in Next(x) - select r; - - public override Pipe Bind(Func> f) => - new Pipe.Yield(Value, x => Next(x).Bind(f)); - - public override Pipe Bind(Func> f) => - new Pipe.Yield(Value, x => Next(x).Bind(f)); - } - - public class Fold(K Items, Func> YieldValue, Func> Next) : Pipe - where F : Foldable - { - public override Pipe Select(Func f) => - new Pipe.Fold(Items, YieldValue, () => Next().Select(f)); - - public override Pipe Bind(Func> f) => - new Pipe.Fold(Items, YieldValue, () => Next().Bind(f)); - - public override Pipe Bind(Func> f) => - new(new IteratorFoldable( - Items, - x => YieldValue(x).Interpret(), - () => Next().Bind(f))); - - public override Pipe Bind(Func> f) => - new Pipe.Fold( - Items, - YieldValue, - () => Next().Bind(f)); - - public override Pipe Bind(Func> f) => - new Pipe.Fold( - Items, - YieldValue, - () => Next().Bind(f)); - - public override Pipe Interpret() => - new(new IteratorFoldable( - Items, - x => YieldValue(x).Interpret(), - () => Next().Interpret())); - } -} diff --git a/LanguageExt.Pipes/PureProxy/Producer.cs b/LanguageExt.Pipes/PureProxy/Producer.cs deleted file mode 100644 index ec6b85725..000000000 --- a/LanguageExt.Pipes/PureProxy/Producer.cs +++ /dev/null @@ -1,188 +0,0 @@ -// -// This file contains a number of micro-free-monads that allow for creation of pure producers, consumers, and pipes. -// They're used to facilitate the building of Proxy derived types without the need for typing the generic arguments endlessly -// The Haskell original could auto-infer the generic parameter types, the system here tries to replicate manually what -// Haskell can do automatically. Hence why there are so many implementations of SelectMany! -// - -using System; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -public abstract class Producer -{ - public abstract Producer Select(Func f); - - public abstract Producer Bind(Func> f); - public abstract Producer Bind(Func> f) where M : Monad; - - public abstract Producer Interpret() where M : Monad; - public abstract Pipe ToPipe(); - - public Producer Bind(Func> f) => - Map(x => f(x).Value); - - public Producer Bind(Func> f) => - Bind(x => new Producer.Fail(f(x).Value)); - - public Producer Bind(Func> f) - where M : Monad => - Interpret().Bind(f); - - public Producer Bind(Func> f) => - Bind(x => PureProxy.ProducerLiftIO(f(x))); - - public Producer Map(Func f) => - Select(f); - - public Producer SelectMany(Func> f, Func project) => - Bind(a => f(a).Select(b => project(a, b))); - - public Producer SelectMany(Func> f, Func project) where M : Monad => - Bind(a => f(a).Select(b => project(a, b))); - - public Producer SelectMany(Func> f, Func project) => - Map(a => project(a, f(a).Value)); - - public Producer SelectMany(Func> f, Func project) => - Bind(f); - - public Producer SelectMany(Func> f, Func project) => - Bind(x => f(x).Map(y => project(x, y))); - - public Producer SelectMany(Func> f, Func project) - where M : Monad => - Bind(a => M.Map(b => project(a, b), f(a))); - - public Producer SelectMany(Func> bind, Func project ) => - Map(a => bind(a) switch - { - { Flag: true } => project(a, default), - var g => g.OnFalse().Throw() - }); - - public static implicit operator Producer(Pure ma) => - new Pure(ma.Value); - - public static Producer operator &( - Producer lhs, - Producer rhs) => - lhs.Bind(_ => rhs); - - public class Pure(A Value) : Producer - { - public override Producer Select(Func f) => - new Producer.Pure(f(Value)); - - public override Producer Bind(Func> f) => - f(Value); - - public override Producer Bind(Func> f) => - f(Value); - - public override Producer Interpret() => - Producer.Pure(Value); - - public override Pipe ToPipe() => - new Pipe.Pure(Value); - } - - public class Fail(Error Error) : Producer - { - public override Producer Select(Func _) => - new Producer.Fail(Error); - - public override Producer Bind(Func> f) => - new Producer.Fail(Error); - - public override Producer Bind(Func> f) => - PureProxy.ProducerLift(Error.Throw).Bind(f); - - public override Producer Interpret() => - PureProxy.ProducerLift(Error.Throw); - - public override Pipe ToPipe() => - new Pipe.Fail(Error); - } - - public class Lift(Func Function, Func> Next) : Producer - { - public override Producer Select(Func f) => - new Producer.Lift(Function, x => Next(x).Select(f)); - - public override Producer Bind(Func> f) => - new Producer.Lift(Function, x => Next(x).Bind(f)); - - public override Producer Bind(Func> f) => - Producer.lift(M.Pure(Function())).SelectMany(x => Next(x).Bind(f)).ToProducer(); - - public override Producer Interpret() => - Producer.lift(M.Pure(Function())).Bind(x => Next(x).Interpret()); - - public override Pipe ToPipe() => - new Pipe.Lift(Function, x => Next(x).ToPipe()); - } - - public class LiftIO(IO Effect, Func> Next) : Producer - { - public override Producer Select(Func f) => - new Producer.LiftIO(Effect, x => Next(x).Select(f)); - - public override Producer Bind(Func> f) => - new Producer.LiftIO(Effect, x => Next(x).Bind(f)); - - public override Producer Bind(Func> f) => - Producer.lift(M.LiftIO(Effect)).SelectMany(x => Next(x).Bind(f)).ToProducer(); - - public override Producer Interpret() => - Producer.lift(M.LiftIO(Effect)).Bind(x => Next(x).Interpret()); - - public override Pipe ToPipe() => - new Pipe.LiftIO(Effect, x => Next(x).ToPipe()); - } - - public class Yield(OUT Value, Func> Next) : Producer - { - public override Producer Select(Func f) => - new Producer.Yield(Value, n => Next(n).Select(f)); - - public override Producer Bind(Func> f) => - new Producer.Yield(Value, n => Next(n).Bind(f)); - - public override Producer Bind(Func> f) => - Interpret().Bind(f).ToProducer(); - - public override Producer Interpret() => - Producer.yield(Value).Bind(x => Next(x).Interpret()).ToProducer(); - - public override Pipe ToPipe() => - new Pipe.Yield(Value, x => Next(x).ToPipe()); - } - - public class Fold(K Items, Func> YieldValue, Func> Next) : Producer - where F : Foldable - { - public override Producer Select(Func f) => - new Producer.Fold(Items, YieldValue, () => Next().Select(f)); - - public override Producer Bind(Func> f) => - new Producer.Fold(Items, YieldValue, () => Next().Bind(f)); - - public override Producer Bind(Func> f) => - new(new IteratorFoldable( - Items, - x => YieldValue(x).Interpret(), - () => Next().Bind(f))); - - public override Producer Interpret() => - new(new IteratorFoldable( - Items, - x => YieldValue(x).Interpret(), - () => Next().Interpret())); - - public override Pipe ToPipe() => - new Pipe.Fold(Items, x => YieldValue(x).ToPipe(), () => Next().ToPipe()); - } -} diff --git a/LanguageExt.Pipes/PureProxy/PureProxy.cs b/LanguageExt.Pipes/PureProxy/PureProxy.cs deleted file mode 100644 index 7d1e50af9..000000000 --- a/LanguageExt.Pipes/PureProxy/PureProxy.cs +++ /dev/null @@ -1,121 +0,0 @@ -// -// This file contains a number of micro-free-monads that allow for creation of pure producers, consumers, and pipes. -// They're used to facilitate the building of Proxy derived types without the need for typing the generic arguments endlessly -// The Haskell original could auto-infer the generic parameter types, the system here tries to replicate manually what -// Haskell can do automatically. Hence why there are so many implementations of SelectMany! -// - -using System; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -public static class PureProxy -{ - public static Pipe PipePure(A value) => - new Pipe.Pure(value); - - public static Producer ProducerPure(A value) => - new Producer.Pure(value); - - public static Consumer ConsumerPure(A value) => - new Consumer.Pure(value); - - - public static Pipe PipeFail(Error value) => - new Pipe.Fail(value); - - public static Producer ProducerFail(Error value) => - new Producer.Fail(value); - - public static Consumer ConsumerFail(Error value) => - new Consumer.Fail(value); - - - public static Pipe PipeLift(Func t) => - new Pipe.Lift(t, PipePure); - - public static Producer ProducerLift(Func t) => - new Producer.Lift(t, ProducerPure); - - public static Consumer ConsumerLift(Func t) => - new Consumer.Lift(t, ConsumerPure); - - - public static Pipe PipeLiftIO(IO ma) => - new Pipe.LiftIO(ma, PipePure); - - public static Producer ProducerLiftIO(IO ma) => - new Producer.LiftIO(ma, ProducerPure); - - public static Consumer ConsumerLiftIO(IO ma) => - new Consumer.LiftIO(ma, ConsumerPure); - - - public static Pipe PipeFold(K items) - where F : Foldable => - new Pipe.Fold( - items, - PipeYield, - () => PipePure(Prelude.unit)); - - public static Producer ProducerFold(K items) - where F : Foldable => - new Producer.Fold( - items, - ProducerYield, - () => ProducerPure(Prelude.unit)); - - public static Consumer ConsumerFold(K items) - where F : Foldable => - new Consumer.Fold( - items, - _ => ConsumerPure(Prelude.unit), - () => ConsumerPure(Prelude.unit)); - - - public static Consumer ConsumerAwait() => - new Consumer.Await(ConsumerPure); - - public static Pipe PipeAwait() => - new Pipe.Await(PipePure); - - - public static Producer ProducerYield(OUT value) => - new Producer.Yield(value, ProducerPure); - - public static Pipe PipeYield(OUT value) => - new Pipe.Yield(value, PipePure); - - // HERE - public static Consumer SelectMany(this K ma, Func> f, Func project) where M : Monad => - from a in Consumer.lift(ma) - from b in f(a).Interpret() - select project(a, b); - - public static Producer SelectMany(this K ma, Func> f, Func project) where M : Monad => - from a in Producer.lift(ma) - from b in f(a).Interpret() - select project(a, b); - - public static Pipe SelectMany(this K ma, Func> f, Func project) where M : Monad => - from a in Pipe.lift(ma) - from b in f(a).Interpret() - select project(a, b); - - public static Consumer SelectMany(this K ma, Func> f, Func project) where M : Monad => - from a in Consumer.lift(ma) - from b in f(a) - select project(a, b); - - public static Producer SelectMany(this K ma, Func> f, Func project) where M : Monad => - from a in Producer.lift(ma) - from b in f(a) - select project(a, b); - - public static Pipe SelectMany(this K ma, Func> f, Func project) where M : Monad => - from a in Pipe.lift(ma) - from b in f(a) - select project(a, b); -} diff --git a/LanguageExt.Pipes/PureProxy/README.md b/LanguageExt.Pipes/PureProxy/README.md deleted file mode 100644 index 208af12c0..000000000 --- a/LanguageExt.Pipes/PureProxy/README.md +++ /dev/null @@ -1,7 +0,0 @@ -This folder contains a number of micro-free-monads that allow for creation of _pure_ producers, consumers, and pipes. They're used to facilitate the building of `Proxy` derived types without the need for typing the generic arguments endlessly. - -The original Haskell Pipes library could auto-infer the generic parameter types, the system here tries to replicate manually what -Haskell can do automatically. Hence why there are so many implementations of `SelectMany`! - -Mostly you shouldn't need to care too much about the types in this folder as they're effectively 'intermediate' types. - diff --git a/LanguageExt.Pipes/Queue/CoreTypes.cs b/LanguageExt.Pipes/Queue/CoreTypes.cs deleted file mode 100644 index 16a813507..000000000 --- a/LanguageExt.Pipes/Queue/CoreTypes.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System; -using System.Diagnostics.Contracts; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -public record Queue : Producer - where M : Monad -{ - /// - /// Single queue channel - /// - readonly Channel channel; - - internal Queue(Proxy value, Channel channel) : base(value) => - this.channel = channel; - - /// - /// Enqueue an item - /// - public Unit Enqueue(OUT value) => - channel.Post(value); - - /// - /// Enqueue an item - /// - public K EnqueueM(OUT value) => - M.Pure(Enqueue(value)); - - /// - /// Mark the Queue as done and cancel any Effect that it is in - /// - public Unit Done() => - channel.Stop(); - - /// - /// Mark the Queue as done and cancel any Effect that it is in - /// - public K DoneM => - M.Pure(Done()); - - [Pure] - public override Proxy ToProxy() => - Value.ToProxy(); - - [Pure] - public override Proxy Bind(Func> f) => - Value.Bind(f); - - [Pure] - public override Proxy Map(Func f) => - Value.Map(f); - - [Pure] - public new Producer Select(Func f) => - Value.Map(f).ToProducer(); - - [Pure] - public override Proxy For(Func> body) => - Value.For(body); - - [Pure] - public override Proxy Action(Proxy r) => - Value.Action(r); - - /// - /// (f +>> p) pairs each 'request' in `this` with a 'respond' in `lhs`. - /// - [Pure] - public override Proxy PairEachRequestWithRespond( - Func> lhs) => - Value.PairEachRequestWithRespond(lhs); - - [Pure] - public override Proxy ReplaceRequest( - Func> lhs) => - Value.ReplaceRequest(lhs); - - [Pure] - public override Proxy PairEachRespondWithRequest( - Func> rhs) => - Value.PairEachRespondWithRequest(rhs); - - [Pure] - public override Proxy ReplaceRespond( - Func> rhs) => - Value.ReplaceRespond(rhs); - - [Pure] - public override Proxy Reflect() => - Value.Reflect(); - - [Pure] - public override Proxy Observe() => - Value.Observe(); - - [Pure] - public static Effect operator |(Queue p1, Consumer p2) => - Proxy.compose(p1, p2); - - [Pure] - public static Effect operator |(Queue p1, Consumer p2) => - Proxy.compose(p1, p2); - - [Pure] - public override string ToString() => - "queue"; -} diff --git a/LanguageExt.Pipes/RequestRespond/CoreTypes.cs b/LanguageExt.Pipes/RequestRespond/CoreTypes.cs deleted file mode 100644 index fc3004f9d..000000000 --- a/LanguageExt.Pipes/RequestRespond/CoreTypes.cs +++ /dev/null @@ -1,240 +0,0 @@ -using System; -using System.Diagnostics.Contracts; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -/// -/// One of the algebraic cases of the `Proxy` type. This type represents a request. -/// -/// Aff system runtime -/// Upstream out type -/// Upstream in type -/// Downstream in type -/// Downstream uut type -/// The monadic bound variable - it doesn't flow up or down stream, it works just like any bound -/// monadic variable. If the effect represented by the `Proxy` ends, then this will be the result value. -/// -/// When composing `Proxy` sub-types (like `Producer`, `Pipe`, `Consumer`, etc.) -public record Request(UOut Value, Func> Next) - : Proxy - where M : Monad -{ - [Pure] - public override Proxy ToProxy() => this; - - [Pure] - public void Deconstruct(out UOut value, out Func> fun) => - (value, fun) = (Value, Next); - - [Pure] - public override Proxy For( - Func> body) => - ReplaceRespond(body); - - [Pure] - public override Proxy Action( - Proxy r) => - new Request(Value, a => Next(a).Action(r)); - - /* - (f >\\ p) replaces each 'request' in `this` with `lhs`. - - Point-ful version of (\>\) - */ - [Pure] - public override Proxy ReplaceRequest( - Func> lhs) => - lhs(Value).Bind(b => Next(b).ReplaceRequest(lhs)); - - /* - (p //> f) replaces each 'respond' in `this` with `rhs` - - Point-ful version of />/ - */ - [Pure] - public override Proxy ReplaceRespond( - Func> rhs) => - new Request(Value, x => Next(x).ReplaceRespond(rhs)); - - /// - /// (f +>> p) pairs each 'request' in `this` with a 'respond' in `lhs`. - /// - [Pure] - public override Proxy PairEachRequestWithRespond( - Func> lhs) => - lhs(Value).PairEachRespondWithRequest(Next); - - /* - (p >>~ f) pairs each 'respond' in `this` with a 'request' in `rhs`. - - Point-ful version of ('>~>') - */ - [Pure] - public override Proxy PairEachRespondWithRequest( - Func> rhs) => - new Request(Value, a => Next(a).PairEachRespondWithRequest(rhs)); - - [Pure] - public override Proxy Reflect() => - new Respond(Value, x => Next(x).Reflect()); - - [Pure] - public override Proxy Observe() => - new ProxyM( - M.Pure>( - new Request( - Value, - x => Next(x).Observe()))); - - [Pure] - public override Proxy Bind(Func> f) => - new Request(Value, a => Next(a).Bind(f)); - - [Pure] - public override Proxy Map(Func f) => - new Request(Value, a => Next(a).Map(f)); - - /// - /// Map the lifted monad - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy MapM(Func, K> f) => - new Request(Value, a => Next(a).MapM(f)); - - /// - /// Extract the lifted IO monad (if there is one) - /// - /// The map function - /// A new `Proxy` that represents the innermost IO monad, if it exists. - /// `Errors.UnliftIONotSupported` if there's no IO monad in the stack - [Pure] - public override Proxy> ToIO() => - new Request>(Value, a => Next(a).ToIO()); - - [Pure] - public override string ToString() => - "request"; -} - -/// -/// One of the algebraic cases of the `Proxy` type. This type represents a response. -/// -/// Aff system runtime -/// Upstream out type -/// Upstream in type -/// Downstream in type -/// Downstream uut type -/// The monadic bound variable - it doesn't flow up or down stream, it works just like any bound -/// monadic variable. If the effect represented by the `Proxy` ends, then this will be the result value. -/// -/// When composing `Proxy` sub-types (like `Producer`, `Pipe`, `Consumer`, etc.) -public record Respond(DOut Value, Func> Next) - : Proxy - where M : Monad -{ - [Pure] - public override Proxy ToProxy() => this; - - [Pure] - public override Proxy Bind(Func> f) => - new Respond(Value, b1 => Next(b1).Bind(f)); - - [Pure] - public override Proxy Map(Func f) => - new Respond(Value, a => Next(a).Map(f)); - - /// - /// Map the lifted monad - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy MapM(Func, K> f) => - new Respond(Value, a => Next(a).MapM(f)); - - /// - /// Extract the lifted IO monad (if there is one) - /// - /// The map function - /// A new `Proxy` that represents the innermost IO monad, if it exists. - /// `Errors.UnliftIONotSupported` if there's no IO monad in the stack - [Pure] - public override Proxy> ToIO() => - new Respond>(Value, a => Next(a).ToIO()); - - [Pure] - public override Proxy For(Func> body) => - ReplaceRespond(body); - - [Pure] - public override Proxy Action(Proxy r) => - new Respond(Value, b1 => Next(b1).Action(r)); - - /* - (f >\\ p) replaces each 'request' in `this` with `lhs`. - - Point-ful version of (\>\) - */ - [Pure] - public override Proxy ReplaceRequest(Func> lhs) => - new Respond(Value, x1 => Next(x1).ReplaceRequest(lhs)); - - /* - (p //> f) replaces each 'respond' in `this` with `rhs` - - Point-ful version of />/ - */ - [Pure] - public override Proxy ReplaceRespond( - Func> rhs) => - rhs(Value).Bind(b1 => Next(b1).ReplaceRespond(rhs)); - - /* - (f +>> p) pairs each 'request' in `this` with a 'respond' in `lhs`. - - Point-ful version of ('>+>') - */ - /// - /// (f +>> p) pairs each 'request' in `this` with a 'respond' in `lhs`. - /// - [Pure] - public override Proxy PairEachRequestWithRespond( - Func> fb1) => - new Respond(Value, c1 => Next(c1).PairEachRequestWithRespond(fb1)); - - /* - (p >>~ f) pairs each 'respond' in `this` with a 'request' in `rhs`. - - Point-ful version of ('>~>') - */ - [Pure] - public override Proxy PairEachRespondWithRequest( - Func> rhs) => - rhs(Value).PairEachRequestWithRespond(Next); - - [Pure] - public override Proxy Reflect() => - new Request(Value, x => Next(x).Reflect()); - - [Pure] - public override Proxy Observe() => - new ProxyM( - M.Pure>( - new Respond( - Value, - x => Next(x).Observe()))); - - [Pure] - public void Deconstruct(out DOut value, out Func> fun) => - (value, fun) = (Value, Next); - - [Pure] - public override string ToString() => - "respond"; -} diff --git a/LanguageExt.Pipes/Server/CoreTypes.cs b/LanguageExt.Pipes/Server/CoreTypes.cs deleted file mode 100644 index 116d48715..000000000 --- a/LanguageExt.Pipes/Server/CoreTypes.cs +++ /dev/null @@ -1,221 +0,0 @@ -using System; -using System.Diagnostics.Contracts; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -/// -/// `Server` receives requests of type `REQ` and sends responses of type `RES`. -/// -/// `Servers` only `respond` and never `request`. -/// -/// -/// Upstream | Downstream -/// +---------+ -/// | | -/// Void〈== 〈== RES -/// | | -/// Unit ==〉 ==〉 REQ -/// | | | -/// +----|----+ -/// | -/// A -/// -public record Server : Proxy - where M : Monad -{ - public readonly Proxy Value; - - /// - /// Constructor - /// - /// Correctly shaped `Proxy` that represents a `Server` - public Server(Proxy value) => - Value = value; - - /// - /// Calling this will effectively cast the subtype to the base. - /// - /// This type wraps up a `Proxy` for convenience, and so it's a `Proxy` proxy. So calling this method - /// isn't exactly the same as a cast operation, as it unwraps the `Proxy` from within. It has the same effect - /// however, and removes a level of indirection - /// A general `Proxy` type from a more specialised type - [Pure] - public override Proxy ToProxy() => - Value.ToProxy(); - - /// - /// Monadic bind operation, for chaining `Proxy` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public override Proxy Bind(Func> f) => - Value.Bind(f); - - /// - /// Lifts a pure function into the `Proxy` domain, causing it to map the bound value within - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy Map(Func f) => - Value.Map(f); - - /// - /// Map the lifted monad - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public override Proxy MapM(Func, K> f) => - Value.MapM(f); - - /// - /// Extract the lifted IO monad (if there is one) - /// - /// The map function - /// A new `Proxy` that represents the innermost IO monad, if it exists. - /// `Errors.UnliftIONotSupported` if there's no IO monad in the stack - [Pure] - public override Proxy> ToIO() => - Value.ToIO(); - - /// - /// Monadic bind operation, for chaining `Server` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Server Bind(Func> f) => - Value.Bind(f).ToServer(); - - /// - /// Monadic bind operation, for chaining `Server` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Server SelectMany(Func> f) => - Value.Bind(f).ToServer(); - - /// - /// Monadic bind operation, for chaining `Server` computations together. - /// - /// The bind function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the bind operation - [Pure] - public Server SelectMany(Func> f, Func project) => - Value.Bind(a => f(a).Map(b => project(a, b))).ToServer(); - - /// - /// Lifts a pure function into the `Proxy` domain, causing it to map the bound value within - /// - /// The map function - /// The mapped bound value type - /// A new `Proxy` that represents the composition of this `Proxy` and the result of the map operation - [Pure] - public new Server Select(Func f) => - Value.Map(f).ToServer(); - - /// - /// `For(body)` loops over the `Proxy p` replacing each `yield` with `body` - /// - /// Any `yield` found in the `Proxy` will be replaced with this function. It will be composed so - /// that the value yielded will be passed to the argument of the function. That returns a `Proxy` to continue the - /// processing of the computation - /// A new `Proxy` that represents the composition of this `Proxy` and the function provided - [Pure] - public override Proxy For(Func> body) => - Value.For(body); - - /// - /// Applicative action - /// - /// Invokes this `Proxy`, then the `Proxy r` - /// - /// `Proxy` to run after this one - [Pure] - public override Proxy Action(Proxy r) => - Value.Action(r); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - /// - /// (f +>> p) pairs each 'request' in `this` with a 'respond' in `lhs`. - /// - [Pure] - public override Proxy PairEachRequestWithRespond( - Func> lhs) => - Value.PairEachRequestWithRespond(lhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy ReplaceRequest( - Func> lhs) => - Value.ReplaceRequest(lhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy PairEachRespondWithRequest( - Func> rhs) => - Value.PairEachRespondWithRequest(rhs); - - /// - /// Used by the various composition functions and when composing proxies with the `|` operator. You usually - /// wouldn't need to call this directly, instead either pipe them using `|` or call `Proxy.compose(lhs, rhs)` - /// - [Pure] - public override Proxy ReplaceRespond( - Func> rhs) => - Value.ReplaceRespond(rhs); - - /// - /// Reverse the arrows of the `Proxy` to find its dual. - /// - /// The dual of `this` - [Pure] - public override Proxy Reflect() => - Value.Reflect(); - - /// - /// - /// Observe(lift (Pure(r))) = Observe(Pure(r)) - /// Observe(lift (m.Bind(f))) = Observe(lift(m.Bind(x => lift(f(x))))) - /// - /// This correctness comes at a small cost to performance, so use this function sparingly. - /// This function is a convenience for low-level pipes implementers. You do not need to - /// use observe if you stick to the safe API. - /// - [Pure] - public override Proxy Observe() => - Value.Observe(); - - [Pure] - public void Deconstruct(out Proxy value) => - value = Value; - - /// - /// Chain one server after another - /// - [Pure] - public static Server operator &( - Server lhs, - Server rhs) => - lhs.Bind(_ => rhs); -} diff --git a/LanguageExt.Pipes/Server/Server.cs b/LanguageExt.Pipes/Server/Server.cs deleted file mode 100644 index bda379330..000000000 --- a/LanguageExt.Pipes/Server/Server.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Diagnostics.Contracts; -using System.Runtime.CompilerServices; -using LanguageExt.Common; -using LanguageExt.Traits; - -namespace LanguageExt.Pipes; - -/// -/// `Server` receives requests of type `REQ` and sends responses of type `RES`. -/// -/// `Servers` only `respond` and never `request`. -/// -/// -/// Upstream | Downstream -/// +---------+ -/// | | -/// Void〈== 〈== RES -/// | | -/// Unit ==〉 ==〉REQ -/// | | | -/// +----|----+ -/// | -/// A -/// -public class Server -{ - /// - /// Monad return / pure - /// - [Pure, MethodImpl(Proxy.mops)] - public static Server Pure(R value) - where M : Monad => - new Pure(value).ToServer(); - - /// - /// Send a value of type `RES` downstream and block waiting for a reply of type `REQ` - /// - /// - /// `respond` is the identity of the respond category. - /// - [Pure, MethodImpl(Proxy.mops)] - public static Server respond(RES value) - where M : Monad => - new Respond(value, r => new Pure(r)).ToServer(); - - /// - /// Lift am IO monad into the `Proxy` monad transformer - /// - [Pure, MethodImpl(Proxy.mops)] - public static Server lift(K ma) - where M : Monad => - new ProxyM(M.Map(Proxy.Pure, ma)).ToServer(); - - /// - /// Lift am IO monad into the `Proxy` monad transformer - /// - [Pure, MethodImpl(Proxy.mops)] - public static Server liftIO(IO ma) - where M : Monad => - lift(M.LiftIO(ma)); -} diff --git a/LanguageExt.Pipes/Utility/Channel.cs b/LanguageExt.Pipes/Utility/Channel.cs deleted file mode 100644 index 5e16b5de1..000000000 --- a/LanguageExt.Pipes/Utility/Channel.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Threading; - -namespace LanguageExt.Pipes; - -/// -/// An asynchronous queue that guarantees that only one item in the queue is being processed at any one time. -/// It also guarantees that every item in the queue is processed before a `Stop` action. -/// -class Channel : IAsyncEnumerable -{ - readonly ConcurrentQueue> queue; - readonly AutoResetEvent wait; - - /// - /// Construct - /// - public Channel() - { - queue = new ConcurrentQueue>(); - wait = new AutoResetEvent(false); - } - - /// - /// Clean up - /// - ~Channel() => - wait.Dispose(); - - /// - /// Number of items in the channel - /// - public int Count => - queue.Count; - - /// - /// Post an event - /// - /// Event - internal Unit Post(Ev @event) - { - queue.Enqueue(@event); - wait.Set(); - return default; - } - - /// - /// Post an item - /// - /// Value - public Unit Post(A value) => - Post(Ev.Item(value)); - - /// - /// Stop event - /// - public Unit Stop() => - Post(Ev.Stop); - - public async IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - { - while (true) - { - await wait.WaitOneAsync(cancellationToken).ConfigureAwait(false); - if (cancellationToken.IsCancellationRequested) yield break; - - while (queue.TryDequeue(out var item)) - { - if (cancellationToken.IsCancellationRequested) yield break; - - switch (item) - { - case ItemEv e: - yield return e.Value; - break; - - case StopEv: - yield break; - } - } - } - } -} - -/// -/// Event -/// -static class Ev -{ - public static Ev Item(A value) => new ItemEv(value); -} - -/// -/// Event -/// -abstract record Ev -{ - public static readonly Ev Stop = StopEv.Default; -} - -/// -/// New value event -/// -sealed record ItemEv(A Value) : Ev; - -/// -/// Stop event -/// -sealed record StopEv : Ev -{ - public static readonly Ev Default = new StopEv(); -} diff --git a/Samples/PipesExamples/Concurrent/Outbox/Outbox.Module.cs b/Samples/PipesExamples/Concurrent/Outbox/Outbox.Module.cs deleted file mode 100644 index 7692b8ea5..000000000 --- a/Samples/PipesExamples/Concurrent/Outbox/Outbox.Module.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace LanguageExt.Pipes2.Concurrent; - -public partial class Outbox -{ - -} diff --git a/Samples/PipesExamples/Program.cs b/Samples/PipesExamples/Program.cs index 271cf55a4..5add49694 100644 --- a/Samples/PipesExamples/Program.cs +++ b/Samples/PipesExamples/Program.cs @@ -2,11 +2,10 @@ using LanguageExt; using LanguageExt.Common; using LanguageExt.Pipes; -using LanguageExt.Pipes2; using LanguageExt.Traits; -using static LanguageExt.Pipes2.ProducerT; -using static LanguageExt.Pipes2.PipeT; -using static LanguageExt.Pipes2.ConsumerT; +using static LanguageExt.Pipes.ProducerT; +using static LanguageExt.Pipes.PipeT; +using static LanguageExt.Pipes.ConsumerT; using static LanguageExt.Prelude; /*var op = from _1 in Producer.lift(writeLine("pre-yield")) diff --git a/Samples/PipesExamples/Utility/Channel.cs b/Samples/PipesExamples/Utility/Channel.cs deleted file mode 100644 index c02cf1d1e..000000000 --- a/Samples/PipesExamples/Utility/Channel.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System.Collections.Concurrent; - -namespace LanguageExt.Pipes2; - -/// -/// An asynchronous queue that guarantees that only one item in the queue is being processed at any one time. -/// It also guarantees that every item in the queue is processed before a `Stop` action. -/// -class Channel : IAsyncEnumerable -{ - readonly ConcurrentQueue> queue; - readonly AutoResetEvent wait; - - /// - /// Construct - /// - public Channel() - { - queue = new ConcurrentQueue>(); - wait = new AutoResetEvent(false); - } - - /// - /// Clean up - /// - ~Channel() => - wait.Dispose(); - - /// - /// Number of items in the channel - /// - public int Count => - queue.Count; - - /// - /// Post an event - /// - /// Event - internal Unit Post(Ev @event) - { - queue.Enqueue(@event); - wait.Set(); - return default; - } - - /// - /// Post an item - /// - /// Value - public Unit Post(A value) => - Post(Ev.Item(value)); - - /// - /// Stop event - /// - public Unit Stop() => - Post(Ev.Stop); - - public async IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - { - while (true) - { - await wait.WaitOneAsync(cancellationToken).ConfigureAwait(false); - if (cancellationToken.IsCancellationRequested) yield break; - - while (queue.TryDequeue(out var item)) - { - if (cancellationToken.IsCancellationRequested) yield break; - - switch (item) - { - case ItemEv e: - yield return e.Value; - break; - - case StopEv: - yield break; - } - } - } - } -} - -/// -/// Event -/// -static class Ev -{ - public static Ev Item(A value) => new ItemEv(value); -} - -/// -/// Event -/// -abstract record Ev -{ - public static readonly Ev Stop = StopEv.Default; -} - -/// -/// New value event -/// -sealed record ItemEv(A Value) : Ev; - -/// -/// Stop event -/// -sealed record StopEv : Ev -{ - public static readonly Ev Default = new StopEv(); -}