% Utils.lhs - utility functions for the HPG
% @(#)Utils.lhs 1.20 dated 92/07/20 at 17:30:41
% Crown Copyright 1991
\section{Utility functions}
This module contains useful utility functions needed throughout the \HPG.
\begin{haskell}
> module Utils (
> cmap, rep, print_str, split_str, finish
> ) where
> import Char
> import Config
> import Types
> import Env
\end{haskell}
\prog{cmap xcs xsc} applies \prog{xsc} to a list of values, being those
values which the \prog{xcs} supply to their continuations.
It is easier to read than to describe$\ldots$
\begin{verbatim}
cmap :: [(Xcont x) -> Cont] -> (Xscont x) -> Cont
cmap [] xsc = xsc []
cmap (xc:xcs) xsc = xc (\x -> cmap xcs (\xs -> xsc (x:xs)))
\end{verbatim}
We can transform the inner lambda abstraction by noting that:
\begin{verbatim}
(\xs -> xsc (x:xs)) == xsc . (:) x
\end{verbatim}
We can then transform the remaining lambda abstraction by noting that:
\begin{verbatim}
(\x -> cmap xcs (xsc . (:) x)) == cmap xcs . (.) xsc . (:)
\end{verbatim}
Thus the final version of \prog{cmap} is:
\begin{haskell}
> cmap :: [(Xcont x) -> Cont] -> (Xscont x) -> Cont
> cmap [] xsc = xsc []
> cmap (xc:xcs) xsc = xc (cmap xcs . (.) xsc . (:))
\end{haskell}
\prog{rep n x} is a list of \prog{n} copies of \prog{x}.
It is taken from the Miranda prelude.
\begin{haskell}
> rep :: Int -> x -> [x]
> rep n x = take n (repeat x)
\end{haskell}
\prog{print\_str s c} prints the string \prog{s} on the standard output and
then executes its continuation, \prog{c}.
\begin{haskell}
> print_str :: String -> Cont -> Cont
> print_str s c = get_output (\ op e -> op s >> c e)
\end{haskell}
\prog{split\_str n s} splits the string \prog{s} into lines by inserting
new line characters at whitespace, roughly every \prog{n}
characters.
By means of a considerable kludge, it takes account of any existing new
line characters in \prog{s}.
\begin{haskell}
> split_str :: Int -> String -> String
> split_str n "" = ""
> split_str n s = start ++ next ++ "\n"
> ++ split_str n (dropWhile isSpace rest)
> where
> (start, rest1) = split_num n s
> (next, rest) = span (not . isSpace) rest1
> split_num 0 s = ("", s)
> split_num _ "" = ("", "")
> split_num _ ('\n':cs) = ("", ' ':cs)
> split_num m (c:cs) = (c:cs', cs'')
> where
> (cs',cs'') = split_num (m-one) cs
\end{haskell}
\prog{finish} is a continuation which does nothing.
\begin{haskell}
> finish :: Cont
> finish e = return ()
\end{haskell}
|