Last active
August 29, 2015 14:08
-
-
Save m1el/95056d95ceecd4572892 to your computer and use it in GitHub Desktop.
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
// FizzBuzz in pure lambda notation | |
// transcribed from http://codon.com/programming-with-nothing | |
// props to http://community.bartdesmet.net/blogs/bart/archive/2009/08/17/mis-using-c-4-0-dynamic-type-free-lambda-calculus-church-numerals-and-more.aspx | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace ConsoleApplication1 | |
{ | |
using Fn = Func<dynamic, dynamic>; | |
class Program | |
{ | |
static int to_int(Fn fn) | |
{ | |
return fn(new Fn(x => x + 1))(0); | |
} | |
static bool to_bool(dynamic fn) | |
{ | |
return fn(true)(false); | |
} | |
static List<object> to_list(Fn fn) | |
{ | |
var list = new List<object>(); | |
var LEFT = new Fn(p => p(new Fn(x => new Fn(y => x)))); | |
var RIGHT = new Fn(p => p(new Fn(x => new Fn(y => y)))); | |
var FIRST = new Fn(l => LEFT(RIGHT(l))); | |
var REST = new Fn(l => RIGHT(RIGHT(l))); | |
while (!to_bool(LEFT(fn))) | |
{ | |
list.Add(FIRST(fn)); | |
fn = REST(fn); | |
} | |
return list; | |
} | |
static string to_string(Fn fn) | |
{ | |
var str = ""; | |
var alpha = "0123456789BFiuz"; | |
foreach (var c in to_list(fn)) | |
{ | |
str += alpha[to_int((Fn)c)]; | |
} | |
return str; | |
} | |
static void Main(string[] args) | |
{ | |
var ZERO = new Fn(f => new Fn(x => x)); | |
var ONE = new Fn(f => new Fn(x => f(x))); | |
var TWO = new Fn(f => new Fn(x => f(f(x)))); | |
var THREE = new Fn(f => new Fn(x => f(f(f(x))))); | |
var FOUR = new Fn(f => new Fn(x => f(f(f(f(x)))))); | |
var FIVE = new Fn(f => new Fn(x => f(f(f(f(f(x))))))); | |
var INC = new Fn(n => new Fn(p => new Fn(x => p(n(p)(x))))); | |
var DEC = new Fn(n => new Fn(f => new Fn(x => n(new Fn(g => new Fn(h => h(g(f)))))(new Fn(u => x))(new Fn(u => u))))); | |
var PLUS = new Fn(m => new Fn(n => new Fn(f => new Fn(x => m(f)(n(f)(x)))))); | |
var MINUS = new Fn(m => new Fn(n => n(DEC)(m))); | |
var MUL = new Fn(m => new Fn(n => new Fn(f => n(m(f))))); | |
var POW = new Fn(m => new Fn(n => n(m))); | |
var FIFTEEN = MUL(FIVE)(THREE); | |
var HUNDRED = MUL(MUL(FIVE)(FIVE))(FOUR); | |
var FALSE = new Fn(a => new Fn(b => b)); | |
var TRUE = new Fn(a => new Fn(b => a)); | |
var IF = new Fn(b => new Fn(x => new Fn(y => b(x)(y)))); | |
var IS_ZERO = new Fn(n => n(new Fn(x => FALSE))(TRUE)); | |
var LEQ = new Fn(m => new Fn(n => IS_ZERO(MINUS(m)(n)))); | |
var Z = new Fn(f => new Fn(x => f(new Fn(y => x(x)(y)))) | |
(new Fn(x => f(new Fn(y => x(x)(y)))))); | |
var MOD = Z(new Fn(f => new Fn(m => new Fn(n => | |
IF(LEQ(n)(m)) | |
(new Fn(x => f(MINUS(m)(n))(n)(x))) | |
(m))))); | |
var PAIR = new Fn(x => new Fn(y => new Fn(f => f(x)(y)))); | |
var LEFT = new Fn(p => p(new Fn(x => new Fn(y => x)))); | |
var RIGHT = new Fn(p => p(new Fn(x => new Fn(y => y)))); | |
var EMPTY = PAIR(TRUE)(TRUE); | |
var UNSHIFT = new Fn(l => new Fn(x => PAIR(FALSE)(PAIR(x)(l)))); | |
var IS_EMPTY = LEFT; | |
var FIRST = new Fn(l => LEFT(RIGHT(l))); | |
var REST = new Fn(l => RIGHT(RIGHT(l))); | |
var RANGE = | |
Z(new Fn(f => new Fn(m => new Fn(n => | |
IF(LEQ(m)(n)) | |
(new Fn(x => UNSHIFT(f(INC(m))(n))(m)(x))) | |
(EMPTY) | |
)))); | |
var FOLD = | |
Z(new Fn(f => new Fn(l => new Fn(x => new Fn(g => | |
IF(IS_EMPTY(l)) | |
(x) | |
(new Fn(y => | |
g(f(REST(l))(x)(g))(FIRST(l))(y)))))))); | |
var MAP = | |
new Fn(k => new Fn(f => | |
FOLD(k)(EMPTY) | |
(new Fn(l => new Fn(x => UNSHIFT(l)(f(x))))))); | |
var TEN = MUL(TWO)(FIVE); | |
var B = TEN; | |
var F = INC(B); | |
var I = INC(F); | |
var U = INC(I); | |
var ZED = INC(U); | |
var FIZZ = UNSHIFT(UNSHIFT(UNSHIFT(UNSHIFT(EMPTY)(ZED))(ZED))(I))(F); | |
var BUZZ = UNSHIFT(UNSHIFT(UNSHIFT(UNSHIFT(EMPTY)(ZED))(ZED))(U))(B); | |
var FIZZBUZZ = UNSHIFT(UNSHIFT(UNSHIFT(UNSHIFT(BUZZ)(ZED))(ZED))(I))(F); | |
var DIV = Z(new Fn(f => new Fn(m => new Fn(n => | |
IF(LEQ(n)(m)) | |
(new Fn(x => INC(f(MINUS(m)(n))(n))(x))) | |
(ZERO))))); | |
var PUSH = | |
new Fn(l => new Fn(x => | |
FOLD(l)(UNSHIFT(EMPTY)(x))(UNSHIFT))); | |
var TO_DIGITS = | |
Z(new Fn(f => new Fn(n => | |
PUSH( | |
IF(LEQ(n)(DEC(TEN))) | |
(EMPTY) | |
(new Fn(x => f(DIV(n)(TEN))(x))) | |
)(MOD(n)(TEN))))); | |
var result = MAP(RANGE(ONE)(HUNDRED))(new Fn(n => | |
IF(IS_ZERO(MOD(n)(FIFTEEN))) | |
(FIZZBUZZ) | |
(IF(IS_ZERO(MOD(n)(THREE))) | |
(FIZZ) | |
(IF(IS_ZERO(MOD(n)(FIVE))) | |
(BUZZ) | |
(TO_DIGITS(n)))) | |
)); | |
foreach (var row in to_list(result)) | |
{ | |
Console.WriteLine(to_string((Fn)row)); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment