%% $Date: 2003/09/15 16:37:46 $ $Author: nthiery $ $Revision: 1.1.1.1 $

\begin{Mhelppage}{Predicate}{N.~Thiéry}

\begin{MInfo}
  \eng{a type for testing object satisfying a given predicate}
  \de {}
\end{MInfo} % end of MInfo

\begin{MIntro}
  \eng{\Margs{predicate} represents the \mupad\ objects which satisfy
    the predicate \Mpar{predicate}.}
  \de {}
\end{MIntro} % end of MIntro

\begin{MCalls}
   \call[testtype]{obj, \Margs{\Mopt{name,} predicate \Mopt{, p1, p2, \Mseq{}}}}
\end{MCalls} % end of MCalls

\begin{MParameters}
  \param{name}
  \eng{a string which will be used for pretty printing the type}
  \param{predicate}
  \eng{a function of one argument which can return \Mup{TRUE},
    \Mup{FALSE} or \Mup{FAIL}}
    \de {}
  \param{obj, p1, p2, \Mseq{}}
    \eng{any \mupad\ objects}
    \de {beliebiges \mupad-Objekten}
\end{MParameters} % end of MParameters

\begin{MReturnValue}
  \eng{see \Mup{testtype}}
  \de {siehe \Mup{testtype}}
\end{MReturnValue} % end of MReturnValue

\MRelatedFunctions{testtype}

\MKeywords{Type}

\begin{MDetails}
  \eng{The call \Mupc{testtype}{obj, \Margs{\Mopt{name,} predicate
        \Mopt{, p1, p2, \Mseq{}}}} test whether \Mpar{obj} satisfies
    \Mpar{predicate}; that is it returns \Mex{predicate(obj, opt1,
      opt2, \Mseq{})}.}
  \de{}
  
  \eng{\Margs{predicate}, \Margs{name, predicate},
    \Margs{predicate\Mopt{, p1, p2, \Mseq{}}}, and \Margs{name,
      predicate\Mopt{, p1, p2, \Mseq{}}} are respectively pretty
    printed as \Mex{Type::Predicate(predicate)}, \Mex{Type::name},
    \Mex{Type::Predicate(p, p1, p2, \Mseq{})}, and
    \Mex{Type::name(p1, p2, \Mseq{})}.}
  \de{}
\end{MDetails} % end of MDetails

\begin{MExample}{ex1}
  \eng{We define a type which contains any \mupad\ object:}
  \begin{Mexin}
t := Type::Predicate(x -> TRUE):
testtype(1, t), testtype(2, t), testtype(x, t)
  \end{Mexin}
  \begin{Mexout}
                       TRUE, TRUE, TRUE
  \end{Mexout}
  \eng{We define a type which contains all the \mupad\ object which
    are solution of \Mex{(x-1)*(x+1)=0}:}
  \begin{Mexin}
t := Type::Predicate(x -> bool((x - 1)*(x + 1) = 0)):
testtype(1, t), testtype(2, t), testtype(x, t)
  \end{Mexin}
  \begin{Mexout}
                      TRUE, FALSE, FALSE
  \end{Mexout}

  \eng{We define a type for partitions, that is decreasing lists of integers:}
  \begin{Mexin}
part :=
    Type::Predicate(l -> _lazy_and(testtype(l, Type::ListOf(Type::Integer)),
                                   bool(revert(sort(l)) = l))):
testtype(a, part), testtype([3, 6, 1], part), testtype([3, 2, 2], part)
  \end{Mexin}
  \begin{Mexout}
                      FALSE, FALSE, TRUE
  \end{Mexout}
  
  \eng{Using the naming facility is recommended to improve the
    readability of error messages:}
  \begin{Mexin}
part :=
    Type::Predicate("Partition",
                    l -> _lazy_and(testtype(l, Type::ListOf(Type::Integer)),
                                   bool(revert(sort(l)) = l))):
f := proc(p: part) begin end:
f(3);
  \end{Mexin}
  \begin{Mexout}
Error: Wrong type of 1. argument (type 'Type::Partition' expec\
ted,
       got argument '3');
during evaluation of 'f'
  \end{Mexout}
\end{MExample} % end of MExample

\begin{MChanges}
  \version{3.0}
  \new
\end{MChanges}

\end{Mhelppage}
%% end of helppage 'Predicate'
