Code Monkey home page Code Monkey logo

ply's People

Contributors

baronfel avatar gusty avatar laenas avatar nimashoghi avatar ninofloris avatar pimbrouwers avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ply's Issues

How to return early / short circuit the task?

Hi, thanks for this great library!
I encountered the issue when I wanted to return early with return (), given user is actually null, but the code actually continue to execute causing signInManager.PasswordSignInAsync to throw null argument exception, how can I avoid this?

    [<HttpPost("sign-in")>]
    member _.SignIn(dto: SignInPortalParams) =
        let username = dto.username
        let password = dto.password

        task {
            let! user = userManager.FindByNameAsync(username)

            if isNull user
            then
                logger.LogError $"Cannot find username {username}"
                return ()

            let! result = signInManager.PasswordSignInAsync(user, password, false, false)

            if result.Succeeded
            then
                logger.LogInformation $"Sign in {user} successfully"
            else
                logger.LogError $"Sign in failed"
        }

More improvements for stack traces with try...with

First of all - great job with dotnet/fsharp#2741 (comment)! It massively improves debugging experience. However, there's still at least one case when stack trace is lost: try...with. To reuse your example:

module PlyProgram

open System.Threading.Tasks
open FSharp.Control.Tasks
open System

let findDingbobbleById(x: int) = vtask {
    let! x = Task.Yield() // Force the Task to unwind the native stack
    return invalidOp "Oh no"
}

let dingbobbleFeature() = vtask {
    return! findDingbobbleById 1
}

let dingbobbleRoute() = vtask {
    try
        return! dingbobbleFeature()
    with
    | :? StackOverflowException as e -> return ()
}

[<EntryPoint>]
let main argv =
    try dingbobbleRoute().GetAwaiter().GetResult() |> ignore
    with ex -> Console.WriteLine(ex)
    0

With stack trace:

