swish-0.2.1: Swish/HaskellRDF/Rule.hs
{-# OPTIONS -XMultiParamTypeClasses #-}
--------------------------------------------------------------------------------
--
-- $Id: Rule.hs,v 1.8 2004/01/07 19:49:13 graham Exp $
--
-- Copyright (c) 2003, G. KLYNE. All rights reserved.
-- See end of this file for licence information.
--------------------------------------------------------------------------------
-- |
-- Module : Rule
-- Copyright : (c) 2003, Graham Klyne
-- License : GPL V2
--
-- Maintainer : Graham Klyne
-- Stability : provisional
-- Portability : H98
--
-- This module defines a framework for defining inference rules
-- over some expression form. It is intended to be used with
-- RDF graphs, but the structures aim to be quite generic with
-- respect to the expression forms allowed.
--
--------------------------------------------------------------------------------
module Swish.HaskellRDF.Rule
( Expression(..), Formula(..), Rule(..), RuleMap
, nullScope, nullFormula, nullRule
, fwdCheckInference, bwdCheckInference
, showsFormula, showsFormulae, showsWidth
)
where
import Swish.HaskellUtils.Namespace
( Namespace(..)
, ScopedName(..)
, getScopePrefix, getScopeURI
, getQName, getScopedNameURI
)
import Swish.HaskellUtils.LookupMap
( LookupEntryClass(..), LookupMap(..)
)
import Swish.HaskellUtils.ShowM
( ShowM(..), showm )
import Swish.HaskellUtils.ListHelpers
( subset )
{- in Prelude????
import List
( union, intersect )
import Maybe
( isJust, fromJust )
-}
------------------------------------------------------------
-- Expressions
------------------------------------------------------------
-- |Expression is a type class for values over which proofs
-- may be constructed.
class (Eq ex) => Expression ex where
-- |Is expression true in all interpretations?
-- If so, then its truth is assumed without justification.
isValid :: ex -> Bool
------------------------------------------------------------
-- Formula: a named expression
------------------------------------------------------------
-- |A Formula is a named expression.
data Formula ex = Formula
{ formName :: ScopedName -- ^ Name used for formula in proof chain
, formExpr :: ex -- ^ Named formula value
} deriving Show
-- |Define equality of formulae as equality of formula names
instance Eq (Formula ex) where
f1 == f2 = formName f1 == formName f2
-- |Define ordering of formulae based on formula names
instance Ord (Formula ex) where
f1 <= f2 = formName f1 <= formName f2
instance LookupEntryClass (Formula ex) ScopedName (Formula ex)
where
newEntry (_,form) = form
keyVal form = (formName form, form)
nullScope :: Namespace
nullScope = Namespace "null" "http://id.ninebynine.org/2003/Ruleset/null"
nullFormula :: Formula ex
nullFormula = Formula
{ formName = ScopedName nullScope "nullFormula"
, formExpr = error "Null formula"
}
-- testf1 = Formula "f1" ('f',1)
-- testf2 = Formula "f2" ('f',2)
-- |showsFormulae
-- Return a displayable form of a list of labelled formulae
showsFormulae :: (ShowM ex) => String -> [Formula ex] -> String -> ShowS
showsFormulae _ [] _ = id
showsFormulae newline [f] after = showsFormula newline f .
showString after
showsFormulae newline (f:fs) after = showsFormula newline f .
showString newline .
showsFormulae newline fs after
-- |showsFormula
-- Create a displayable form of a labelled formula
showsFormula :: (ShowM ex) => String -> Formula ex -> ShowS
showsFormula newline f =
showsWidth 16 ("["++show (formName f)++"] ") .
showms (newline++(replicate 16 ' ')) (formExpr f)
------------------------------------------------------------
-- Rule
------------------------------------------------------------
-- |Rule is a data type for inference rules that can be used
-- to construct a step in a proof.
data Rule ex = Rule
-- |Name of rule, for use when displaying a proof
{ ruleName :: ScopedName
-- |Forward application of a rule, takes a list of
-- expressions and returns a list (possibly empty)
-- of forward applications of the rule to combinations
-- of the antecedent expressions.
-- Note that all of the results returned can be assumed to
-- be (simultaneously) true, given the antecedents provided.
, fwdApply :: [ex] -> [ex]
-- |Backward application of a rule, takes an expression
-- and returns a list of alternative antecedents, each of
-- which is a list of expressions that jointly yield the
-- given consequence through application of the inference
-- rule. An empty list is returned if no antecedents
-- will allow the consequence to be inferred.
, bwdApply :: ex -> [[ex]]
-- |Inference check. Takes a list of antecedent expressions
-- and a consequent expression, returning True if the
-- consequence can be obtained from the antecedents by
-- application of the rule. When the antecedents and
-- consequent are both given, this is generally more efficient
-- that using either forward or backward chaining.
-- Also, a particular rule may not fully support either
-- forward or backward chaining, but all rules are required
-- to fully support this function.
--
-- A default implementation based on forward chaining is
-- given below.
, checkInference :: [ex] -> ex -> Bool
}
-- |Define equality of rules as equality of rule names
instance Eq (Rule ex) where
r1 == r2 = ruleName r1 == ruleName r2
-- |Define ordering of rules based on rule names
instance Ord (Rule ex) where
r1 <= r2 = ruleName r1 <= ruleName r2
instance Show (Rule ex) where
show rl = "Rule "++show (ruleName rl)
instance LookupEntryClass (Rule ex) ScopedName (Rule ex)
where
newEntry (_,rule) = rule
keyVal rule = (ruleName rule, rule)
type RuleMap ex = LookupMap (Rule ex)
fwdCheckInference :: (Eq ex) => Rule ex -> [ex] -> ex -> Bool
fwdCheckInference rule ante cons =
(cons `elem` fwdApply rule ante)
bwdCheckInference :: (Eq ex) => Rule ex -> [ex] -> ex -> Bool
bwdCheckInference rule ante cons = any checkAnts (bwdApply rule cons)
where
checkAnts = all (`elem` ante)
nullRule :: Rule ex
nullRule = Rule
{ ruleName = ScopedName nullScope "nullRule"
, fwdApply = \ _ -> []
, bwdApply = \ _ -> []
, checkInference = \ _ _ -> False
}
------------------------------------------------------------
-- Shows formatting support functions
-----------------------------------------------------------
-- |Show a string left justified in a field of at least the specified
-- number of characters width.
showsWidth :: Int -> String -> ShowS
showsWidth wid str more = str++replicate pad ' '++more
where
pad = wid - length str
--------------------------------------------------------------------------------
--
-- Copyright (c) 2003, G. KLYNE. All rights reserved.
--
-- This file is part of Swish.
--
-- Swish is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- Swish 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 General Public License
-- along with Swish; if not, write to:
-- The Free Software Foundation, Inc.,
-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--
--------------------------------------------------------------------------------
-- $Source: /file/cvsdev/HaskellRDF/Rule.hs,v $
-- $Author: graham $
-- $Revision: 1.8 $
-- $Log: Rule.hs,v $
-- Revision 1.8 2004/01/07 19:49:13 graham
-- Reorganized RDFLabel details to eliminate separate language field,
-- and to use ScopedName rather than QName.
-- Removed some duplicated functions from module Namespace.
--
-- Revision 1.7 2003/12/10 03:48:58 graham
-- SwishScript nearly complete: BwdChain and PrrofCheck to do.
--
-- Revision 1.6 2003/12/04 02:53:27 graham
-- More changes to LookupMap functions.
-- SwishScript logic part complete, type-checks OK.
--
-- Revision 1.5 2003/11/13 01:13:48 graham
-- Reworked ruleset to use ScopedName lookup.
-- Various minor fixes.
--
-- Revision 1.4 2003/11/06 17:58:33 graham
-- About to rework Datatype to better support class-based reasoning.
--
-- Revision 1.3 2003/10/24 21:05:09 graham
-- Working on datatype inference. Most of the variable binding logic
-- is done, but the rule structure still needs to be worked out to support
-- forward and backward chaining through the same rule.
--
-- Revision 1.2 2003/10/02 13:41:26 graham
-- Supporting changes for RDF axioms and rules defined as Rulesets,
-- and moved out of module RDFProofCheck.
-- Datatype named using ScopedName rather than QName
-- (Datatype framework is still work in progress).
--
-- Revision 1.1 2003/09/30 20:00:46 graham
-- Add module Rule as common dependency for Proof and Ruleset
--