OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-atomspace / opencog / atoms / signature / TypeUtils.h

130 lines · c ref:
/*
 * TypeUtils.h
 *
 * Copyright (C) 2015 Linas Vepstas
 *
 * Author: Linas Vepstas <linasvepstas@gmail.com> December 2015
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef _OPENCOG_TYPE_UTILS_H
#define _OPENCOG_TYPE_UTILS_H

#include <opencog/atoms/base/Handle.h>
#include <opencog/atoms/atom_types/types.h>
#include <opencog/atoms/value/Value.h>

namespace opencog
{
/** \addtogroup grp_atomspace
 *  @{
 */

/**
 * Type checker.  Returns true if `value` is of type `type_spec`.
 * More precisely, returns true if `value` will fit into the type
 * specification given by `type_spec`; that the value and the type
 * specification can be connected, e.g. for beta-reduction, or for
 * pattern matching (searching).
 */
bool value_is_type(const Handle& type_spec, const ValuePtr& value);

/**
 * Type matcher. Returns true if `left` can mate with `right`.
 * Here, `left` can be a type definition, and `right` can be
 * another type definition, or a value.  Mating is possible whenever
 * `left` is broader, less restricitve than `right`; equivalently
 * if `right` is narrower than 'left`.
 *
 * Mating types and arguments:
 * left == (Type "Concept")    right == (Concept "foo")  can mate.
 * left == (Type "Concept")    right == (Number 13)  cannot.
 *
 * Mating types and types:
 * left == (Type "Concept")    right == (Type "Concept")  can mate.
 *
 * Left is wider (polymorphic, in this case)
 *   left == (TypeChoice (Type "Concept") (Type "Number"))
 *   right == (Type "Number")  can mate.
 *
 * Function call arguments can be checked:
 *   left == (Arrow (Type "Concept") (Type "Number"))
 *   right == (Concept "foo")  can mate.
 *
 *   left == (Arrow (Type "Concept") (Type "Number"))
 *   right == (Number 13)  cannot.
 *
 * Function call chains can be checked:
 *   left == (Arrow (Type "Concept") (Type "Number"))
 *   right == (Type "Concept")  can mate.
 *
 * The following can mate, because left accepts a concept as input,
 * and right generates a concept as output:
 *   left == (Arrow (Type "Concept") (Type "Number"))
 *   right == (Arrow (Type "Evaluation") (Type "Concept")
 *
 * Any type specification is valid: SignatureLinks, etc work too.
 */
bool type_match(const Handle&, const ValuePtr&);

/**
 * Same as above, but return the composition (beta-reduction) of the
 * match. If the types do NOT match, an exception is thrown.
 * If the types do match, then, for many cases, the right side is the
 * result.  The compostion of arrows, however, results either in a
 * new arrow, or a simple return type.
 *
 * Examples:
 *
 * Function call arguments can be checked:
 *   left == (Arrow (Type "Concept") (Type "Number"))
 *   right == (Concept "foo")  can mate.
 *   result = (Type "Number")
 *
 * Function call chains:
 *   left == (Arrow (Type "Concept") (Type "Number"))
 *   right == (Type "Concept")  can mate.
 *   result = (Type "Number")
 *
 * The following can mate, because left accepts a concept as input,
 * and right generates a concept as output:
 *   left == (Arrow (Type "Concept") (Type "Number"))
 *   right == (Arrow (Type "Evaluation") (Type "Concept")
 *   result = (Arrow (Type "Evaluation") (Type "Number"))
 */
ValuePtr type_compose(const Handle&, const ValuePtr&);

/**
 * Return true if t is different than NOTYPE.
 */
bool is_well_typed(Type t);

/**
 * Return true if all types in ts are well typed.
 *
 * This might too strict. One might argue that NOTYPE is akin to the
 * empty set, thus the union of a valid type and NOTYPE should merely
 * amount to the valid type. We may want to relax that definition in
 * the future.
 */
bool is_well_typed(const TypeSet& ts);

/** @}*/
}

#endif // _OPENCOG_TYPE_UTILS_H