Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #![allow(dead_code)]
- /// so, when are two type, `a` and `b`, considered equal?
- /// a definition might be, it is possible to go from `a` to `b`,
- /// and from `b` to `a`.
- /// Going a roundway trip should leave you the same value.
- /// Unfortunately it is virtually impossible to test this.
- /// This is called ISO.
- pub enum Void { }
- impl PartialEq for Void {
- fn eq(&self, _: &Void) -> bool {
- true
- }
- }
- pub fn absurd(_: Void) -> ! {
- panic!("You must be kidding! Where did you find that void instance?");
- }
- pub type ISO<A: 'static, B: 'static> = (Box<Fn(A) -> B>, Box<Fn(B) -> A>);
- pub fn iso<A: 'static, B: 'static, F1, F2>(a: F1, b: F2) -> ISO<A, B>
- where F1: 'static + Fn(A) -> B,
- F2: 'static + Fn(B) -> A,
- {
- (Box::new(a), Box::new(b))
- }
- /// given ISO a b, we can go from a to b
- pub fn sub_st_l<A, B>(iso: ISO<A, B>) -> Box<Fn(A) -> B> { iso.0 }
- /// and vice versa
- pub fn sub_st_r<A, B>(iso: ISO<A, B>) -> Box<Fn(B) -> A> { iso.1 }
- /// There can be more than one ISO a b
- pub fn iso_bool() -> ISO<bool, bool> {
- (Box::new(|x| x), Box::new(|x| x))
- }
- pub fn iso_bool_not() -> ISO<bool, bool> {
- (Box::new(|x| !x), Box::new(|x| !x))
- }
- /// isomorphism is reflexive
- pub fn refl<A: 'static>() -> ISO<A, A> {
- (Box::new(|x| x), Box::new(|x| x))
- }
- /// isomorphism is symmetric
- pub fn symm<A: 'static, B: 'static>(i: ISO<A, B>) -> ISO<B, A> {
- (i.1, i.0)
- }
- /// isomorphism is transitive
- pub fn trans<A: 'static, B: 'static, C: 'static>
- (ab: ISO<A, B>, bc: ISO<B, C>) -> ISO<A, C> {
- let (ab, ba) = ab;
- let (bc, cb) = bc;
- (Box::new(move |a| bc(ab(a))),
- Box::new(move |c| ba(cb(c))))
- }
- /// we can combine isomorphism
- pub fn iso_tuple<A: 'static, B: 'static, C: 'static, D: 'static>
- (ab: ISO<A, B>, cd: ISO<C, D>) -> ISO<(A, C), (B, D)> {
- let (ab, ba) = ab;
- let (cd, dc) = cd;
- (Box::new(move |(a,c)| (ab(a), cd(c))),
- Box::new(move |(b,d)| (ba(b), dc(d))))
- }
- pub fn iso_vec<A: 'static, B: 'static>(i: ISO<A, B>) -> ISO<Vec<A>, Vec<B>> {
- let (ab, ba) = i;
- (Box::new(move |v| v.into_iter().map(&*ab).collect()),
- Box::new(move |v| v.into_iter().map(&*ba).collect()))
- }
- pub fn iso_option<A: 'static, B: 'static>
- (i: ISO<A, B>) -> ISO<Option<A>, Option<B>> {
- let (ab, ba) = i;
- (Box::new(move |a: Option<A>| a.map(&*ab)),
- Box::new(move |b: Option<B>| b.map(&*ba)))
- }
- pub fn iso_result<A: 'static, B: 'static, C: 'static, D: 'static>
- (ab: ISO<A, B>, cd: ISO<C, D>) -> ISO<Result<A, C>, Result<B, D>> {
- let (ab, ba) = ab;
- let (cd, dc) = cd;
- (Box::new(move |ac: Result<A, C>| ac.map(&*ab).map_err(&*cd)),
- Box::new(move |bd: Result<B, D>| bd.map(&*ba).map_err(&*dc)))
- }
- /// Going another way is hard (and is generally impossible)
- /// Remember, for all valid ISO, converting and converting back
- /// is the same as the original value.
- /// You need this to prove some case are impossible.
- pub fn iso_un_option<A: 'static, B: 'static>
- (i: ISO<Option<A>, Option<B>>) -> ISO<A, B> {
- let (ab, ba) = i;
- (Box::new(move |a: A| ab(Some(a)).unwrap_or(ab(None).unwrap())),
- Box::new(move |b: B| ba(Some(b)).unwrap_or(ba(None).unwrap())))
- }
- /// inf + 0 = inf + 1
- pub fn iso_eu() -> ISO<Result<Vec<()>, ()>, Result<Vec<()>, Void>> {
- let l2r = |a: Result<Vec<()>, ()>| {
- Ok( match a {
- Ok(v) => {
- let mut v = v.to_vec();
- v.push(());
- v
- }
- Err(_) => vec![]
- })
- };
- let r2l = |b: Result<Vec<()>, Void>| {
- let mut v = b.unwrap_or(vec![]);
- if v.is_empty() {
- Err(())
- } else {
- v.pop();
- Ok(v)
- }
- };
- (Box::new(l2r), Box::new(r2l))
- }
- pub type IsoFL<A, B, C, D> = Box<FnOnce(Box<Fn(A) -> C>) -> Box<FnOnce(B) -> D>>;
- pub type IsoFR<A, B, C, D> = Box<FnOnce(Box<Fn(B) -> D>) -> Box<FnOnce(A) -> C>>;
- pub type IsoF<A, B, C, D> = (IsoFL<A, B, C, D>, IsoFR<A, B, C, D>);
- /// translator note:
- /// FnBox is not yet supported, we can only return an uncallable
- /// Box<FnOnce> (RetFunc). You should return the function with
- /// correct type, which will be checked by the tests.
- /// The type annotation is shown above. You need you return something like
- /// (Box::new(...), Box::new(...))
- pub fn iso_func<A: 'static, B: 'static, C: 'static, D: 'static>
- (ab: ISO<A, B>, cd: ISO<C, D>) -> IsoF<A, B, C, D> {
- let (ab, ba) = ab;
- let (cd, dc) = cd;
- let f1: FnOnce(Box<Fn(A) -> C>) -> Box<FnOnce(B) -> D> = move |ac| {
- Box::new(|b: B| cd(ac(ba(b))))
- };
- let f2 = |bd: Box<Fn(B) -> D>| {
- Box::new(|a: A| dc(bd(ab(a))))
- };
- //let f1: FnOnce(Box<Fn(A) -> C>) -> Box<FnOnce(B) -> D> = unimplemented!();
- //let f2: FnOnce(Box<Fn(B) -> D>) -> Box<FnOnce(A) -> C> = unimplemented!();
- (Box::new(f1), Box::new(f2))
- //unimplemented!()
- }
- /// And we have isomorphism on isomorphism!
- pub fn iso_symm<A: 'static, B: 'static>() -> ISO<ISO<A, B>, ISO<B, A>> {
- (Box::new(symm), Box::new(symm))
- }
- /*************************************************************************************************/
- fn main() {
- for n in 1..10 {
- println!("going({})", n);
- }
- assert!(sub_st_l(iso_bool())(true));
- assert!(!sub_st_l(iso_bool())(false));
- assert!(sub_st_l(iso_bool_not())(false));
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement