Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Fabian Meyer
    @fabianmeyer

    Hi, is there something like Haskell's alternative (<|>) for Option<T> in LanguageExt?

    @fabianmeyer Yes, use ||

    Thanks! Is there also some variant with lazy eval for the RHS? Something like Option<T> Alternative<T>(Option<T> lhs, Func<Option<T>> rhs)?

    1 reply
    Xi Shen
    @davidshen84
    Hi
    I want to convert a function using TryOption, so that if the function passes it returns Some(value), if it throws it returns None.
    but the return type of TryOption is OptionResult which cannot use with Option in a linq query. any suggestions?
    Jedidja
    @jedidja
    Has anyone tried to setup AutoMapper so we could automatically map from a nullable reference type (e.g. int?) to Option<> (e.g. Option<int>)?
    Jedidja
    @jedidja
    Obviously you can do something like
        public class IntConverter : ITypeConverter<int?, Option<int>>
        {
            public Option<int> Convert(int? source, Option<int> destination, ResolutionContext context)
            {
                if (source.HasValue)
                {
                    return Option<int>.Some(source.Value);
                }
    
                return Option<int>.None;
            }
        }
    but I can't find a way to get a generic version to work.
        public class ContainerConverter<T> : IValueConverter<T?, Option<T>>, ITypeConverter<T?, Option<T>>
        {
            public Option<T> Convert(T? source, Option<T> destination, ResolutionContext context)
            {
                if (source == null)
                {
                    return Option<T>.None;
                }
    
                return Option<T>.Some(source);
            }
    
            public Option<T> Convert(T? sourceMember, ResolutionContext context)
            {
                if (sourceMember == null)
                {
                    return Option<T>.None;
                }
    
                return Option<T>.Some(sourceMember);
            }
        }
    Stefan Bertels
    @StefanBertels

    How about tree (data type)?

    I'm not sure whether this was discussed somewhere -- I could not find something. What's the (best / LanguageExt way) to create a custom immutable tree data structure -- using the current stable 3.4.15 (with codegen)?

    Should I use [Union] to make some Tree/Leaf types or just build a custom tree type ([Record]) with a Mapproperty for subtrees and some TValue property?
    My key would be "case insensitive string" (represents a directory/file structure). Just for the record: non-leaf nodes can have values, too.

    I would love to make this generic to re-use the structure with different types (TValue) but I guess this isn't an option with [Union] / [Record] (at least with 3.4.15).

    Feedback welcome.

    YuriiNskyi
    @YuriiNskyi
    Hello, I'm currently looking at this page https://github.com/louthy/language-ext/blob/master/Performance.md and have a question: am I right that e. g. HashMap is NOT more performant than simple BCL's Dictionary?
    Stefan Bertels
    @StefanBertels

    @YuriiNskyi As HashMap is immutable and simple Dictionary is not. It is not surprising that simple Dictionary will be faster in many cases (and probably effort will be taken to improve performance with every new dotnet runtime version).
    You will need to decide whether you need plain speed or a "better" type (type-safety).

    There is one thing where HashMap might outperform Dictionary: I you need multiple versions (version before and after adding/removing items) immutable types can share their storage (parts of their trees) while a mutable variant like Dictionary will have to make a full copy. I guess you will feel this if you use plenty versions (e.g. side-effect free recursive hashmap creation) with larger data size (many/large items). Finally this will depend on your use case. My take: Use immutable (LanguageExt) types where possible to make code better (small / safe / correct / expressive ...) and then look at performance bottle necks.

    Paul Louth
    @louthy
    Stefan is correct. But reading speed is the same as Dictionary, writing is more expensive due to its immutable nature. They are fundamentally different approaches, both with trade-offs. That’s why i compare it to Microsoft’s ImmutableCollections. That comparison makes sense and lang-ext collections out-perform the MS ones
    YuriiNskyi
    @YuriiNskyi
    Thank you, the performance is really bottle neck in my case, so I guess simple Dictionary is slightly preferred
    Christian Kaps
    @akkie

    Hi, has anyone suggestions regarding unit testing. Currently I use the LanguageExt.UnitTesting package. But now I have an issue with async operations and it seems that lib isn't maintained anymore. Curious about how do you test your code. Here is an example how I test the code currently:

    const string xml = "<root />";
    var httpBody = new HttpBody(HttpBodyType.Xml, xml);
    
    var result = _format.Write(httpBody);
    
    await result.ShouldBeSuccess(content =>
    {
        content.Headers.ContentType.CharSet.Should().Be(Encoding.UTF8.HeaderName);
        content.Headers.ContentType.MediaType.Should().Be(MediaTypeNames.Application.Xml);
    });

    It feels totally natural to me because I come from Scala and have used Specs2 for testing. Is there anything similar without LanguageExt.UnitTesting?

    Washington A. Ramos
    @WashingtonARamos
    Hi, guys. I'm starting with LanguageExt on a project of mine, could someone help me with some questions I have?
    First, I'm using FluentValidation to validate some fields in a method. The method returns Either<Error, T> (where T : return type). If validation through FluentValidation fails, I use Error.FromObject(validation.Errors);, how could I retrieve the List<ValidationFailure> from FluentValidation that I put in the Error?
    Secondly, I see there's some Validation part of LanguageExt, is it supposed to be used in unit tests (as most examples of it I see seem to use) or could it be used instead of FluentValidation in order to validate fields?
    Remi Guittaut
    @remiguittaut
    Hi. I'm facing like a lot of people problems with the new msft codegen setup using 0.75-alpha
    I saw that @louthy, you had yourself problems with the nuget packages
    Has anyone found a way to make things work with codegen using the 0.75-alpha? or should I revert to the 0.6.1 dotnet packages?
    Remi Guittaut
    @remiguittaut
    it's like... was working perfectly with 0.6.1 on another machine. I have a new machine , impossible to make it work even with 0.6.1. dotnet-codegen is like the worst experience ever. A colleague clones my project, it should just work! but no, we need to fiddle around, install another dotnet sdk, etc. I just don't get that msft couldn't get a simple macro system right... I'm just using scala macros in parallel and understand why I'm trying to stay away from dotnet as much as possible
    sorry for the rant
    Paul Louth
    @louthy
    You will need to use 0.6.1. The alpha was just broken. I will eventually switch over to Source Generators, which should hopefully be a better solution
    Remi Guittaut
    @remiguittaut
    Yeah, but 0.6.1 wasn't working either. Catch22, if you don't generate the code, the project doesn't compile. BUT the code isn't generated if the code doesn't compile
    So, delete the code needing codegen, build -> codegen works, and then restore it.
    Stefan Bertels
    @StefanBertels

    @remiguittaut: I use this in my csproj files with last stable 3.4.15 of LanguageExt and so far had no build problem (even after setup of a new machine) -- using [Record] and [Union]:

    <Project Sdk="Microsoft.NET.Sdk">
        <PropertyGroup>
            <TargetFramework>net5.0</TargetFramework>
            <LangVersion>latest</LangVersion>
            <Nullable>enable</Nullable>
        </PropertyGroup>
    
        <ItemGroup>
            <PackageReference Include="LanguageExt.Core" Version="3.4.15" />
            <PackageReference Include="LanguageExt.CodeGen" Version="3.4.15" />
            <PackageReference Include="CodeGeneration.Roslyn.BuildTime" Version="0.7.5-alpha" PrivateAssets="all" />
            <DotNetCliToolReference Include="dotnet-codegen" Version="0.6.1" />
        </ItemGroup>
    </Project>

    I didn't upgrade to latest (beta) LanguageExt yet. Some things changed (and improved) and I won't recommend using the old version if you're using the lastest lib.

    Andreas Bernard
    @anderschbe
    Good afternoon. I'm trying to build a validation/error handling chain. Now I'm running in some weird problems: trying to BindAsync a Task<Either> onto a Either, I get the error that Either doesn't know BindAsync. Am I missunderstanding the API reference, or was this added after 3. 4.15
    Sean Farrow
    @SeanFarrow
    Hi all, I've got a method that returns Option<string> and a second one that returns Seq<string>. Is there an easy way to check whether the string contained within the Option returned from the first method exists inthe sequence? I found the class instances folder, but wouldn't really know where to go from there. Any help apreciated.
    Mohammad Azhdari
    @azhdari
    @StefanBertels Is this project file (codegen) works on vscode-macos as well as VS on windows?
    Stefan Bertels
    @StefanBertels
    @azhdari I tested with Windows only.
    @SeanFarrow maybeOptionValue.Exists(_ => sequence.Contains(_)) or maybeOptionValue.Map(_ => sequence.Contains(_)) == false/true/None if you need tri-state result.
    Eddie Stanley
    @flakey-bit

    Hi, quick question on EitherAsync -

    Let's say I have the two methods with signatures

    private EitherAsync<ValidationProblemDetails, ImportProfile> FetchImportProfileAsync(Guid importProfileId, CancellationToken cancellationToken)
    {
        // .. 
    }
    
    private EitherAsync<ValidationProblemDetails, Account> FetchAccountAsync(Guid accountId, CancellationToken cancellationToken)
    {
        //
    }

    and I want to implement

    private async EitherAsync<IEnumerable<ValidationProblemDetails>, (Account Account, ImportProfile ImportProfile)> FetchAccountAndProfileAsync(Guid accountId, Guid importProfileId, CancellationToken cancellationToken)
    {
    }

    such that it fires off both fetches in parallel, waits for them both to complete and then if either of them are in the "Left" state, accumulates a sequence of ValidationProblemDetails - otherwise, returns a tuple of the two parts (Account and ImportProfile respectively)

    YuriiNskyi
    @YuriiNskyi
    Hello, I was wondering about Prelude.memo, and have one small question.
    Does that cached value live until Garbage Collection has occurred?
    Seems I need to investigate in which exact generation it stores the values, but maybe you can suggest?
    Andreas Bernard
    @anderschbe
    Does anyone know, if the LanguageExt.HashSet will purge duplicates automatically if given an IEnumerable? Or does it error out?
    Stefan Bertels
    @StefanBertels
    Hi Andreas, I (still) use 3.4.15 (stable) and it seems that Set/HashSet purge duplicates by default. I'm not sure how consistent this is and IIRC it wasn't consistent in the past. Maybe use explicit constructors (there should be an optional parameter tryadd) or -- if you use static functions (Prelude) then maybe use this style (which also documents your intent): HashSet<T>().TryAddRange(items).
    Sean Farrow
    @SeanFarrow

    Hi,

    I have two queries regarding the types in the class instances folder:
    Given a standard .Net int type, what is the easiest way of transforming this in to a TInt? I can't seem to find anything obvious!
    Finally, do all class instances override the ToString function? or do I need to do something special?

    Thanks,
    Sean.

    Rich Bryant
    @richbryant
    parseInt?
    Paul Louth
    @louthy

    Does anyone know, if the LanguageExt.HashSet will purge duplicates automatically if given an IEnumerable? Or does it error out?

    Yes, it does.

    Paul Louth
    @louthy

    I have two queries regarding the types in the class instances folder:
    Given a standard .Net int type, what is the easiest way of transforming this in to a TInt? I can't seem to find anything obvious!

    There is no conversion to TInt as TInt isn't a data-type, it's a mechanism for providing functionality related to int. For example:

        public static A Double<NumA, A>(A value) where NumA : struct, Num<A> => 
            default(NumA).Add(value, value);
    
        int x = Double<TInt, int>(100);
        float x = Double<TFloat, float>(100.5);

    Finally, do all class instances override the ToString function? or do I need to do something special?

    No, there's no data within them, so there's no need for a ToString on the instances.

    Does that cached value live until Garbage Collection has occurred?

    memo uses WeakReferences to hold onto the memoised value. And so it's up to the Garbage Collector when it's collected.

    If you want something that never clears use memoUnsafe. I will probably revisit the default memo implementation, because it's clearing of values is a bit too aggressive.

    Paul Louth
    @louthy

    @flakey-bit

    Hi, quick question on EitherAsync -

    Let's say I have the two methods with signatures

    private EitherAsync<ValidationProblemDetails, ImportProfile> FetchImportProfileAsync(Guid importProfileId, CancellationToken cancellationToken)
    {
        // .. 
    }
    
    private EitherAsync<ValidationProblemDetails, Account> FetchAccountAsync(Guid accountId, CancellationToken cancellationToken)
    {
        //
    }

    and I want to implement

    private async EitherAsync<IEnumerable<ValidationProblemDetails>, (Account Account, ImportProfile ImportProfile)> FetchAccountAndProfileAsync(Guid accountId, Guid importProfileId, CancellationToken cancellationToken)
    {
    }

    such that it fires off both fetches in parallel, waits for them both to complete and then if either of them are in the "Left" state, accumulates a sequence of ValidationProblemDetails - otherwise, returns a tuple of the two parts (Account and ImportProfile respectively)

    Nothing exists by default, but you could build something that works like this:

        public static EitherAsync<Seq<L>, (R Item1, R Item2)> collect<L, R>(EitherAsync<L, R> ma, EitherAsync<L, R> mb)
        {
            return Go().ToAsync();
            async Task<Either<Seq<L>, (R Item1, R Item2)>> Go()
            {
                await Task.WhenAll(ma.ToEither(), mb.ToEither()).ConfigureAwait(false);
                return (ma.Case, mb.Case) switch
                       {
                           (R x, R y) => Right((x, y)),
                           (L x, L y) => Left(Seq(x, y)),
                           (_ ,  L y) => Left(Seq1(y)),
                           (L x, _  ) => Left(Seq1(x)),
                           _          => Left(Seq<L>())
                       };
            }
        }
    Stefan Bertels
    @StefanBertels
    @louthy Regarding memo, I just want to add some use case in case you revisit/redesign memo: I'm often in need of something like memo to cache results of e.g. expensive API calls (like a REST call). I use my own custom "Lazy" wrapper which uses a timeout (validUntil) which can be dynamic (for API results that itself have time-limited validity) and allows me to explicitly invalidate the cache (in case the last value causes an error I want a "fresh" one). I use this for plain (single) values and for lookups (map) and currently free unused things up manually. Another "problem" (related to memo and Try) is that I need to re-evaluate the function in case of errors which means not memoising "fail" result (or for a much shorter time).
    Of course these are real-world examples and I don't expect a perfect fit in LanguageExt at all, especially as this is full of side-effects. But if there is support by some building blocks, I'd be happy to use them. :-)
    3 replies
    Eddie Stanley
    @flakey-bit

    Thanks @louthy . Curious that I need to convert from/to EitherAsync (i.e. can't just say in EitherAsync the whole time).

    I changed the implementation slightly:

    private static EitherAsync<Seq<TLeft>, (TRight1 Item1, TRight2 Item2)> Collect<TLeft, TRight1, TRight2>(EitherAsync<TLeft, TRight1> ma, EitherAsync<TLeft, TRight2> mb)
    {
        return Go().ToAsync();
        async Task<Either<Seq<TLeft>, (TRight1 Item1, TRight2 Item2)>> Go()
        {
            await Task.WhenAll(ma.ToEither(), mb.ToEither()).ConfigureAwait(false);
            return (ma.Case, mb.Case) switch
                   {
                       (TRight1 x, TRight2 y) => (x, y),
                       (TLeft x, TLeft y) => Seq.create(x, y),
                       (_ ,  TLeft y) => Seq.create(y),
                       (TLeft x, _  ) => Seq.create(x),
                       _          => Seq<TLeft>.Empty
                   };
        }
    }
    2 replies
    Igor Postanogov
    @ipostanogov

    Hi, I'm trying to implement Retry at most N times pattern for handling specific exception type.

    Here is a naive implementaion

                Func<Task<string>> f = async () => await File.ReadAllTextAsync("path maybe IOException");
                var fileText = "error";
                for (var i = 0; i < 3; i++)
                {
                    try
                    {
                        fileText = await f();
                        break;
                    }
                    catch (IOException) { }
                    catch { break; }
                }
                Console.WriteLine(fileText);

    Any recommendations how to implement it using Try?

    2 replies
    Abdelhakim OUBRAHAM
    @abdelhakim94
    Hi, I'm new to the functional programming world and I'm wondering, are features like Record and [With], Map...etc in this library still relevant knowing that C# 9 has records and that System.Collections.Immutable has immutable dictionaries ?
    Stefan Bertels
    @StefanBertels

    @abdelhakim94 Short: yes.
    Longer: If you dive into this library you will see that Nullable even in c# latest is worse than Option and System.Collections.Immutable is worse than LanguageExt types, especially from a FP point of view.
    LanguageExt has a lot more features and is integrated in a way that even single parts can be used they fit perfectly together (obviously this it a design goal). Besides that you get great LINQ support.
    Regarding record the LanguageExt types [Record] and [Union] have more features, to be honest, I didn't have any desire to create a record yet.

    But it depends on your use-case.

    Abdelhakim OUBRAHAM
    @abdelhakim94
    Thank you @StefanBertels for the clarification. Love your work folks by the way.
    Stefan Bertels
    @StefanBertels
    We should give a big thankyou to @louthy at this point ;-)
    1 reply
    Paul Louth
    @louthy

    @abdelhakim94

    Hi, I'm new to the functional programming world and I'm wondering, are features like Record and [With], Map...etc in this library still relevant knowing that C# 9 has records and that System.Collections.Immutable has immutable dictionaries ?

    Records are definitely not needed now that there's first-class support in C# (unless you're stuck on an older version of C# of course). Language-ext records do have structural ordering (Comparable) though, which C# records don't (they're only equatable).

    Union types are something that C# doesn't yet have, so the [Union] code-gen is still valuable. However, you can achieve similar results by inheriting records:

    This:

        public abstract record ExampleUnion;
        public record CaseOne(int X) : ExampleUnion;
        public record CaseTwo(string Y) : ExampleUnion;

    Is almost as good as:

        [Union]
        public interface ExampleUnion
        {
            ExampleUnion CaseOne(int X);
            ExampleUnion CaseTwo(string Y);
        }

    System.Collections.Immutable are very OO in their implementation, and have significantly less features that language-ext immutable collections. language-ext immutable collections are also much faster than System.Collections.Immutable, especially the HashMap, HashSet, and Seq types, which are up to an order of magnitude faster.

    As @StefanBertels points out, the goal is to have a fully integrated ecosystem, where all the types complement each other. You'll have a tougher time if you use System.Collections.Immutable, because it's not 'part of the ecosystem'. Not that it's impossible to work with, it's just a bit more effort.

    Abdelhakim OUBRAHAM
    @abdelhakim94
    Thanks @louthy. I definitely will dive deeper in the library then.