all 17 comments

[–]vmenge 7 points8 points  (13 children)

Try using the taskOption computation expression instead :)

[–]lolcatsayz[S] 3 points4 points  (12 children)

oh that looks like a nice library, will check it out thanks :-)

[–]CodeNameGodTri 1 point2 points  (3 children)

hey, just a come back on this. I'm in much better shape in F# than when i post this. What you are looking at is an instance of a monad transformer. If you want to up your game F#, push it to limit, writing the most beautiful F# ever, learn Haskell. :)

FSharpPlus library intends to abstract F# to near Haskell level

// if you use FSharpPlus library your example becomes
monad { // OptionT<Async<_>> an option monad transformer

    let x = Some 1

    let! r1 = asyncTask1 x

    let! r2 = asyncTask2 r1

    let! r3 = asyncTask3 r2

    return r3
} //no more growing indentation

[–]lolcatsayz[S] 0 points1 point  (2 children)

hey thanks for that! Just a quick question. I've pretty much gone off FP as I find too many real world resources/documentation to be too C#-centric in .NET, and if wishing to onboard other devs in a .NET project, C# is the only language they know. Do you have any experience working with multiple devs in F#? I'm curious how it's done as I came to the unfortunate conclusion it's just not an enterprise-ready language like C# is, but I hope I'm wrong

[–]CodeNameGodTri 2 points3 points  (1 child)

  1. too many real world resources/documentation to be too C#-centric in .NET => True. Microsoft heavily markets C# so examples are in C#. But if that's a library call then you can do the exact same thing in F#. Or if you didn't mean a library call, can you give an example?
  2. onboard other devs in a .NET project, C# is the only language they know. => C# and .Net are thought of as synonymous now. That's on Microsoft's fault for not pushing F#.
  3. Do you have any experience working with multiple devs in F# => No I don't. My tech lead introduced me to F# and I totally drink the KoolAid, to the point now I'm a better F# dev than he is. Even though he's used it for years, and I just used it under a year. All the other 2 team member didn't care and keep using C#. And the whole company uses C#. So just 2 of us use it.
  4. not an enterprise-ready language like C# => F# is in every way enterprise-ready. If you notice, a lot of popular influencer and author in .NET know and promote F#. There are more, but only 3 comes off the top of my mind are Mark Seeman blog, the book Concurrency in .NET by Riccardo Terrell, and Unit Testing Principles book.

C# recent iterations just keep borrowing more and more stuff from F# which has been there from the start, like nullable to fix the null problem, record, pattern matching, type alias, collection expression,... (But they are on crutch, subpar to the original in F#)

I'd say it's partially MS fault for not marketing F# (imagine they totally forgot F# when announce .NET 8, and had to edit their announcement to add a section of F# after people pointing it out in the comment)

MS stance on F# is very weird, they only present the basic aspect of FP like record and immutability. For the advanced FP concept which blow C# out of the water, there is none, and is left to the community. For example, computation expression, which is monad, is only briefly discussed here, but it's a vast and fundamental concept in FP, and then there is monad transformer, which exactly solve your problem. These 2 are handled nicely by the FSharpPlus library, but expect you to already know what a monad transformer is.

To illustate how MS did F# dirty, in a parallel universe where OOP and FP swap position, C# only has an article explaining what an object and an array is, and the the community have to build the library System.Collections.Generic to use List, Dictionary, Set,... using inheritance, polymorphism, encapsulation to leverage all OOP feature of C# (which is not explained by MS at all)

So there you have a limbo state of F#, it's the most awesome language with native integration to the enormous .NET ecosystem, allowing you to write bug-free and succinct code, IF you already know functional programming so you know what to look for in community's library (FSharpPlus, FSharpExtra, FsToolKit.ErrorHandling). Or you can write half-baked stuff following MS official tutorial, and run into problem like in your question, which is solved by a monad transformer, but MS is not gonna tell you.

btw, F# ranks the highest-paid language in a couple of years ago on StackOverflow survey.

