Last active
October 16, 2024 08:40
-
-
Save ClarkeRemy/fcda36f82310adde6a530d5c861f811c to your computer and use it in GitHub Desktop.
Dictionary Passing style
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
structure Plus = struct | |
datatype 'a t = T of 'a -> 'a -> 'a | |
end | |
structure Mul = struct | |
datatype 'a t = T of 'a -> 'a -> 'a | |
end | |
structure FromInt = struct | |
datatype 'a t = T of int -> 'a | |
end | |
fun uses_dict (Plus.T plus, Mul.T mul, FromInt.T from_num) = | |
let val z = from_num 15 | |
fun compiled x y = mul (plus x y) z | |
in compiled end | |
fun uses_dict2 (Plus.T plus, FromInt.T fromInt) = | |
let val z = fromInt 15 | |
fun compiled x = plus x z | |
in compiled end | |
fun uses_dict3 (plus, mul, fromNum as FromInt.T frN) = | |
let | |
val f = uses_dict (plus, mul, fromNum) | |
val g = uses_dict2 (plus, fromNum) | |
val z = frN 5 | |
fun compiled x = f (g x) z | |
in | |
compiled | |
end | |
local fun curry f x y = f(x,y) in | |
structure Int_ = | |
struct | |
val plus = Plus.T (curry Int.+) | |
val mul = Mul.T (curry Int.*) | |
val fromInt = FromInt.T (fn x => x) | |
end | |
structure Real_ = | |
struct | |
val plus = Plus.T (curry Real.+) | |
val mul = Mul.T (curry Real.*) | |
val fromInt = FromInt.T Real.fromInt | |
end | |
end | |
local open Int_ in | |
val _ = uses_dict (plus, mul, fromInt) 5 6 | |
val _ = uses_dict2 (plus, fromInt) 5 | |
end | |
local open Real_ in | |
val _ = uses_dict (plus, mul, fromInt) 5.0 6.0 | |
val _ = uses_dict2 (plus, fromInt) 5.0 | |
end |
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
// //////////////////////////////////// | |
// These structs constrain the types // | |
// //////////////////////////////////// | |
struct Plus<T>(fn(T,T)->T); | |
impl<T> Clone for Plus<T> { fn clone(&self) -> Self {Self(self.0)} } | |
impl<T> Copy for Plus<T> {} | |
struct Mul<T>(fn(T,T)->T); | |
impl<T> Clone for Mul<T> { fn clone(&self) -> Self {Self(self.0)} } | |
impl<T> Copy for Mul<T> {} | |
struct FromInt<T>(fn(i32)->T); | |
impl<T> Clone for FromInt<T> { fn clone(&self) -> Self {Self(self.0)} } | |
impl<T> Copy for FromInt<T> {} | |
struct Dup<T>(fn(&T)->T); | |
impl<T> Clone for Dup<T> { fn clone(&self) -> Self {Self(self.0)} } | |
impl<T> Copy for Dup<T> {} | |
// //////////////////////////////////////// | |
// passing the dictionary with arguments // | |
// //////////////////////////////////////// | |
fn uses_dict<T>( | |
(Plus(plus), Mul(mul), FromInt(from_int)): (Plus<T>, Mul<T>, FromInt<T>), | |
x :T, | |
y:T | |
)->T { | |
mul(plus(x,y), from_int(15)) | |
} | |
fn uses_dict2<T>( | |
(Plus(plus), FromInt(from_int)): (Plus<T>, FromInt<T>), | |
x : T | |
)->T{ | |
plus(x, from_int(15)) | |
} | |
fn uses_dict3<T>( | |
dict @ (p, m, fi @ FromInt(from_int)): (Plus<T>, Mul<T>, FromInt<T>), | |
x : T | |
)->T { | |
uses_dict(dict, uses_dict2((p,fi), x), from_int(5)) | |
} | |
// ////////////////////////////////////////// | |
// partially evaluate the function eagerly // | |
// ////////////////////////////////////////// | |
fn uses_dict_<T>( | |
(Plus(plus), Mul(mul), FromInt(from_int), Dup(dup)): (Plus<T>, Mul<T>, FromInt<T>, Dup<T>), | |
)-> impl Fn(T,T)->T { | |
let z = from_int(15); | |
move |x,y| mul(plus(x,y), dup(&z)) | |
} | |
fn uses_dict2_<T>( | |
(Plus(plus), FromInt(from_int), Dup(dup)): (Plus<T>, FromInt<T>, Dup<T>), | |
)->impl Fn(T)->T{ | |
let z = from_int(15); | |
move|x|plus(x, dup(&z)) | |
} | |
fn uses_dict3_<T>( | |
dict @ (p, m, fi @ FromInt(from_int), d @ Dup(dup)): (Plus<T>, Mul<T>, FromInt<T>, Dup<T>), | |
)->impl Fn(T) -> T { | |
let z = from_int(5); | |
let f = uses_dict_(dict); | |
let g = uses_dict2_((p,fi,d)); | |
move|x| f( g(x), dup(&z)) | |
} | |
#[allow(non_upper_case_globals)] | |
mod i32_ { | |
use crate::{Plus, Mul, FromInt, Dup}; | |
pub const plus : Plus<i32> = Plus(|x,y| x + y); | |
pub const mul : Mul<i32> = Mul(|x,y| x * y); | |
pub const from_int : FromInt<i32> = FromInt(|x| x); | |
pub const dup : Dup<i32> = Dup(|x| *x); | |
} | |
#[allow(non_upper_case_globals)] | |
mod f64_ { | |
use crate::{Plus, Mul, FromInt, Dup}; | |
pub const plus : Plus<f64> = Plus(|x,y| x + y); | |
pub const mul : Mul<f64> = Mul(|x,y| x * y); | |
pub const from_int : FromInt<f64> = FromInt(f64::from); | |
pub const dup : Dup<f64> = Dup(|x| *x); | |
} | |
#[allow(non_upper_case_globals)] | |
mod string_ { | |
use crate::{Plus, FromInt, Dup}; | |
pub const plus : Plus<String> = Plus(|x,y| x+&y); | |
pub const from_int : FromInt<String> = FromInt(|x|i32::to_string(&x)); | |
pub const dup : Dup<String> = Dup(|x| x.clone()); | |
} | |
fn use_generics() { | |
'int : { | |
use i32_::*; | |
// run with dict | |
let _ = uses_dict((plus,mul,from_int), 5, 6); | |
let _ = uses_dict2((plus, from_int), 5); | |
let _ = uses_dict3((plus,mul,from_int), 5); | |
// partial eval dict | |
let f = uses_dict_((plus,mul,from_int,dup)); | |
let _ = f(5, 6); | |
let g = uses_dict2_((plus, from_int, dup)); | |
let _ = g(5); | |
let h = uses_dict3_((plus,mul,from_int,dup)); | |
let _ = h(5); | |
} | |
'int : { | |
use f64_::*; | |
// run with dict | |
let _ = uses_dict((plus,mul,from_int), 5.0, 6.0); | |
let _ = uses_dict2((plus, from_int), 5.0); | |
let _ = uses_dict3((plus,mul,from_int), 5.0); | |
// partial eval dict | |
let f = uses_dict_((plus,mul,from_int,dup)); | |
let _ = f(5.0, 6.0); | |
let g = uses_dict2_((plus, from_int, dup)); | |
let _ = g(5.0); | |
let h = uses_dict3_((plus,mul,from_int,dup)); | |
let _ = h(5.0); | |
} | |
'string : { | |
use string_::*; | |
// run with dict | |
let _ = uses_dict2((plus, from_int), "Five".to_string()); | |
// partial eval dict | |
let g = uses_dict2_((plus, from_int, dup)); | |
let _ = g("Five".to_string()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment