From 21edad6c75cc3cb56142a5563cab38cf30b81c0e Mon Sep 17 00:00:00 2001
From: timofey <tim@ongoteam.yaconnect.com>
Date: Tue, 25 Apr 2023 11:33:11 +0000
Subject: [PATCH] SharedFunctor for LazyClass

---
 src/func/classes/lazy.rs | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/src/func/classes/lazy.rs b/src/func/classes/lazy.rs
index b0dde7e..9120e6a 100644
--- a/src/func/classes/lazy.rs
+++ b/src/func/classes/lazy.rs
@@ -7,6 +7,8 @@
 //!
 //! For stackless execution see [`super::stackless`].
 
+use std::{cell::RefCell, rc::Rc};
+
 use crate::func::*;
 
 pub struct LazyClass;
@@ -104,3 +106,32 @@ impl Monad for LazyClass {
         Box::new(|| ffa()())
     }
 }
+
+fn unshare<'a, A: 'a + Clone>(shared: &mut Option<Box<dyn 'a + FnOnce() -> A>>) -> A {
+    let a = shared.take().expect(
+        "cannot evaluate a missing shared lazy value. probably, the shared value depends on itself",
+    )();
+    let cloned = a.clone();
+    *shared = Some(Box::new(|| cloned));
+    a
+}
+
+impl SharedFunctor for LazyClass {
+    type Shared<'a, A: 'a + Clone> = Rc<RefCell<Option<Box<dyn 'a + FnOnce() -> A>>>>
+    where
+        Self: 'a;
+
+    fn share<'a, A: 'a + Clone>(fa: Self::F<'a, A>) -> Self::Shared<'a, A>
+    where
+        Self: 'a,
+    {
+        Rc::new(RefCell::new(Some(fa)))
+    }
+
+    fn unshare<'a, A: 'a + Clone>(sa: Self::Shared<'a, A>) -> Self::F<'a, A>
+    where
+        Self: 'a,
+    {
+        Box::new(move || unshare(&mut *sa.borrow_mut()))
+    }
+}