question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to use Option and Writer together with LINQ syntax?

See original GitHub issue

I understand that with Option type, step 3 from c in SomeC(b) will be “skipped” due to NoneB(a) returns type of None.

//pseudo code
from a in SomeA(0) //returns Some<int>
from b in NoneB(a) //returns None
from c in SomeC(b) //returns Some<int>
select c //c is of None type

If I’m trying to combine Option with Writer. Is it possible to achieve the same “skipping” behaviour?

//pseudo code
from a in WriterSomeA(0) //returns Writer<Option<int>, string[]>
from _1 in Tell("Done A")
from b in WriterNoneBB(a) //returns None
from _2 in Tell("Done B")
from c in WriterSomeC(b)
from _3 in Tell("Done C")
select c

And should I be expecting c to be of type Writer<None<int>, string[]> as well as skipping step from c in WriterSomeC(b)?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
louthycommented, Sep 8, 2019

@HistoricallyCorrect Mixing of monad types is a bad idea and special-case SelectMany implementations leads to real inference problems for the C# compiler. It would also wipe out the writer log for stages which don’t support it (the Option stages).

However the Writer has an IsBottom state, which you could use for None:

     public static Writer<MonoidW, W, A> WriterNone<MonoidW, W, A>() 
        where MonoidW : struct, Monoid<W> => () => 
            (default, default, true);

But some better advice might be to use the code-gen system for wrapping up the RWS monad (Reader/Writer/State):

    [RWS(WriterMonoid: typeof(MSeq<string>), Env: typeof(Unit), State: typeof(Unit), 
         Constructor: "Pure", Fail: "WriterNone")]
    public partial struct Subsys<T>
    {
        // This is here to wrap up the call to the generation of a single item `Seq`
        public static Subsys<Unit> tell(string what) =>
            tell(Seq1(what));
    }

By making the Env and State into Unit you effectively have a Writer which is easier to use than the default one. So you can see that by using WriterNone it effectively gives you a short-cut out of the monad.

The Constructor and Fail parameters are used to give names to the constructor an failure functions.

You can then do this:

using static Subsys;

from a  in Pure(0)
from _1 in tell("Done A")
from b  in WriterNone<Unit>()
from _2 in tell("Done B")
from c  in Pure(b)
from _3 in tell("Done C")
select c

I updated the Reader a few weeks back to support better error handling, and will update the RWS to have a similar error handling mode in the next few days. So you’ll be able to provide an Error type that can take exceptions, strings, and error codes.

1reaction
TysonMNcommented, Sep 2, 2019

I think you meant OptionAsync ?

Yep, just fixed that typo. Thanks 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

Write LINQ queries in C# | Microsoft Learn
This example shows how to use method syntax on the results of a query clause. Just enclose the query expression in parentheses, and...
Read more >
LINQ Query Syntax
The LINQ query syntax starts with from keyword and ends with select keyword. The following is a sample LINQ query that returns a...
Read more >
Working with LINQ
This tutorial teaches you how to generate sequences with LINQ, write methods for use in LINQ queries, and distinguish between eager and lazy ......
Read more >
How to do joins in LINQ on multiple fields in single join
Just to complete this with an equivalent method chain syntax: ... I think a more readable and flexible option is to use Where...
Read more >
Can I declare / use some variable in LINQ? Or can I write ...
You need let : var q = from PropertyDescriptor t in TypeDescriptor.GetProperties(instance) let name = t.ComponentType.GetProperty(t.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found