Advertisement
sglienke

Either type

Jan 21st, 2015
234
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. program Either;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. uses
  6.   SysUtils;
  7.  
  8. const
  9.   IsLeft = False;
  10.   IsRight = True;
  11.  
  12. type
  13.   Either<TLeft,TRight> = record
  14.   strict private
  15.     fIsRight: Boolean;
  16.     fLeft: TLeft;
  17.     fRight: TRight;
  18.   public
  19.     constructor FromLeft(const value: TLeft);
  20.     constructor FromRight(const value: TRight);
  21.  
  22.     property Match: Boolean read fIsRight;
  23.     procedure CaseOf(const left: TProc<TLeft>; const right: TProc<TRight>);
  24.  
  25.     property Left: TLeft read fLeft;
  26.     property Right: TRight read fRight;
  27.  
  28.     class operator Implicit(const value: TLeft): Either<TLeft,TRight>;
  29.     class operator Implicit(const value: TRight): Either<TLeft,TRight>;
  30.   end;
  31.  
  32. { Either<TLeft, TRight> }
  33.  
  34. constructor Either<TLeft, TRight>.FromLeft(const value: TLeft);
  35. begin
  36.   fIsRight := False;
  37.   fLeft := value;
  38.   fRight := Default(TRight);
  39. end;
  40.  
  41. constructor Either<TLeft, TRight>.FromRight(const value: TRight);
  42. begin
  43.   fIsRight := True;
  44.   fLeft := Default(TLeft);
  45.   fRight := value;
  46. end;
  47.  
  48. procedure Either<TLeft, TRight>.CaseOf(const left: TProc<TLeft>;
  49.   const right: TProc<TRight>);
  50. begin
  51.   case Match of
  52.     IsLeft: left(fLeft);
  53.     IsRight: right(fRight);
  54.   end;
  55. end;
  56.  
  57. class operator Either<TLeft, TRight>.Implicit(
  58.   const value: TLeft): Either<TLeft, TRight>;
  59. begin
  60.   Result := Either<TLeft,TRight>.FromLeft(value);
  61. end;
  62.  
  63. class operator Either<TLeft, TRight>.Implicit(
  64.   const value: TRight): Either<TLeft, TRight>;
  65. begin
  66.   Result := Either<TLeft,TRight>.FromRight(value);
  67. end;
  68.  
  69. function Divide(x, y: Integer): Either<string,Integer>;
  70. begin
  71.   if y = 0 then
  72.     Result := 'Division by zero!'
  73.   else
  74.     Result := x div y;
  75. end;
  76.  
  77. procedure ShowError(msg: string);
  78. begin
  79.   Writeln('Error: ' + msg);
  80. end;
  81.  
  82. procedure Main;
  83. begin
  84.   with Divide(42, 0) do
  85.     case Match of
  86.       IsLeft: ShowError(Left);
  87.       IsRight: Writeln(Right);
  88.   end;
  89.  
  90.   // or
  91.  
  92.   Divide(42, 0).CaseOf(
  93.     ShowError,
  94.     procedure(i: integer)
  95.     begin
  96.       Writeln(i);
  97.     end);
  98. end;
  99.  
  100. begin
  101.   try
  102.     Main;
  103.   except
  104.     on E: Exception do
  105.       Writeln(E.ClassName, ': ', E.Message);
  106.   end;
  107.   Readln;
  108. end.
Advertisement
RAW Paste Data Copied
Advertisement