aboutsummaryrefslogtreecommitdiff
path: root/src/algebra/pattern.spad.pamphlet
diff options
context:
space:
mode:
authordos-reis <gdr@axiomatics.org>2007-08-14 05:14:52 +0000
committerdos-reis <gdr@axiomatics.org>2007-08-14 05:14:52 +0000
commitab8cc85adde879fb963c94d15675783f2cf4b183 (patch)
treec202482327f474583b750b2c45dedfc4e4312b1d /src/algebra/pattern.spad.pamphlet
downloadopen-axiom-ab8cc85adde879fb963c94d15675783f2cf4b183.tar.gz
Initial population.
Diffstat (limited to 'src/algebra/pattern.spad.pamphlet')
-rw-r--r--src/algebra/pattern.spad.pamphlet555
1 files changed, 555 insertions, 0 deletions
diff --git a/src/algebra/pattern.spad.pamphlet b/src/algebra/pattern.spad.pamphlet
new file mode 100644
index 00000000..e22e9207
--- /dev/null
+++ b/src/algebra/pattern.spad.pamphlet
@@ -0,0 +1,555 @@
+\documentclass{article}
+\usepackage{axiom}
+\begin{document}
+\title{\$SPAD/src/algebra pattern.spad}
+\author{Manuel Bronstein}
+\maketitle
+\begin{abstract}
+\end{abstract}
+\eject
+\tableofcontents
+\eject
+\section{domain PATTERN Pattern}
+<<domain PATTERN Pattern>>=
+)abbrev domain PATTERN Pattern
+++ Patterns for use by the pattern matcher
+++ Author: Manuel Bronstein
+++ Date Created: 10 Nov 1988
+++ Date Last Updated: 20 June 1991
+++ Description: Patterns for use by the pattern matcher.
+++ Keywords: pattern, matching.
+-- Not exposed.
+-- Patterns are optimized for quick answers to structural questions.
+Pattern(R:SetCategory): Exports == Implementation where
+ B ==> Boolean
+ SI ==> SingleInteger
+ Z ==> Integer
+ SY ==> Symbol
+ O ==> OutputForm
+ BOP ==> BasicOperator
+ QOT ==> Record(num:%, den:%)
+ REC ==> Record(val:%, exponent:NonNegativeInteger)
+ RSY ==> Record(tag:SI, val: SY, pred:List Any, bad:List Any)
+ KER ==> Record(tag:SI, op:BOP, arg:List %)
+ PAT ==> Union(ret:R, ker: KER, exp:REC, qot: QOT, sym:RSY)
+
+-- the following MUST be the name of the formal exponentiation operator
+ POWER ==> "%power"::Symbol
+
+-- the 4 SYM_ constants must be disting powers of 2 (bitwise arithmetic)
+ SYM_GENERIC ==> 1::SI
+ SYM_MULTIPLE ==> 2::SI
+ SYM_OPTIONAL ==> 4::SI
+
+ PAT_PLUS ==> 1::SI
+ PAT_TIMES ==> 2::SI
+ PAT_LIST ==> 3::SI
+ PAT_ZERO ==> 4::SI
+ PAT_ONE ==> 5::SI
+ PAT_EXPT ==> 6::SI
+
+ Exports ==> Join(SetCategory, RetractableTo R, RetractableTo SY) with
+ 0 : constant -> % ++ 0
+ 1 : constant -> % ++ 1
+ isPlus : % -> Union(List %, "failed")
+ ++ isPlus(p) returns \spad{[a1,...,an]} if \spad{n > 1}
+ ++ and \spad{p = a1 + ... + an},
+ ++ and "failed" otherwise.
+ isTimes : % -> Union(List %, "failed")
+ ++ isTimes(p) returns \spad{[a1,...,an]} if \spad{n > 1} and
+ ++ \spad{p = a1 * ... * an}, and
+ ++ "failed" otherwise.
+ isOp : (%, BOP) -> Union(List %, "failed")
+ ++ isOp(p, op) returns \spad{[a1,...,an]} if \spad{p = op(a1,...,an)}, and
+ ++ "failed" otherwise.
+ isOp : % -> Union(Record(op:BOP, arg:List %), "failed")
+ ++ isOp(p) returns \spad{[op, [a1,...,an]]} if
+ ++ \spad{p = op(a1,...,an)}, and
+ ++ "failed" otherwise;
+ isExpt : % -> Union(REC, "failed")
+ ++ isExpt(p) returns \spad{[q, n]} if \spad{n > 0} and \spad{p = q ** n},
+ ++ and "failed" otherwise.
+ isQuotient : % -> Union(QOT, "failed")
+ ++ isQuotient(p) returns \spad{[a, b]} if \spad{p = a / b}, and
+ ++ "failed" otherwise.
+ isList : % -> Union(List %, "failed")
+ ++ isList(p) returns \spad{[a1,...,an]} if \spad{p = [a1,...,an]},
+ ++ "failed" otherwise;
+ isPower : % -> Union(Record(val:%, exponent:%), "failed")
+ ++ isPower(p) returns \spad{[a, b]} if \spad{p = a ** b}, and
+ ++ "failed" otherwise.
+ elt : (BOP, List %) -> %
+ ++ \spad{elt(op, [a1,...,an])} returns \spad{op(a1,...,an)}.
+ "+" : (%, %) -> %
+ ++ \spad{a + b} returns the pattern \spad{a + b}.
+ "*" : (%, %) -> %
+ ++ \spad{a * b} returns the pattern \spad{a * b}.
+ "**" : (%, NonNegativeInteger) -> %
+ ++ \spad{a ** n} returns the pattern \spad{a ** n}.
+ "**" : (%, %) -> %
+ ++ \spad{a ** b} returns the pattern \spad{a ** b}.
+ "/" : (%, %) -> %
+ ++ \spad{a / b} returns the pattern \spad{a / b}.
+ depth : % -> NonNegativeInteger
+ ++ depth(p) returns the nesting level of p.
+ convert : List % -> %
+ ++ \spad{convert([a1,...,an])} returns the pattern \spad{[a1,...,an]}.
+ copy : % -> %
+ ++ copy(p) returns a recursive copy of p.
+ inR? : % -> B
+ ++ inR?(p) tests if p is an atom (i.e. an element of R).
+ quoted? : % -> B
+ ++ quoted?(p) tests if p is of the form 's for a symbol s.
+ symbol? : % -> B
+ ++ symbol?(p) tests if p is a symbol.
+ constant? : % -> B
+ ++ constant?(p) tests if p contains no matching variables.
+ generic? : % -> B
+ ++ generic?(p) tests if p is a single matching variable.
+ multiple? : % -> B
+ ++ multiple?(p) tests if p is a single matching variable
+ ++ allowing list matching or multiple term matching in a
+ ++ sum or product.
+ optional? : % -> B
+ ++ optional?(p) tests if p is a single matching variable
+ ++ which can match an identity.
+ hasPredicate?: % -> B
+ ++ hasPredicate?(p) tests if p has predicates attached to it.
+ predicates : % -> List Any
+ ++ predicates(p) returns \spad{[p1,...,pn]} such that the predicate
+ ++ attached to p is p1 and ... and pn.
+ setPredicates: (%, List Any) -> %
+ ++ \spad{setPredicates(p, [p1,...,pn])} attaches the predicate
+ ++ p1 and ... and pn to p.
+ withPredicates:(%, List Any) -> %
+ ++ \spad{withPredicates(p, [p1,...,pn])} makes a copy of p and attaches
+ ++ the predicate p1 and ... and pn to the copy, which is
+ ++ returned.
+ patternVariable: (SY, B, B, B) -> %
+ ++ patternVariable(x, c?, o?, m?) creates a pattern variable x,
+ ++ which is constant if \spad{c? = true}, optional if \spad{o? = true},
+ ++ and multiple if \spad{m? = true}.
+ setTopPredicate: (%, List SY, Any) -> %
+ ++ \spad{setTopPredicate(x, [a1,...,an], f)} returns x with
+ ++ the top-level predicate set to \spad{f(a1,...,an)}.
+ topPredicate: % -> Record(var:List SY, pred:Any)
+ ++ topPredicate(x) returns \spad{[[a1,...,an], f]} where the top-level
+ ++ predicate of x is \spad{f(a1,...,an)}.
+ ++ Note: n is 0 if x has no top-level
+ ++ predicate.
+ hasTopPredicate?: % -> B
+ ++ hasTopPredicate?(p) tests if p has a top-level predicate.
+ resetBadValues: % -> %
+ ++ resetBadValues(p) initializes the list of "bad values" for p
+ ++ to \spad{[]}.
+ ++ Note: p is not allowed to match any of its "bad values".
+ addBadValue: (%, Any) -> %
+ ++ addBadValue(p, v) adds v to the list of "bad values" for p.
+ ++ Note: p is not allowed to match any of its "bad values".
+ getBadValues: % -> List Any
+ ++ getBadValues(p) returns the list of "bad values" for p.
+ ++ Note: p is not allowed to match any of its "bad values".
+ variables: % -> List %
+ ++ variables(p) returns the list of matching variables
+ ++ appearing in p.
+ optpair: List % -> Union(List %, "failed")
+ ++ optpair(l) returns l has the form \spad{[a, b]} and
+ ++ a is optional, and
+ ++ "failed" otherwise;
+
+ Implementation ==> add
+ Rep := Record(cons?: B, pat:PAT, lev: NonNegativeInteger,
+ topvar: List SY, toppred: Any)
+
+ dummy:BOP := operator(new()$Symbol)
+ nopred := coerce(0$Integer)$AnyFunctions1(Integer)
+
+ mkPat : (B, PAT, NonNegativeInteger) -> %
+ mkrsy : (SY, B, B, B) -> RSY
+ SYM2O : RSY -> O
+ PAT2O : PAT -> O
+ patcopy : PAT -> PAT
+ bitSet? : (SI , SI) -> B
+ pateq? : (PAT, PAT) -> B
+ LPAT2O : ((O, O) -> O, List %) -> O
+ taggedElt : (SI, List %) -> %
+ isTaggedOp: (%, SI) -> Union(List %, "failed")
+ incmax : List % -> NonNegativeInteger
+
+ coerce(r:R):% == mkPat(true, [r], 0)
+ mkPat(c, p, l) == [c, p, l, empty(), nopred]
+ hasTopPredicate? x == not empty?(x.topvar)
+ topPredicate x == [x.topvar, x.toppred]
+ setTopPredicate(x, l, f) == (x.topvar := l; x.toppred := f; x)
+ constant? p == p.cons?
+ depth p == p.lev
+ inR? p == p.pat case ret
+ symbol? p == p.pat case sym
+ isPlus p == isTaggedOp(p, PAT_PLUS)
+ isTimes p == isTaggedOp(p, PAT_TIMES)
+ isList p == isTaggedOp(p, PAT_LIST)
+ isExpt p == (p.pat case exp => p.pat.exp; "failed")
+ isQuotient p == (p.pat case qot => p.pat.qot; "failed")
+ hasPredicate? p == not empty? predicates p
+ quoted? p == symbol? p and zero?(p.pat.sym.tag)
+ generic? p == symbol? p and bitSet?(p.pat.sym.tag, SYM_GENERIC)
+ multiple? p == symbol? p and bitSet?(p.pat.sym.tag,SYM_MULTIPLE)
+ optional? p == symbol? p and bitSet?(p.pat.sym.tag,SYM_OPTIONAL)
+ bitSet?(a, b) == And(a, b) ^= 0
+ coerce(p:%):O == PAT2O(p.pat)
+ p1:% ** p2:% == taggedElt(PAT_EXPT, [p1, p2])
+ LPAT2O(f, l) == reduce(f, [x::O for x in l])$List(O)
+ retract(p:%):R == (inR? p => p.pat.ret; error "Not retractable")
+ convert(l:List %):% == taggedElt(PAT_LIST, l)
+ retractIfCan(p:%):Union(R,"failed") ==(inR? p => p.pat.ret;"failed")
+ withPredicates(p, l) == setPredicates(copy p, l)
+ coerce(sy:SY):% == patternVariable(sy, false, false, false)
+ copy p == [constant? p, patcopy(p.pat), p.lev, p.topvar, p.toppred]
+
+ -- returns [a, b] if #l = 2 and optional? a, "failed" otherwise
+ optpair l ==
+ empty? rest rest l =>
+ b := first rest l
+ optional?(a := first l) => l
+ optional? b => reverse l
+ "failed"
+ "failed"
+
+ incmax l ==
+ 1 + reduce("max", [p.lev for p in l], 0)$List(NonNegativeInteger)
+
+ p1 = p2 ==
+ (p1.cons? = p2.cons?) and (p1.lev = p2.lev) and
+ (p1.topvar = p2.topvar) and
+ ((EQ(p1.toppred, p2.toppred)$Lisp) pretend B) and
+ pateq?(p1.pat, p2.pat)
+
+ isPower p ==
+ (u := isTaggedOp(p, PAT_EXPT)) case "failed" => "failed"
+ [first(u::List(%)), second(u::List(%))]
+
+ taggedElt(n, l) ==
+ mkPat(every?(constant?, l), [[n, dummy, l]$KER], incmax l)
+
+ elt(o, l) ==
+ is?(o, POWER) and #l = 2 => first(l) ** last(l)
+ mkPat(every?(constant?, l), [[0, o, l]$KER], incmax l)
+
+ isOp p ==
+ (p.pat case ker) and zero?(p.pat.ker.tag) =>
+ [p.pat.ker.op, p.pat.ker.arg]
+ "failed"
+
+ isTaggedOp(p,t) ==
+ (p.pat case ker) and (p.pat.ker.tag = t) => p.pat.ker.arg
+ "failed"
+
+ if R has Monoid then
+ 1 == 1::R::%
+ else
+ 1 == taggedElt(PAT_ONE, empty())
+
+ if R has AbelianMonoid then
+ 0 == 0::R::%
+ else
+ 0 == taggedElt(PAT_ZERO, empty())
+
+ p:% ** n:NonNegativeInteger ==
+ p = 0 and n > 0 => 0
+ p = 1 or zero? n => 1
+-- one? n => p
+ (n = 1) => p
+ mkPat(constant? p, [[p, n]$REC], 1 + (p.lev))
+
+ p1 / p2 ==
+ p2 = 1 => p1
+ mkPat(constant? p1 and constant? p2, [[p1, p2]$QOT],
+ 1 + max(p1.lev, p2.lev))
+
+ p1 + p2 ==
+ p1 = 0 => p2
+ p2 = 0 => p1
+ (u1 := isPlus p1) case List(%) =>
+ (u2 := isPlus p2) case List(%) =>
+ taggedElt(PAT_PLUS, concat(u1::List %, u2::List %))
+ taggedElt(PAT_PLUS, concat(u1::List %, p2))
+ (u2 := isPlus p2) case List(%) =>
+ taggedElt(PAT_PLUS, concat(p1, u2::List %))
+ taggedElt(PAT_PLUS, [p1, p2])
+
+ p1 * p2 ==
+ p1 = 0 or p2 = 0 => 0
+ p1 = 1 => p2
+ p2 = 1 => p1
+ (u1 := isTimes p1) case List(%) =>
+ (u2 := isTimes p2) case List(%) =>
+ taggedElt(PAT_TIMES, concat(u1::List %, u2::List %))
+ taggedElt(PAT_TIMES, concat(u1::List %, p2))
+ (u2 := isTimes p2) case List(%) =>
+ taggedElt(PAT_TIMES, concat(p1, u2::List %))
+ taggedElt(PAT_TIMES, [p1, p2])
+
+ isOp(p, o) ==
+ (p.pat case ker) and zero?(p.pat.ker.tag) and (p.pat.ker.op =o) =>
+ p.pat.ker.arg
+ "failed"
+
+ predicates p ==
+ symbol? p => p.pat.sym.pred
+ empty()
+
+ setPredicates(p, l) ==
+ generic? p => (p.pat.sym.pred := l; p)
+ error "Can only attach predicates to generic symbol"
+
+ resetBadValues p ==
+ generic? p => (p.pat.sym.bad := empty()$List(Any); p)
+ error "Can only attach bad values to generic symbol"
+
+ addBadValue(p, a) ==
+ generic? p =>
+ if not member?(a, p.pat.sym.bad) then
+ p.pat.sym.bad := concat(a, p.pat.sym.bad)
+ p
+ error "Can only attach bad values to generic symbol"
+
+ getBadValues p ==
+ generic? p => p.pat.sym.bad
+ error "Not a generic symbol"
+
+ SYM2O p ==
+ sy := (p.val)::O
+ empty?(p.pred) => sy
+ paren infix(" | "::O, sy,
+ reduce("and",[sub("f"::O, i::O) for i in 1..#(p.pred)])$List(O))
+
+ variables p ==
+ constant? p => empty()
+ generic? p => [p]
+ q := p.pat
+ q case ret => empty()
+ q case exp => variables(q.exp.val)
+ q case qot => concat_!(variables(q.qot.num), variables(q.qot.den))
+ q case ker => concat [variables r for r in q.ker.arg]
+ empty()
+
+ PAT2O p ==
+ p case ret => (p.ret)::O
+ p case sym => SYM2O(p.sym)
+ p case exp => (p.exp.val)::O ** (p.exp.exponent)::O
+ p case qot => (p.qot.num)::O / (p.qot.den)::O
+ p.ker.tag = PAT_PLUS => LPAT2O("+", p.ker.arg)
+ p.ker.tag = PAT_TIMES => LPAT2O("*", p.ker.arg)
+ p.ker.tag = PAT_LIST => (p.ker.arg)::O
+ p.ker.tag = PAT_ZERO => 0::Integer::O
+ p.ker.tag = PAT_ONE => 1::Integer::O
+ l := [x::O for x in p.ker.arg]$List(O)
+ (u:=display(p.ker.op)) case "failed" =>prefix(name(p.ker.op)::O,l)
+ (u::(List O -> O)) l
+
+ patcopy p ==
+ p case ret => [p.ret]
+ p case sym =>
+ [[p.sym.tag, p.sym.val, copy(p.sym.pred), copy(p.sym.bad)]$RSY]
+ p case ker=>[[p.ker.tag,p.ker.op,[copy x for x in p.ker.arg]]$KER]
+ p case qot => [[copy(p.qot.num), copy(p.qot.den)]$QOT]
+ [[copy(p.exp.val), p.exp.exponent]$REC]
+
+ pateq?(p1, p2) ==
+ p1 case ret => (p2 case ret) and (p1.ret = p2.ret)
+ p1 case qot =>
+ (p2 case qot) and (p1.qot.num = p2.qot.num)
+ and (p1.qot.den = p2.qot.den)
+ p1 case sym =>
+ (p2 case sym) and (p1.sym.val = p2.sym.val)
+ and {p1.sym.pred} =$Set(Any) {p2.sym.pred}
+ and {p1.sym.bad} =$Set(Any) {p2.sym.bad}
+ p1 case ker =>
+ (p2 case ker) and (p1.ker.tag = p2.ker.tag)
+ and (p1.ker.op = p2.ker.op) and (p1.ker.arg = p2.ker.arg)
+ (p2 case exp) and (p1.exp.exponent = p2.exp.exponent)
+ and (p1.exp.val = p2.exp.val)
+
+ retractIfCan(p:%):Union(SY, "failed") ==
+ symbol? p => p.pat.sym.val
+ "failed"
+
+ mkrsy(t, c?, o?, m?) ==
+ c? => [0, t, empty(), empty()]
+ mlt := (m? => SYM_MULTIPLE; 0)
+ opt := (o? => SYM_OPTIONAL; 0)
+ [Or(Or(SYM_GENERIC, mlt), opt), t, empty(), empty()]
+
+ patternVariable(sy, c?, o?, m?) ==
+ rsy := mkrsy(sy, c?, o?, m?)
+ mkPat(zero?(rsy.tag), [rsy], 0)
+
+@
+\section{package PATTERN1 PatternFunctions1}
+<<package PATTERN1 PatternFunctions1>>=
+)abbrev package PATTERN1 PatternFunctions1
+++ Utilities for handling patterns
+++ Author: Manuel Bronstein
+++ Date Created: 28 Nov 1989
+++ Date Last Updated: 5 Jul 1990
+++ Description: Tools for patterns;
+++ Keywords: pattern, matching.
+PatternFunctions1(R:SetCategory, D:Type): with
+ suchThat : (Pattern R, D -> Boolean) -> Pattern R
+ ++ suchThat(p, f) makes a copy of p and adds the predicate
+ ++ f to the copy, which is returned.
+ suchThat : (Pattern R, List(D -> Boolean)) -> Pattern R
+ ++ \spad{suchThat(p, [f1,...,fn])} makes a copy of p and adds the
+ ++ predicate f1 and ... and fn to the copy, which is returned.
+ suchThat : (Pattern R, List Symbol, List D -> Boolean) -> Pattern R
+ ++ \spad{suchThat(p, [a1,...,an], f)} returns a copy of p with
+ ++ the top-level predicate set to \spad{f(a1,...,an)}.
+ predicate : Pattern R -> (D -> Boolean)
+ ++ predicate(p) returns the predicate attached to p, the
+ ++ constant function true if p has no predicates attached to it.
+ satisfy? : (D, Pattern R) -> Boolean
+ ++ satisfy?(v, p) returns f(v) where f is the predicate
+ ++ attached to p.
+ satisfy? : (List D, Pattern R) -> Boolean
+ ++ \spad{satisfy?([v1,...,vn], p)} returns \spad{f(v1,...,vn)}
+ ++ where f is the
+ ++ top-level predicate attached to p.
+ addBadValue: (Pattern R, D) -> Pattern R
+ ++ addBadValue(p, v) adds v to the list of "bad values" for p;
+ ++ p is not allowed to match any of its "bad values".
+ badValues : Pattern R -> List D
+ ++ badValues(p) returns the list of "bad values" for p;
+ ++ p is not allowed to match any of its "bad values".
+ == add
+ A1D ==> AnyFunctions1(D)
+ A1 ==> AnyFunctions1(D -> Boolean)
+ A1L ==> AnyFunctions1(List D -> Boolean)
+
+ applyAll: (List Any, D) -> Boolean
+ st : (Pattern R, List Any) -> Pattern R
+
+ st(p, l) == withPredicates(p, concat(predicates p, l))
+ predicate p == applyAll(predicates p, #1)
+ addBadValue(p, v) == addBadValue(p, coerce(v)$A1D)
+ badValues p == [retract(v)$A1D for v in getBadValues p]
+ suchThat(p, l, f) == setTopPredicate(copy p, l, coerce(f)$A1L)
+ suchThat(p:Pattern R, f:D -> Boolean) == st(p, [coerce(f)$A1])
+ satisfy?(d:D, p:Pattern R) == applyAll(predicates p, d)
+
+ satisfy?(l:List D, p:Pattern R) ==
+ empty?((rec := topPredicate p).var) => true
+ retract(rec.pred)$A1L l
+
+ applyAll(l, d) ==
+ for f in l repeat
+ not(retract(f)$A1 d) => return false
+ true
+
+ suchThat(p:Pattern R, l:List(D -> Boolean)) ==
+ st(p, [coerce(f)$A1 for f in l])
+
+@
+\section{package PATTERN2 PatternFunctions2}
+<<package PATTERN2 PatternFunctions2>>=
+)abbrev package PATTERN2 PatternFunctions2
+++ Lifting of maps to patterns
+++ Author: Manuel Bronstein
+++ Date Created: 28 Nov 1989
+++ Date Last Updated: 12 Jan 1990
+++ Description: Lifts maps to patterns;
+++ Keywords: pattern, matching.
+PatternFunctions2(R:SetCategory, S:SetCategory): with
+ map: (R -> S, Pattern R) -> Pattern S
+ ++ map(f, p) applies f to all the leaves of p and
+ ++ returns the result as a pattern over S.
+ == add
+ map(f, p) ==
+ (r := (retractIfCan p)@Union(R, "failed")) case R =>
+ f(r::R)::Pattern(S)
+ (u := isOp p) case Record(op:BasicOperator, arg:List Pattern R) =>
+ ur := u::Record(op:BasicOperator, arg:List Pattern R)
+ (ur.op) [map(f, x) for x in ur.arg]
+ (v := isQuotient p) case Record(num:Pattern R, den:Pattern R) =>
+ vr := v::Record(num:Pattern R, den:Pattern R)
+ map(f, vr.num) / map(f, vr.den)
+ (l := isPlus p) case List(Pattern R) =>
+ reduce("+", [map(f, x) for x in l::List(Pattern R)])
+ (l := isTimes p) case List(Pattern R) =>
+ reduce("*", [map(f, x) for x in l::List(Pattern R)])
+ (x := isPower p) case
+ Record(val:Pattern R, exponent: Pattern R) =>
+ xr := x::Record(val:Pattern R, exponent: Pattern R)
+ map(f, xr.val) ** map(f, xr.exponent)
+ (w := isExpt p) case
+ Record(val:Pattern R, exponent: NonNegativeInteger) =>
+ wr := w::Record(val:Pattern R, exponent: NonNegativeInteger)
+ map(f, wr.val) ** wr.exponent
+ sy := retract(p)@Symbol
+ setPredicates(sy::Pattern(S), copy predicates p)
+
+@
+\section{category PATAB Patternable}
+<<category PATAB Patternable>>=
+)abbrev category PATAB Patternable
+++ Category of sets that can be converted to useful patterns
+++ Author: Manuel Bronstein
+++ Date Created: 29 Nov 1989
+++ Date Last Updated: 29 Nov 1989
+++ Description:
+++ An object S is Patternable over an object R if S can
+++ lift the conversions from R into \spadtype{Pattern(Integer)} and
+++ \spadtype{Pattern(Float)} to itself;
+++ Keywords: pattern, matching.
+Patternable(R:Type): Category == with
+ if R has ConvertibleTo Pattern Integer then
+ ConvertibleTo Pattern Integer
+ if R has ConvertibleTo Pattern Float then
+ ConvertibleTo Pattern Float
+
+@
+\section{License}
+<<license>>=
+--Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+--All rights reserved.
+--
+--Redistribution and use in source and binary forms, with or without
+--modification, are permitted provided that the following conditions are
+--met:
+--
+-- - Redistributions of source code must retain the above copyright
+-- notice, this list of conditions and the following disclaimer.
+--
+-- - Redistributions in binary form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in
+-- the documentation and/or other materials provided with the
+-- distribution.
+--
+-- - Neither the name of The Numerical ALgorithms Group Ltd. nor the
+-- names of its contributors may be used to endorse or promote products
+-- derived from this software without specific prior written permission.
+--
+--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+--IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+--TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+--PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+--OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+--EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+--PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+--PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+--LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+--NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+--SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+@
+<<*>>=
+<<license>>
+
+<<domain PATTERN Pattern>>
+<<package PATTERN1 PatternFunctions1>>
+<<package PATTERN2 PatternFunctions2>>
+<<category PATAB Patternable>>
+@
+\eject
+\begin{thebibliography}{99}
+\bibitem{1} nothing
+\end{thebibliography}
+\end{document}