Skip to content
This repository has been archived by the owner on Oct 5, 2023. It is now read-only.

Understand and explore whether we really need that many monads in SymEval #112

Open
VictorCMiraldo opened this issue Jun 17, 2022 · 6 comments
Assignees

Comments

@VictorCMiraldo
Copy link
Contributor

In #110 we started using a pure and parallel solve function; which meant we could remove IO from the symbolic engine altogether! 🎉

Yet, the SymEval monad now looks like:

newtype SymEval lang a = SymEval
  { symEval ::
      ReaderT
        (PrtOrderedDefs lang)
        (ReaderT (SymEvalSolvers lang) (StateT (SymEvalSt lang) WeightedList))
        a
  }

And, in particular, the StateT is the one that hurts our ability to parallelize the symbolic engine even further: every call to mapM can't be replaced by a parMap because of the state being threaded through.

This issue aims at document an exploration of the design space: now that we have no more IO to deal with, we might be able to afford ourselves better types and an even cleaner implementation.

One particular point where it might be interesting to attempt to parallelize is the Monad instance for WeigthedList.

@VictorCMiraldo
Copy link
Contributor Author

For the record, I think we can drastically simplify WeigthedT and make it a plain monad, no need to be a transformer at this point.
Also, no need to use a "list" structure either; WeigthedT could well be a tree: there's no more need to worry about synchronizing different monadic effects inside! :)

@VictorCMiraldo VictorCMiraldo added the dev This is an issue relevant to our `dev` branch label Jun 17, 2022
@VictorCMiraldo
Copy link
Contributor Author

Another piece of information to use: #110 (comment)

@serras
Copy link
Contributor

serras commented Jun 17, 2022

The State part threads two pieces of information:

  • the current known facts,
  • the statistics about found constructors, and so on.
    Those two things always "grow", and in a sense it's like a tree.

Why the State then? Because we have the worker function, which implements the recursion-and-stop-when-needed steps. Right now the call structure is worker -> symEvalOneStep -> return to worker. So if we somehow can remove that "going back", we should be able to make everything parallel.

@serras
Copy link
Contributor

serras commented Jun 22, 2022

I've been talking with @lucaspena about how to change the weighted list into a Tree.

@serras
Copy link
Contributor

serras commented Jun 22, 2022

In fact, I think that we can more or less easily use the following monad:

data Tree lang a = Leaf a | Node (Maybe (TermMeta lang SymVar)) [Tree lang a]

which keeps the branching and at each point records "the term at this point." At the very list it has the usual Functor, Applicative and Alternative instances. And during symEvalDestructor and the evaluation of built-ins we could use the Node to record whatever we are doing there.

@lucaspena will you give it a go? Otherwise I can try tomorrow!

@serras
Copy link
Contributor

serras commented Jun 24, 2022

Current progress:

@VictorCMiraldo VictorCMiraldo changed the title In dev: understand and explore whether we really need that many monads in SymEval Understand and explore whether we really need that many monads in SymEval Jun 29, 2022
@VictorCMiraldo VictorCMiraldo removed the dev This is an issue relevant to our `dev` branch label Jun 29, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants