packages feed

pubgrub-0.1.0.0: src/PubGrub/Provider.hs

-- | The provider: how the solver learns about the world, one variable at a
-- time.
module PubGrub.Provider
    ( Provider (..)
    ) where

import           PubGrub.Incompatibility (Domain (..), Incompatibility)


-- | What the solver asks of the world. It never sees the world itself, only
-- variables, sets of values and incompatibilities, and it asks about one
-- variable when it needs to: there is no problem description handed over up
-- front, so a provider reads only what the search reaches.
--
-- The question is always the same: here is a variable, and the set of values
-- it may still take; commit to one of them, and say what that choice entails.
-- The set may be symbolic, a range rather than a list, so the provider is not
-- asked to enumerate it: it picks a value the set admits, by whatever
-- preference it has (the newest version, an installed one, a default).
--
-- @m@ is the provider's own monad: 'Data.Functor.Identity.Identity' for a world
-- held in memory, 'IO' for one read from disk.
newtype Provider v m = Provider
    { expand :: v -> SetOf v -> m (Maybe (ValueOf v), [Incompatibility v])
      -- ^ Pick a value of the variable from the set, and state what is known
      -- on the way: typically the chosen value's dependencies.
      --
      -- __The value must be in the set.__ The set is everything the solver
      -- has derived about the variable, and the solver records the value as a
      -- decision at once, so a value outside it contradicts what the solver
      -- already knows. The solver checks, and stops the solve with
      -- 'PubGrub.Solver.BadValue' rather than go on. A value in the set that
      -- turns out wrong is not an error: on a later conflict the solver
      -- backtracks and asks again with a smaller set.
      --
      -- Answer 'Nothing' when no value in the set can be chosen. The solver
      -- then states that the variable takes no value in the set, so the same
      -- set is never offered twice.
      --
      -- __The incompatibilities are facts.__ The solver adds them to what it
      -- knows without examining them, and each must be true of every solution,
      -- whatever has been decided so far. They need not mention the chosen
      -- value. So a provider that passes over values on the way to its answer
      -- may say why it passed them over, and those facts prune the search and
      -- explain a failure like any other. A fact should have a positive term,
      -- or a single negative one: a fact of two or more negative terms and
      -- nothing else says that one of several variables must have a value
      -- without saying which, and the search never acts on it.
      --
      -- This matters most when the answer is 'Nothing'. If every value in the
      -- set was rejected for a reason (it cannot be built here, it needs
      -- something missing), state the reasons: the solver uses them, and
      -- states \"no value\" only for what they do not cover. A failure is then
      -- explained by what was wrong with the values, not by their absence.
      -- Only a fact about the variable alone covers its values. A reason that
      -- names another variable rules the values out only while its other terms
      -- hold, so the solver states \"no value\" for them as well.
    }