Example #1
0
 /**
  * Creates a new ManyMaybe instance from the given collection,
  * thereby composing each collection item into an Maybe monad.
  *
  * @param array $values
  */
 protected function __construct(array $values)
 {
     $unit = function ($value) {
         return Maybe::unit($value);
     };
     parent::__construct(array_map($unit, $values));
 }
Example #2
0
 public function orElse(callable $f, array $args)
 {
     // Since we don't know if $f will throw an exception, we wrap the call
     // in a try/catch. The result wiil be Left if there's an exception.
     try {
         $maybeResult = call_user_func_array($f, $args);
     } catch (\Exception $e) {
         // Unfortunately, we lose the error context. That's just the nature
         // of using Maybe in a language that has exceptions.
         $maybeResult = Maybe::nothing();
     }
     return $maybeResult;
 }
Example #3
0
 /**
  * Solve probeert één $goal op te lossen door regels toe te passen of
  * relevante vragen te stellen. Als het lukt een regel toe te passen of
  * een vraag te stellen geeft hij een nieuwe $state terug. Ook geeft hij
  * de TruthState voor $goal terug. In het geval van Maybe kan dat gebruikt
  * worden om af te leiden welk $goal als volgende moet worden afgeleid om
  * verder te komen.
  *
  * @param KnowledgeState $state huidige knowledge state
  * @param string goal naam van het fact dat wordt afgeleid
  * @return TruthState | AskedQuestion
  */
 public function solve(KnowledgeState $state, $goal)
 {
     // Forward chain until there is nothing left to derive.
     $this->forwardChain($state);
     // Test whether the fact is already in the knowledge base and if not, if it is solely
     // unknown because we don't know the current goal we try to prove. Because, it could
     // have a variable as value which still needs to be resolved, but that might be a
     // different goal!
     $current_value = $state->value($goal);
     if (!($current_value instanceof Maybe && $current_value->factors == new ArrayIterator([$goal]))) {
         return $current_value;
     }
     // Is er misschien een regel die we kunnen toepassen
     $relevant_rules = new CallbackFilterIterator($state->rules->getIterator(), function ($rule) use($goal) {
         return $rule->infers($goal);
     });
     // Assume that all relevant rules result in maybe's. If not, something went
     // horribly wrong in $this->forwardChain()!
     foreach ($relevant_rules as $rule) {
         assert('$rule->condition->evaluate($state) instanceof Maybe');
     }
     // Is er misschien een directe vraag die we kunnen stellen?
     $relevant_questions = new CallbackFilterIterator($state->questions->getIterator(), function ($question) use($goal) {
         return $question->infers($goal);
     });
     $this->log("Found %d rules and %s questions", [iterator_count($relevant_rules), iterator_count($relevant_questions)], LOG_LEVEL_VERBOSE);
     // If this problem can be solved by a rule, use it!
     if (iterator_count($relevant_rules) > 0) {
         return Maybe::because(new CallbackMapIterator($relevant_rules, function ($rule) use($state) {
             return $rule->condition->evaluate($state);
         }));
     }
     // If not, but when we do have a question to solve it, use that instead.
     if (iterator_count($relevant_questions) > 0) {
         $question = iterator_first($relevant_questions);
         // deze vraag is alleen over te slaan als er nog regels open staan om dit feit
         // af te leiden of als er alternatieve vragen naast deze (of eerder gestelde,
         // vandaar $n++) zijn.
         $skippable = iterator_count($relevant_questions) - 1;
         // haal de vraag hoe dan ook uit de mogelijk te stellen vragen. Het heeft geen zin
         // om hem twee keer te stellen.
         $state->questions->remove($question);
         return new AskedQuestion($question, $skippable);
     }
     // We have no idea how to solve this. No longer our problem!
     // (The caller should set $goal to undefined or something.)
     return Maybe::because();
 }
Example #4
0
 /**
  * @param Maybe $other
  * @return JustList
  */
 public function combine(Maybe $other)
 {
     return new JustList(array_merge($this->all(), $other->all()));
 }
 /**
  * Apply a function to this Monad's value only if the value is not null
  *
  * @param callable $f
  *
  * @return Maybe
  */
 public function map(callable $f)
 {
     return $this->isNothing() ? Maybe::of(null) : Maybe::of($f($this->value));
 }
    {
        if ($value instanceof Maybe) {
            return $value;
        }
        return new static($value);
    }
    // Places an object into the monad if the isNothing function returns true
    public function bind(callable $function)
    {
        return $this->isNothing() ? $this : static::unit($function($this->container));
    }
    public function isNothing()
    {
        return $this->container === false;
    }
}
// Object to test
$vehicle = new Vehicle(1, 'golf', 'red', 12000, true, 1000);
// Ruleset for type, color and mileage
$type = function ($value) {
    return Maybe::unit($value->type == 'golf' ? $value : false);
};
$color = function ($value) {
    return Maybe::unit($value->color == 'red' ? $value : false);
};
$mileage = function ($value) {
    return Maybe::unit($value->mileage == 12000 ? $value : false);
};
// Execution. On success an object will be returned
$test = Maybe::unit($vehicle)->bind($type)->bind($color)->bind($mileage);
var_dump($test->get());
Example #7
0
 /**
  * Creates a new None monad.
  */
 public function __construct()
 {
     parent::__construct(null);
 }