Skip to content

Instantly share code, notes, and snippets.

@ClarkeRemy
Last active October 16, 2024 08:40
Show Gist options
  • Save ClarkeRemy/fcda36f82310adde6a530d5c861f811c to your computer and use it in GitHub Desktop.
Save ClarkeRemy/fcda36f82310adde6a530d5c861f811c to your computer and use it in GitHub Desktop.
Dictionary Passing style
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
// ////////////////////////////////////
// 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