Skip to content

Instantly share code, notes, and snippets.

@Luiz-Monad
Last active December 5, 2016 23:53
Show Gist options
  • Save Luiz-Monad/fc3720151cc823c135e7b89875068b0d to your computer and use it in GitHub Desktop.
Save Luiz-Monad/fc3720151cc823c135e7b89875068b0d to your computer and use it in GitHub Desktop.
A Profunctor is just a bifunctor that is contravariant in the first argument and covariant in the second. What's the problem?
//https://ocharles.org.uk/blog/guest-posts/2013-12-22-24-days-of-hackage-profunctors.html
//http://blog.sigfpe.com/2011/07/profunctors-in-haskell.html
//https://www.schoolofhaskell.com/school/to-infinity-and-beyond/pick-of-the-week/profunctors
public interface Variant { }
public interface CoVariant { }
public interface Profunctor<P>
{
P p { get; }
}
public interface Profunctor<P, S> : Profunctor<P> { }
public interface Profunctor<P, out A, in B, co> : Profunctor<P, CoVariant> { }
public delegate O Func<in I, out O>(I arg);
public delegate I CoFunc<out I, in O>(O arg);
//class Profunctor p where
public interface Profunctor<P, in A, out B> : Profunctor<P, Variant>
{
//lmap :: (c -> a) -> p a b -> p c b
Profunctor<P, C, B> lmap<C>(Func<C, A> h, Profunctor<P, A, B, CoVariant> g);
//rmap :: (b -> d) -> p a b -> p a d
Profunctor<P, A, D> rmap<D>(Func<B, D> f, Profunctor<P, A, B, CoVariant> g);
//dimap :: (c -> a) -> (b -> d) -> p a b -> p c d
Profunctor<P, C, D> dimap<C, D>(Func<C, A> h, Func<B, D> f, Profunctor<P, A, B, CoVariant> g);
}
public abstract class Arrow
{
private Delegate f; //This is where the type system fails us
public Arrow(Delegate f) { this.f = f; }
public Func<I, O> fn<I, O>() { return (Func<I, O>)f; }
}
//instance Profunctor (->) where
public class Arrow<I, O> : Arrow, Profunctor<Arrow, I, O>
{
public Arrow(Func<I, O> fn) : base(fn) { }
public Arrow p
{
get { return this; }
}
private static Func<x, y> Y<x, y>(Func<x, y> t) { return t; }
//lmap h g = g . h
public Profunctor<Arrow, C, O> lmap<C>(Func<C, I> h, Profunctor<Arrow, I, O, CoVariant> g)
{
var fg = g.p.fn<I, O>();
var l = Y((C c) => fg(h(c)));
return new Arrow<C, O>(l);
}
//rmap f g = f . g
public Profunctor<Arrow, I, D> rmap<D>(Func<O, D> f, Profunctor<Arrow, I, O, CoVariant> g)
{
var fg = g.p.fn<I, O>();
var l = Y((I i) => f(fg(i)));
return new Arrow<I, D>(l);
}
//dimap h f g = f . g . h
public Profunctor<Arrow, C, D> dimap<C, D>(Func<C, I> h, Func<O, D> f, Profunctor<Arrow, I, O, CoVariant> g)
{
var fg = g.p.fn<I, O>();
var l = Y((C c) => f(fg(h(c))));
return new Arrow<C, D>(l);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment