Skip to content

Instantly share code, notes, and snippets.

@zonaryFUND
Created January 26, 2019 09:20
Show Gist options
  • Save zonaryFUND/ef24a0a996cb616e7deb99b5bc96b95b to your computer and use it in GitHub Desktop.
Save zonaryFUND/ef24a0a996cb616e7deb99b5bc96b95b to your computer and use it in GitHub Desktop.
using System;
namespace Monad.Extensions
{
public interface ContState<TState, TValue> : Cont<Unit, State<TState, TValue>> { }
internal readonly struct PureContState<TState, TValue> : ContState<TState, TValue>
{
readonly Func<Func<State<TState, TValue>, Unit>, Unit> function;
internal PureContState(Func<Func<State<TState, TValue>, Unit>, Unit> function) => this.function = function;
public Unit Run(Func<State<TState, TValue>, Unit> observer)
{
return function(observer);
}
}
public static partial class ContState
{
public static ContState<TState, TValue> Pure<TState, TValue>(Func<Func<State<TState, TValue>, Unit>, Unit> function)
=> new PureContState<TState, TValue>(function);
public static ContState<TState, TValue> Lift<TState, TValue>(this Cont<Unit, TValue> cont)
=> Pure<TState, TValue>(observer => cont.Run(value => observer(State.Return<TState, TValue>(value))));
public static ContState<TState, TValue> Lift<TState, TValue>(this State<TState, TValue> state)
=> Pure<TState, TValue>(observer => observer(state));
public static ContState<TState, TValue> GetSelect<TState, TValue>(Func<TState, Cont<Unit, TValue>> generator)
=>
from state in State.Get<TState>().Lift()
from value in generator(state).Lift<TState, TValue>()
select value;
public static ContState<TState, TSelectedValue> Select<TState, TSourceValue, TSelectedValue>(this ContState<TState, TSourceValue> source, Func<TSourceValue, TSelectedValue> selector)
=> Pure<TState, TSelectedValue>(observer => source.Run(state => observer(state.Select(selector))));
public static ContState<TState, TSelectedValue> SelectMany<TState, TSourceValue, TSelectedValue>(
this ContState<TState, TSourceValue> source,
Func<TSourceValue, ContState<TState, TSelectedValue>> selector)
=> Pure<TState, TSelectedValue>(observer => source.SelectMany(sourceValue => selector(sourceValue)).Run(observer));
public static ContState<TState, TProjectedValue> SelectMany<TState, TSourceValue, TSelectedValue, TProjectedValue>(
this ContState<TState, TSourceValue> source,
Func<TSourceValue, ContState<TState, TSelectedValue>> selector,
Func<TSourceValue, TSelectedValue, TProjectedValue> projector)
=> Pure<TState, TProjectedValue>(observer => source.SelectMany(sourceValue => selector(sourceValue), projector).Run(observer));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment