Skip to content

Instantly share code, notes, and snippets.

@dogwith1eye
Last active March 17, 2017 01:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dogwith1eye/b0d76285324e065de934c94e9b838aab to your computer and use it in GitHub Desktop.
Save dogwith1eye/b0d76285324e065de934c94e9b838aab to your computer and use it in GitHub Desktop.
Visitor Pattern Rank 2 Types
using System;
namespace HigherRankC
{
abstract class TypeWrapper<T>
{
public TypeWrapper(T value)
{
this.Value = value;
}
public T Value { get; }
public abstract U Accept<U>(IVisitor<T, U> visitor);
}
interface IVisitor<T, U>
{
U Visit(T t);
}
interface IShowable<T>
{
T Value { get; }
U Accept<U>(IVisitor<T, U> visitor);
}
class StringWrapper : TypeWrapper<string>, IShowable<string>
{
public StringWrapper(string value) : base(value) { }
public interface IStringVisitor<U> : IVisitor<string, U> { }
public U Accept<U>(IStringVisitor<U> visitor)
{
return visitor.Visit(this.Value);
}
public override U Accept<U>(IVisitor<string, U> visitor)
{
return visitor.Visit(this.Value);
}
}
class IntWrapper : TypeWrapper<int>, IShowable<int>, IRoundable<int>
{
public IntWrapper(int value) : base(value) { }
public interface IIntVisitor<U> : IVisitor<int, U> { }
public U Accept<U>(IIntVisitor<U> visitor)
{
return visitor.Visit(this.Value);
}
public override U Accept<U>(IVisitor<int, U> visitor)
{
return visitor.Visit(this.Value);
}
}
class FloatWrapper : TypeWrapper<float>, IShowable<float>, IRoundable<float>
{
public FloatWrapper(float value) : base(value) { }
public interface IFloatVisitor<U> : IVisitor<float, U> { }
public U Accept<U>(IFloatVisitor<U> visitor)
{
return visitor.Visit(this.Value);
}
public override U Accept<U>(IVisitor<float, U> visitor)
{
return visitor.Visit(this.Value);
}
}
class ShowVisitor : StringWrapper.IStringVisitor<string>,
IVisitor<string, string>,
IntWrapper.IIntVisitor<string>,
IVisitor<int, string>,
FloatWrapper.IFloatVisitor<string>
{
public string Visit(string t)
{
return t;
}
public string Visit(int t)
{
return t.ToString();
}
public string Visit(float t)
{
return t.ToString();
}
public string Show<T>(IShowable<T> showable)
{
return showable.Accept(this as IVisitor<T, string>);
}
}
interface IRoundable<T>
{
T Value { get; }
U Accept<U>(IVisitor<T, U> visitor);
}
class RoundVisitor : IntWrapper.IIntVisitor<int>,
IVisitor<int, int>,
FloatWrapper.IFloatVisitor<int>,
IVisitor<float, int>
{
public int Visit(int t)
{
return t;
}
public int Visit(float f)
{
return (int)Math.Round(f);
}
public int Round<T>(IRoundable<T> roundable)
{
return roundable.Accept(this as IVisitor<T, int>);
}
}
static class Prelude
{
// show :: forall a. (IShowable a) => a -> string
public static string Show<T>(IShowable<T> t)
{
var show = new ShowVisitor();
return t.Accept(show as IVisitor<T, string>);
}
// show :: forall a. (IRoundable a) => a -> int
public static int Round<T>(IRoundable<T> t)
{
var round = new RoundVisitor();
return t.Accept(round as IVisitor<T, int>);
}
// accept :: forall b. (forall a. (IIntVisitor a) => a) -> b
public static U Accept<U>(IntWrapper.IIntVisitor<U> v)
{
var i = new IntWrapper(1);
return i.Accept(v);
}
}
class Program
{
static void Main(string[] args)
{
var s = new StringWrapper("foo");
var i = new IntWrapper(1);
var f = new FloatWrapper(5.5f);
var show = new ShowVisitor();
var round = new RoundVisitor();
// accept :: forall b. (forall a. IStringVisitor a => a) -> b
var r1 = s.Accept(show);
//var r4 = s.Accept(round);
var r11 = show.Show(s);
var r111 = Prelude.Show(s);
//var r44 = round.Round(s);
//var r444 = Prelude.Round(s);
// accept :: forall b. (forall a. IIntVisitor a => a) -> b
var r2 = i.Accept(show);
var r5 = i.Accept(round);
var r22 = show.Show(i);
var r222 = Prelude.Show(i);
var r55 = round.Round(i);
var r555 = Prelude.Round(i);
// accept :: forall b. (forall a. IFloatVisitor a => a) -> b
var r3 = f.Accept(show);
var r6 = f.Accept(round);
var r33 = show.Show(f);
var r333 = Prelude.Show(f);
var r66 = round.Round(f);
var r666 = Prelude.Round(f);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment