OK, turing.

<- leave blank

Thu Jul 12 00:36:47 EDT 2018

use std

trait bindable @t -> @a, @b =
	bind : (b : @t, f : (a : @a -> @b) -> @b)
;;

trait bindable1 @a -> @f, @b =
	bind1 : (a : @a, f : @f -> @b)
;;

trait bindable2 @a -> @f =
	bind2 : (a : @a, f : @f -> @a)
;;

impl bindable std.option(@a) -> @a, std.option(@b) =
	bind = {o, f
		match o
		| `std.Some v: -> f(v)
		| `std.None: -> `std.None
		;;
	}
;;

impl bindable1 std.option(@a) -> (a : @a -> std.option(@b)), std.option(@b)
=
	bind1 = {o, f
		match o
		| `std.Some v: -> f(v)
		| `std.None: -> `std.None
		;;
	}
;;

impl bindable2 std.option(@a) -> (a : @a -> std.option(@a)) =
	bind2 = {o, f
		match o
		| `std.Some v: -> f(v)
		| `std.None: -> `std.None
		;;
	}
;;

generic bind3 = {o, f
	match o
	| `std.Some v: -> f(v)
	| `std.None: -> `std.None
	;;
}

const gets = {n
	if n == 0
		-> `std.Some "hello"
	;;
	-> `std.None
}

const append = {s
	if s.len < 16
		-> `std.Some std.strcat(s, " world")
	;;
	-> `std.None
}

const put = {o
	match o
	| `std.Some s: std.put("{}\n", s)
	| `std.None:
	;;
}

const main = {
	// put(bind(gets(std.rand(0, 1)), append))
	// put(bind1(gets(std.rand(0, 1)), append))
	// put(bind2(gets(std.rand(0, 1)), append))
	put(bind3(gets(std.rand(0, 1)), append))
	put(bind3(bind3(gets(std.rand(0, 1)), append), append))
	put(bind3(bind3(bind3(gets(std.rand(0, 1)), append), append), append))
}