``````module Free.RunBased.Add
( main
, eval
) where
--
import Effect (Effect)
import Effect.Console (log)
import Data.Either (Either(..))
import Data.Functor.Variant (VariantF, on, case_)
import Type.Row (type (+))
import Type.Proxy (Proxy(..))
import Free.RunBased.Value (value)
import Run (Run, lift, peel)

-- Data stuff

-- Variant Stuff

{-
We know from previous code that we need a type signature like
-> Expression a
-> Expression a

However, if we follow the same pattern we've been using via `Run.lift`
the return type's `a` will be another "Expression a"
-}
. Run (ADD + r) a
-> Run (ADD + r) a

{-
To get around this problem, we need to remember that
Run is a monad. Thus, the above type signature could look like this:

=> m a
-> m a
-> m (m a)

We need a function whose type signature is...
m (m a) -> m a
... to get rid of that nested monad.
This is known as 'join' from 'Bind'                                         -}
. Run (ADD + r) a
-> Run (ADD + r) a
-> Run (ADD + r) a

-- Putting it all on one line:
. Run (ADD + r) a
-> Run (ADD + r) a
-> Run (ADD + r) a

-- Eval stuff
. (VariantF r Int -> Int)
-> (VariantF (ADD + r) Int -> Int)

-- fold
iter :: forall r a. (VariantF r a -> a) -> Run r a -> a
iter k = go
where
go m = case peel m of
Left f -> k (go <\$> f)
Right a -> a

eval :: forall r a b
. ((VariantF () a -> b) -> VariantF r Int -> Int)
-> Run r Int
-> Int
eval algebra = iter (case_ # algebra)

-- Examples
main :: Effect Unit
main = do