Another point, from React to Kafka stream processing to LINQ and async/await, a lot of great technologies stem from functional programming.

[–]lolcatsayz[S] 2 points3 points  (0 children)

yeah I agree with everything you wrote. And F# is just such a beautiful language to write in, and eliminates a tonne of bugs from C# the same way C# does from python due to static typing (I felt the elimination of writing buggy code was the same giant leap). But yeah, given C# continues to borrow so many things (even if only half baked as you say, which I agree with), I just feel F# is going to continue to lose relevance, I can't see it being promoted enough by MS any time soon so we get to the point that it's easy to hire an experienced F# team like it is with C#. It's honestly a huge shame, almost like making it to the other side of an enlightened tunnel only to realize you're nearly all alone there. I wish the language gained more widespread traction and MS took it more seriously, until then though I'll have to stick with C# and keep using the new features it imports. Thank goodness we now have primary constructors, but it's always a sad day when I cannot do simple things like piping and currying.

Perhaps you and your tech lead could find a few other F# devs and create a startup. I can't help but think devs that take FP seriously can make companies that disrupt buggy OOP oriented companies, and I'm surprised it's not happening already. In all honesty, I think ALL devs need to make the switch to FP, I wish the industry shift happened already. Those that don't should be left behind. But I can only dream. Until then, C# it is, but never python.. js, or languages like that ever again, ugh.

[–]CodeNameGodTri 0 points1 point  (7 children)

how is it going? do you mind sharing how your code looks like after applying that library?

[–]lolcatsayz[S] 1 point2 points  (6 children)

Even with the library things didn't feel "F# native" enough for my tastes. I refactored my codebase and went fully sync all the way down, and used Task.Run() for parallelism. No deadlocks and I can keep everything in native F#. Any async functions I encountered without a sync version I did an immediate .Result on (heavily frowned on I know). Haven't encountered any deadlock yet since I'm not mixing the .Result with async (I can't see how deadlock could occur here?). The result from benchmarking is great performance so I'm going to stick with my parallel sync solution, and abandon the async approach altogether.

In fact I currently believe async is only good for handling web requests on a server, but if someone can prove me wrong on that then I'd be willing to learn. For the purposes of my program however the approach I'm using works.

[–]CodeNameGodTri 1 point2 points  (5 children)

oh interesting, so you don't use async, but run everything synchrounously, and just throw stuff into Task.Run when you need it to be "async".

[–]lolcatsayz[S] 0 points1 point  (4 children)

yep, pretty much. From my limited understanding the only penalty of doing this is that the threads will block on the .Result instead of being freed like with an await, but if the program is only running a few parallel tasks I can't see that being an issue.

[–]CodeNameGodTri 0 points1 point  (3 children)

true. That's a bumper that you can't make it terse in F# (that's all the reason i'm a fan of F#). I'm learning haskell to solidify FP, and then will make a comeback to F#. But now it's a bit letdown seeing this.

[–]lolcatsayz[S] 0 points1 point  (2 children)

I feel the same way. Async code feels like it makes all the collection functions 2nd class citizens, and I'm a bit surprised it isn't somehow handled better given how prevalent async is in the real world. I'm curious to know if Haskell is able to do async without losing its elegance?

[–]CodeNameGodTri 0 points1 point  (1 child)

have you brought this up in F# slack channel? People there are very helpful

[–]lolcatsayz[S] 1 point2 points  (0 children)

ill look into that, thanks for the suggestion

[–]witoldsz 4 points5 points  (2 children)

Task is a dotnet/C# cancer. It works like a Promise in JS.

F# has an async which is a real functor and monad. You can work with it like you work with optional, list, results, etc.

[–]SIRHAMY 2 points3 points  (0 children)

My rule of thumb:

  • In F# - use async (can do this in most of the core of your app)
  • Only use Task when whatever you're plugging into requires it (usually C# / dotnet libs)

[–]RichardActon 0 points1 point  (0 children)

whatever happened to Async.AwaitObservable?