Skip to content

Instantly share code, notes, and snippets.

@dogwith1eye
Last active March 14, 2017 21:49
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/95d4f4ba21b6a71d26669fd85629e1e6 to your computer and use it in GitHub Desktop.
Save dogwith1eye/95d4f4ba21b6a71d26669fd85629e1e6 to your computer and use it in GitHub Desktop.
Vistor Pattern Rank 2 Types
using System;
namespace ConsoleApp1
{
abstract class TypeWrapper<T>
{
public TypeWrapper(T value) {
this.Value = value;
}
public T Value { get; }
}
class StringWrapper : TypeWrapper<string>
{
public StringWrapper(string value) : base(value) {}
public interface IStringVisitor<T>
{
T Visit(StringWrapper w);
}
public U Accept<U>(IStringVisitor<U> visitor) {
return visitor.Visit(this);
}
}
class IntWrapper : TypeWrapper<int>
{
public IntWrapper(int value) : base(value) { }
public interface IIntVisitor<T>
{
T Visit(IntWrapper w);
}
public U Accept<U>(IIntVisitor<U> visitor) {
return visitor.Visit(this);
}
}
class FloatWrapper : TypeWrapper<float>
{
public FloatWrapper(float value) : base(value) { }
public interface IFloatVisitor<T>
{
T Visit(FloatWrapper w);
}
public U Accept<U>(IFloatVisitor<U> visitor) {
return visitor.Visit(this);
}
}
class ShowVisitor : StringWrapper.IStringVisitor<string>,
IntWrapper.IIntVisitor<string>,
FloatWrapper.IFloatVisitor<string>
{
public string Visit(StringWrapper t) {
return t.Value;
}
public string Visit(IntWrapper t) {
return t.Value.ToString();
}
public string Visit(FloatWrapper t) {
return t.Value.ToString();
}
}
class NumVisitor : IntWrapper.IIntVisitor<IntWrapper>,
FloatWrapper.IFloatVisitor<IntWrapper>
{
public IntWrapper Visit(IntWrapper w) {
return w;
}
public IntWrapper Visit(FloatWrapper w) {
return new IntWrapper((int)w.Value);
}
}
static class Prelude
{
public static string show(dynamic t) {
var show = new ShowVisitor();
return t.Accept(show);
}
public static string num(dynamic t) {
var num = new NumVisitor();
return t.Accept(num);
}
}
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();
// accept::forall a. IStringVisitor a -> a
var r1 = s.Accept(show);
// accept::forall a. IIntVisitor a -> a
var r2 = i.Accept(show);
// accept::forall a. IFloatVisitor a -> a
var r3 = f.Accept(show);
var num = new NumVisitor();
// accept::forall a. IStringVisitor a -> a
// var r4 = s.Accept(num);
// accept::forall a. IIntVisitor a -> a
var r5 = i.Accept(num);
// accept::forall a. IFloatVisitor a -> a
var r6 = f.Accept(num);
Console.WriteLine("r1:{0} r2:{1} r3:{2}", r1, r2, r3);
Console.WriteLine("r5:{0} r6:{1}", r5.Accept(show), r6.Accept(show));
Console.WriteLine("r5:{0} r6:{1}", Prelude.show(r5), Prelude.show(r6));
// this fails at runtime
// Prelude.num(s);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment