<commit_before>﻿using System;
using LanguageExt;
using LanguageExt.Common;
using static LanguageExt.Prelude;
using LanguageExt.ClassInstances;
using LanguageExt.TypeClasses;
using System.Diagnostics.Contracts;
using System.Collections.Generic;

/// <summary>
/// Extension methods for RWS
/// </summary>
public static class RWSExtensions
{
    /// <summary>
    /// Monadic join
    /// </summary>
    [Pure]
    public static RWS<MonoidW, R, W, S, A> Flatten<MonoidW, R, W, S, A>(this RWS<MonoidW, R, W, S, RWS<MonoidW, R, W, S, A>> ma)
        where MonoidW : struct, Monoid<W> =>
        ma.Bind(identity);

    /// <summary>
    /// Runs the RWS monad and memoizes the result in a TryOption monad.  Use
    /// Match, IfSucc, IfNone, etc to extract.
    /// </summary>
    public static (TryOption<A> Value, W Output, S State) Run<MonoidW, R, W, S, A>(this RWS<MonoidW, R, W, S, A> self, R env, S state)
        where MonoidW : struct, Monoid<W>
    {
        try
        {
            if (self == null) return (() => Option<A>.None, default(MonoidW).Empty(), state);
            if (state == null) return (() => Option<A>.None, default(MonoidW).Empty(), state);
            var res = self(env, state);
            if (res.IsFaulted)
            {
                return (() => Option<A>.None, res.Output, state);
            }
            else
            {
                return (() => Optional(res.Value), res.Output, res.State);
            }
        }
        catch (Exception e)
        {
            return (() => new OptionalResult<A>(e), default(MonoidW).Empty(), state);
        }
    }

    [Pure]
    public static RWS<MonoidW, R, W, S, int> Sum<MonoidW, R, W, S>(this RWS<MonoidW, R, W, S, int> self)
        where MonoidW : struct, Monoid<W> => self;

    [Pure]
    public static RWS<MonoidW, R, W, S, Seq<A>> ToSeq<MonoidW, R, W, S, A>(this RWS<MonoidW, R, W, S, A> self)
       where MonoidW : struct, Monoid<W> => self.Map(x => x.Cons());

    [Pure]
    public static RWS<MonoidW, R, W, S, Seq<A>> AsEnumerable<MonoidW, R, W, S, A>(this RWS<MonoidW, R, W, S, A> self)
       where MonoidW : struct, Monoid<W> => ToSeq(self);

    [Pure]
    public static Seq<A> ToSeq<MonoidW, R, W, S, A>(this RWS<MonoidW, R, W, S, A> self, R env, S state)
       where MonoidW : struct, Monoid<W>
    {
        IEnumerable<A> Yield()
        {
            var res = self(env, state);
            if (!res.IsFaulted)
            {
                yield return res.Value;
            }<commit_msg>Bug fix: RWS.Run should return RWSResult<commit_after>﻿using System;
using LanguageExt;
using LanguageExt.Common;
using static LanguageExt.Prelude;
using LanguageExt.ClassInstances;
using LanguageExt.TypeClasses;
using System.Diagnostics.Contracts;
using System.Collections.Generic;

/// <summary>
/// Extension methods for RWS
/// </summary>
public static class RWSExtensions
{
    /// <summary>
    /// Monadic join
    /// </summary>
    [Pure]
    public static RWS<MonoidW, R, W, S, A> Flatten<MonoidW, R, W, S, A>(this RWS<MonoidW, R, W, S, RWS<MonoidW, R, W, S, A>> ma)
        where MonoidW : struct, Monoid<W> =>
        ma.Bind(identity);

    /// <summary>
    /// Runs the RWS monad and memoizes the result in a TryOption monad.  Use
    /// Match, IfSucc, IfNone, etc to extract.
    /// </summary>
    public static RWSResult<MonoidW, R, W, S, A> Run<MonoidW, R, W, S, A>(this RWS<MonoidW, R, W, S, A> self, R env, S state)
        where MonoidW : struct, Monoid<W>
    {
        if (self == null) throw new ArgumentNullException(nameof(self));
        if (state == null) throw new ArgumentNullException(nameof(state));
        try
        {
            return self(env, state);
        }
        catch (Exception e)
        {
            return RWSResult<MonoidW, R, W, S, A>.New(state, Error.New(e));
        }
    }

    [Pure]
    public static RWS<MonoidW, R, W, S, int> Sum<MonoidW, R, W, S>(this RWS<MonoidW, R, W, S, int> self)
        where MonoidW : struct, Monoid<W> => self;

    [Pure]
    public static RWS<MonoidW, R, W, S, Seq<A>> ToSeq<MonoidW, R, W, S, A>(this RWS<MonoidW, R, W, S, A> self)
       where MonoidW : struct, Monoid<W> => self.Map(x => x.Cons());

    [Pure]
    public static RWS<MonoidW, R, W, S, Seq<A>> AsEnumerable<MonoidW, R, W, S, A>(this RWS<MonoidW, R, W, S, A> self)
       where MonoidW : struct, Monoid<W> => ToSeq(self);

    [Pure]
    public static Seq<A> ToSeq<MonoidW, R, W, S, A>(this RWS<MonoidW, R, W, S, A> self, R env, S state)
       where MonoidW : struct, Monoid<W>
    {
        IEnumerable<A> Yield()
        {
            var res = self(env, state);
            if (!res.IsFaulted)
            {
                yield return res.Value;
            }
{'fraction_non_alphanumeric': 0.14998942246668076, 'fraction_numerical': 0.0, 'mean_word_length': 2.3202247191011236, 'pattern_counts': {'":': 0, '<': 76, '<?xml version=': 0, '>': 91, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5556012', 'n_tokens_mistral': 1698, 'n_tokens_neox': 1681, 'n_words': 494}