Skip to content

Instantly share code, notes, and snippets.

@masaeedu
Created July 3, 2018 15:34
Show Gist options
  • Save masaeedu/0c52dacfaf0a3154740910c17eabb1dc to your computer and use it in GitHub Desktop.
Save masaeedu/0c52dacfaf0a3154740910c17eabb1dc to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace FPUtils
{
using static EnumerableUtils;
using static DictUtils;
using static TaskUtils;
public static class TaskUtils
{
// Monad
public static Task<A> Pure<A>(A a)
=> Task.FromResult(a);
public static async Task<B> Bind<A, B>(this Task<A> a, Func<A, Task<B>> f)
=> await f(await a);
public static Task<B> Map<A, B>(this Task<A> a, Func<A, B> f)
=> a.Bind(x => Pure(f(x)));
public static Task<C> Lift2<A, B, C>(Func<A, B, C> f, Task<A> fa, Task<B> fb)
=> fa.Bind(a => fb.Map(b => f(a, b)));
public static Task<B> Ap<A, B>(this Task<Func<A, B>> af, Task<A> av)
=> Lift2((f, v) => f(v), af, av);
}
public static class EnumerableUtils
{
// Misc
public static bool HasDuplicatesBy<X, K>(Func<X, K> f, IEnumerable<X> a)
=> a.Map(f).Distinct().Count() != a.Count();
// Monoid
public static IEnumerable<A> Empty<A>(A a)
=> new A[] { };
public static IEnumerable<A> Append<A>(IEnumerable<A> a, IEnumerable<A> b)
=> a.Concat(b);
// Monad
public static IEnumerable<A> Pure<A>(A a)
=> new[] { a };
public static IEnumerable<B> Bind<A, B>(this IEnumerable<A> a, Func<A, IEnumerable<B>> f)
=> a.SelectMany(f);
public static IEnumerable<B> Map<A, B>(this IEnumerable<A> a, Func<A, B> f)
=> a.Select(f);
public static IEnumerable<C> Lift2<A, B, C>(Func<A, B, C> f, IEnumerable<A> fa, IEnumerable<B> fb)
=> fa.Bind(a => fb.Map(b => f(a, b)));
public static IEnumerable<B> Ap<A, B>(this IEnumerable<Func<A, B>> af, IEnumerable<A> av)
=> Lift2((f, v) => f(v), af, av);
// Foldable
public static B Fold<A, B>(this IEnumerable<A> xs, B z, Func<B, A, B> f)
=> xs.Aggregate(z, f);
}
public static class DictUtils
{
// Misc
public static IReadOnlyDictionary<K, V> Insert<K, V>(K k, V v)
=> new Dictionary<K, V>() { [k] = v };
// Monoid
public static IReadOnlyDictionary<K, V> Empty<K, V>()
=> new Dictionary<K, V>();
public static IReadOnlyDictionary<K, V> Append<K, V>(IReadOnlyDictionary<K, V> x, IReadOnlyDictionary<K, V> y)
=> x.Concat(y).ToDictionary(d => d.Key, d => d.Value);
// Traversable
public static IEnumerable<IReadOnlyDictionary<K, V>> Sequence<K, V>(IReadOnlyDictionary<K, IEnumerable<V>> dict)
=> dict.Keys
.Map(k => dict[k].Map(v => Insert(k, v)))
.Fold(EnumerableUtils.Pure(Empty<K, V>()), (e1, e2) => Lift2(Append, e1, e2));
public static Task<IReadOnlyDictionary<K, V>> Sequence<K, V>(IReadOnlyDictionary<K, Task<V>> dict)
=> dict.Keys
.Map(k => dict[k].Map(v => Insert(k, v)))
.Fold(TaskUtils.Pure(Empty<K, V>()), (e1, e2) => Lift2(Append, e1, e2));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment