Last active
March 14, 2017 21:49
-
-
Save dogwith1eye/95d4f4ba21b6a71d26669fd85629e1e6 to your computer and use it in GitHub Desktop.
Vistor Pattern Rank 2 Types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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