System.InvalidOperationException: Oh no
   at [email protected](Exception _arg2) in /home/abbradar/projects/somefun/src/Program.fs:line 21
   at Ply.TplPrimitives.ContinuationStateMachine`1.System-Runtime-CompilerServices-IAsyncStateMachine-MoveNext()
   at PlyProgram.main(String[] argv) in /home/abbradar/projects/somefun/src/Program.fs:line 26

Maybe we can improve this too?

EDIT: cleaned up the example

Question on ContextInsensitive tasks

Reposting @dsyme's question from TaskBuilder.


Hi all,

A question for people who use TaskBuilder, in relation to https://github.com/fsharp/fslang-design/blob/master/RFCs/FS-1097-task-builder.md

As everyone might know, the proposed support for tasks in F# is very much based around the functionality of TaskBuilder and we started with the test suite (though the implementation is entirely new).

Now TaskBuilder supports ContextInsensitive tasks where ConfigureAwait is false by default, e.g. https://github.com/rspeele/TaskBuilder.fs/blob/master/TaskBuilder.fs#L352. However the task { ... } support in the F# RFC doens't include ContextInsensitive tasks.

So the question is - how important is it for inbuilt F# task support to support a builder (e.g. open ContextInsensitive ... task { ...}) for context insensitive tasks? Or is it ok for people to do this manually?

Personally I think moving away from the UI thread should be done explicitly, e.g.

task {
    do! Task.SwitchToBackgroundThread() // or whatever

    ... }

or via explicit ConfigureAwait calls.

Any chance of implementing `let! ... and! ...`

While I'm not sure if I understand that correctly,

it would be nice to be able to launch tasks in parallel using and! notation rather than launching them separately and then do! Task.WhenAll ...

i.e., instead of:

    let task1 = launchTask1()
    let task2 = launchTask2()

    do! Task.WhenAll [| task1 :> Task; task2 :> Task |]

    let! result1 = task1
    let! result2 = task2

i'd prefer to write:

    let! result1 = launchTask1()
    and! result2 = launchTask2()

Default type inference mismatch?

I've been moving some code from Taskbuilder.fs to Ply and I've noticed an odd compilation error.

It seems that when the type of an expression unwrapped with let! is unspecified, it is always inferred as Ply<'t>.

Naturally, if I'm not using the uply builder, that's unlikely to be the default that I want, especially since it's an "unsafe" builder.

I'm much more likely to be composing the same kind of CE all the way through. But then I get a compile error at the call site because the let! expects a Ply<_> unless explicitly annotated.

Would it be possible to make each builder choose its own type as the default inference target for let! and other unwrappings?

Minimal repro

open FSharp.Control.Tasks

let higherOrderTask t = task {
    let! result = t()    
    return result + "_1"
}

let someTask () = System.IO.File.ReadAllTextAsync("/somePath")

let instance = higherOrderTask someTask
(* someTask: Type mismatch. Expecting a
    'unit -> Ply.Ply<string>'    
but given a
    'unit -> Task<string>'
*)

Current workaround:

    let! result = (t() : Task<_>)

Async.Ignore

Is there any equivalent of Async.Ignore? It would be nice to have it.

Current:

task {
    let! _ = ..
    return ()
}

After:

task {
   do! .. |> Task.ignore
}

Clarify referential transparency

F# newbie/learner here. Came across ply while following discussions about the performance of Async. Can we assume ply provides a referentially transparent representation of Tasks since it is based on computation expressions? If yes, it sounds like best of both worlds, performance and purity. Worth making this point in the introduction document.
I'd love to learn the answer to the question anyway. Many thanks for making this work open source. Looking forward to experimenting with it.

Exception gets lost

I didn't research what the root cause is, but in this example:

let testTask () =
    task {
        try
            do! Task.Yield ()
            failwith "Catch me"
        with
        | e ->
            failwith "Fail now"
        failwith "Test failed"
    }

Current output is "Test failed". Ply 0.2.2.

open FSharp.Control.Tasks vs open FSharp.Control.Tasks.Builders

read.me tells me to use the namespace FSharp.Control.Tasks.Builders that is marked as obsolete in code and I'm told to use FSharp.Control.Tasks.
And in release notes of FsToolkit.ErrorHandling: FSharp.Control.Tasks.NonAffine/Affine
Which namespace should be used?

Question: Does Ply have the same performance issue with tail recursion as TaskBuilder.fs

Does Ply have the same performance issue with recursion as TaskBuilder.fs?

From TaskBuilder.fs documentation:

In F# it is idiomatic to use tail recursion to implement loops more complex than a simple for or while. works with some computation expressions (like the built-in F# async builder), but not with TaskBuilder.fs. As far as I know it is not possible to make this work with TPL tasks. C# async/await function are not tail-call optimized either, so at least this is consistent. implement a loop that may iterate many times (or indefinitely), use a while loop instead of tail recursion.

MIssingMethodException

I'm seeing this error when calling a netstandard2.0 lib from a netcore2.2 app using the nuget package

System.MissingMethodException: Method not found: 'System.Threading.Tasks.Task`1<!!0> Ply.TplPrimitives.run(Microsoft.FSharp.Core.FSharpFunc`2<Microsoft.FSharp.Core.Unit,Ply.Ply`1<!!0>>)

However, it works if I import the source

Is Ply going to be obsolete?

I've been using Ply to great effect on an ultra-low-latency proof of concept, and it's been a joy to use. As of RFC FS-1072 native CE support for task creation is now an official part of F#, albeit on an experimental basis.

Do you believe that this will obsolete F#? Are there any benchmarks that compare Ply performance and the official F# support?

Unsafe builder use

Hello, I'd like to get a clarification on when to avoid unsafe builders with regards to the execution bubble.

It's rare that methods do anything with async locals or synchronization contexts, even in C#. So if you know anything you use doesn't do that either then there's nothing inherently unsafe about using the Unsafe CEs as you don't need any execution bubble for correctness.

What exactly does the bold part refer to? Use of synchronization contexts in my user code or also 3rd party library methods that I'm awaiting? For instance, given this code

let setupConnection () = unitVtask {
    cmd.Connection <- new NpgsqlConnection (connectionString)
    do! cmd.Connection.OpenAsync ()
    do! cmd.PrepareAsync ()
    if cfg.UseNetTopologySuite then cmd.Connection.TypeMapper.UseNetTopologySuite () |> ignore }

If I am unsure whether Npgsql uses synchronization contexts and want to play it safe, do I have to refrain from using unsafe builders all the way down? Or is it perfectly fine because OpenAsync and PrepareAsync return tasks with their own bubbles?

Additionally, I assume Unsafe.uply is the most performant of the unsafe builders. Does it have any drawbacks compared to the rest of them when used internally in a library (i.e. it does not leak through the API)?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.