Advertisement
Guest User

Untitled

a guest
Oct 4th, 2015
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.66 KB | None | 0 0
  1. use std::marker::PhantomData;
  2.  
  3. type Is<S, T> = Is_<S, T>;
  4.  
  5. #[derive(Clone)]
  6. struct Is_ <S, T>(PhantomData<S>, PhantomData<T>);
  7.  
  8. fn refl<T>() -> Is<T, T> {
  9. Is_(PhantomData, PhantomData)
  10. }
  11.  
  12. impl<S, T> Is_<S, T> {
  13. fn coerce (&self, value: T) -> S {
  14. unsafe {
  15. * std::mem::transmute::<_, Box<_>>(Box::new(value))
  16. }
  17. }
  18. }
  19.  
  20. #[derive(Clone)]
  21. enum Exp<T> {
  22. LitInt(Is<T, i64>, i64),
  23. LitString(Is<T, String>, String),
  24. Add(Is<T, i64>, Box<Exp<i64>>, Box<Exp<i64>>),
  25. }
  26.  
  27. impl<T> Exp<T> {
  28. fn eval(self) -> T {
  29. use Exp::*;
  30.  
  31. match self {
  32. LitInt(witness, i) => witness.coerce(i),
  33. LitString(witness, s) => witness.coerce(s),
  34. Add(witness, bx, by) => {
  35. let x = bx.eval();
  36. let y = by.eval();
  37. witness.coerce(x + y)
  38. },
  39. }
  40. }
  41. }
  42.  
  43. #[test]
  44. fn it_works() {
  45. use Exp::*;
  46.  
  47. let one = LitInt(refl(), 1);
  48. assert_eq!(one.clone().eval(), 1);
  49.  
  50. let two = LitInt(refl(), 2);
  51. assert_eq!(two.clone().eval(), 2);
  52.  
  53. let exp = Add(refl(), Box::new(one), Box::new(two));
  54.  
  55. assert_eq!(exp.eval(), 3);
  56.  
  57. let name: Exp<String> = LitString(refl(), "GADTs".to_string());
  58. assert_eq!(name.eval(), "GADTs");
  59.  
  60. // let wrong = Add(refl(), Box::new(name), Box::new(two));
  61. /*
  62. src/lib.rs:66:38: 66:42 error: mismatched types:
  63. expected `Exp<i64>`,
  64. found `Exp<collections::string::String>`
  65. (expected i64,
  66. found struct `collections::string::String`) [E0308]
  67. src/lib.rs:66 let wrong = Add(refl(), Box::new(name), Box::new(two));
  68. ^~~~
  69. */
  70. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement