The latest GHC chokes on the latest HaskellDirect file src/Utils.lhs.
Here is a copy of error message and attached is the src/Utils.lhs file.
It will be seen from the file that ghc is objecting to an explicit
universal quantification. What should I do?
------------------------------------------------------------------------
===fptools== Recursively making `all' in src lib examples doc ...
PWD = /export/ger/fptools/hdirect
------------------------------------------------------------------------
------------------------------------------------------------------------
==fptools== gmake all -r;
in /export/ger/fptools/hdirect/src
------------------------------------------------------------------------
../../ghc/driver/ghc -syslib exts -Rghc-timing -H16m -W -recomp -O -O2-for-C -H30m
-c Utils.lhs -o Utils.o -osuf o
ghc: ignoring heap-size-setting option (-H16m)...not the largest seen
Utils.lhs:345: parse error on input `.'
Compilation had errors
%
% @(#) $Docid: May. 24th 1999 17:42 Sigbjorn Finne $
% @(#) $Contactid: [EMAIL PROTECTED] $
%
\begin{code}
module Utils
( showOct
, showHex
, mapFromMb
, mapMb
, mapMbM
, concMaybe
, split
, prefix
, traceIf
, elemBy
, mapUnzip
, diff
, deEscapeString
, (#)
--,UNUSED: catMapMaybes
, dropSuffix
-- re-exported
, trace
, tryOpen
, basename
, prefixDir
, hdirect_root
, bailIf
, decons
, safe_init
, mapAccumLM
, readTaggedFields
, read_int
, read_string
, read_bool
, read_qid
, FieldInfo(..)
) where
--import NumExts
import Char (chr, ord, readLitChar, isSpace, isAlphaNum)
import IOExts
import IO
{- BEGIN_GHC_ONLY
import Directory
END_GHC_ONLY -}
import Monad ( when )
import List ( mapAccumL, nub, isPrefixOf )
infixl 1 #
\end{code}
A convenience operator for invoking methods on objects:
\begin{code}
obj # meth = meth obj
\end{code}
Until NumExts is commonly available, we define the following show functions here:
\begin{code}
showIntAtBase :: Integral a => a -> (a -> Char) -> a -> ShowS
showIntAtBase base toChr n r
| n < 0 = '-':showIntAtBase 10 toChr (negate n) r
| otherwise =
case quotRem n base of { (n', d) ->
case toChr d of { ch ->
let
r' = ch : r
in
if n' == 0 then r' else showIntAtBase base toChr n' r'
}}
showHex :: Integral a => a -> ShowS
showHex n r =
showString "0x" $
showIntAtBase 16 (toChrHex) n r
where
toChrHex d
| d < 10 = chr (ord_0 + fromIntegral d)
| otherwise = chr (ord 'a' + fromIntegral (d - 10))
showOct :: Integral a => a -> ShowS
showOct n r =
showString "0o" $
showIntAtBase 8 (toChrOct) n r
where toChrOct d = chr (ord_0 + fromIntegral d)
ord_0 :: Num a => a
ord_0 = fromInt (ord '0')
\end{code}
Mapping from a Maybe:
\begin{code}
mapFromMb :: b -> (a -> b) -> Maybe a -> b
mapFromMb d f mb = case mb of Nothing -> d ; Just v -> f v
\end{code}
\begin{code}
split :: Eq a => a -> [a] -> [[a]]
split a [] = []
split a as =
case break (==a) as of
(xs,[]) -> [xs]
(xs,_:ys) -> xs:split a ys
\end{code}
\begin{code}
prefix :: Eq a => [a] -> [a] -> Maybe [a] -- what's left
prefix [] ls = Just ls
prefix ls [] = Nothing
prefix (x:xs) (y:ys)
| x == y = prefix xs ys
| otherwise = Nothing
\end{code}
\begin{code}
traceIf :: Bool -> String -> a -> a
traceIf True str v = trace str v
traceIf _ _ v = v
elemBy :: (a -> Bool) -> [a] -> Bool
elemBy isEqual [] = False
elemBy isEqual (y:ys) = isEqual y || elemBy isEqual ys
mapUnzip :: (a -> (b,c)) -> [a] -> ([b],[c])
mapUnzip f [] = ([],[])
mapUnzip f (x:xs) =
let
(a, b) = f x
(as,bs) = mapUnzip f xs
in
(a:as,b:bs)
\end{code}
Returns list of deltas, i.e,
@
diff [x0,x1..xp,xn] = [x0, x1-x0, .., xp - xn]
@
\begin{code}
diff :: Num a => [a] -> [a]
diff ls = snd (mapAccumL ( \ acc v -> (v, v - acc)) 0 ls)
\end{code}
\begin{code}
catMapMaybes :: (a -> b) -> [Maybe a] -> [b]
catMapMaybes f ls = [f x | Just x <- ls]
\end{code}
Dropping the extension off of a filename:
\begin{code}
dropSuffix :: String -> String
dropSuffix str =
case dropWhile (\ch -> ch /= '.' && ch /= '/' && ch /= '\\' )
(reverse str) of
('.':rs) -> reverse rs
_ -> str
-- give up if we reach a separator (/ or \) or end of list.
dropPrefix :: Eq a => [a] -> [a] -> [a]
dropPrefix [] ys = ys
dropPrefix xs [] = []
dropPrefix (x:xs) (y:ys)
| x == y = dropPrefix xs ys
| otherwise = y:ys
\end{code}
Slightly generalised version of code found in Green Card's front end:
\begin{code}
tryOpen :: Bool
-> [FilePath]
-> [String]
-> FilePath
-> IO (Maybe FilePath)
tryOpen verbose path exts name =
doUntil (mbOpenFile verbose) (allFileNames path name exts)
doUntil :: (a -> IO (Maybe b)) -> [a] -> IO (Maybe b)
doUntil f [] = return Nothing
doUntil f (a:as) = do
v <- f a
case v of
Nothing -> doUntil f as
Just k -> return v
allFileNames :: [String] -> String -> [String] -> [String]
allFileNames path file exts
= [addSuffix '/' d ++ file ++ (prefixWith '.' ext) | d <- path, ext <- exts]
where
addSuffix ch [] = []
addSuffix ch ls =
case (decons ls) of
(xs,x)
| x == ch -> ls
| otherwise -> ls++[ch]
prefixWith ch [] = []
prefixWith ch ls@(x:xs)
| ch == x = ls
| otherwise = ch:ls
\end{code}
Combining <tt>last</tt> and <tt>init</tt> into one (pass
over the list):
\begin{code}
decons :: [a] -> ([a],a)
decons xs = trundle xs
where
trundle [] = error "decons: empty list"
trundle [x] = ([], x)
trundle (x:xs) = let (ls, l) = trundle xs in (x:ls, l)
\end{code}
Try reading a file:
\begin{code}
mbOpenFile :: Bool -> FilePath -> IO (Maybe FilePath)
mbOpenFile verbose fpath = do
-- I seem to remember that Hugs doesn't support Directory...
{- BEGIN_GHC_ONLY
flg <- doesFileExist fpath
END_GHC_ONLY -}
{- BEGIN_NOT_FOR_GHC -}
flg <- (openFile fpath ReadMode >>= \ h -> hClose h >> return True)
`catch` (\ _ -> return False)
{- END_NOT_FOR_GHC -}
if not flg
then return Nothing
else do
when verbose (hPutStrLn stderr ("Reading file: " ++ show fpath))
return (Just fpath)
\end{code}
\begin{code}
basename :: String -> String
basename str = go str str
where
-- bi-lingual, the upshot of which is that
-- / isn't allowed in DOS-style paths (and vice
-- versa \ isn't allowed in POSIX(?) style pathnames).
go acc [] = acc
go acc ('/':xs) = go xs xs
go acc ('\\':xs) = go xs xs
go acc (_:xs) = go acc xs
prefixDir :: String -> String -> String
prefixDir [] rest = rest
prefixDir ['/'] rest = '/':rest
prefixDir ['\\'] rest = '/':rest
prefixDir [x] rest = x:'/':rest
prefixDir (x:xs) rest = x : prefixDir xs rest
\end{code}
Removing escape char from double quotes:
\begin{code}
deEscapeString :: String -> String
deEscapeString [] = []
deEscapeString ls@('\\':x:xs) =
case x of
'"' -> x : deEscapeString xs
_ ->
case readLitChar ls of
((ch,rs):_) -> ch : deEscapeString rs
_ -> '\\':x: deEscapeString xs
deEscapeString (x:xs) = x: deEscapeString xs
\end{code}
The top of the HaskellDirect Registry tree:
\begin{code}
hdirect_root = "Software\\Haskell\\HaskellDirect"
-- sporadically handy in a monadic context.
bailIf :: Bool -> a -> a -> a
bailIf True a b = a
bailIf _ _ b = b
\end{code}
Avoids Haskell version trouble:
\begin{code}
mapMb :: (a -> b) -> Maybe a -> Maybe b
mapMb f Nothing = Nothing
mapMb f (Just c) = Just (f c)
mapMbM :: (Monad m) => (a -> m b) -> Maybe a -> m (Maybe b)
mapMbM f Nothing = return Nothing
mapMbM f (Just c) = f c >>= return.Just
concMaybe :: Maybe a -> Maybe a -> Maybe a
concMaybe v@(Just x) _ = v
concMaybe _ v = v
\end{code}
\begin{code}
safe_init :: [a] -> [a]
safe_init [] = []
safe_init ls = init ls
\end{code}
\begin{code}
mapAccumLM :: (Monad m)
=> (acc -> x -> m (acc, y)) -- Function of elt of input list
-- and accumulator, returning new
-- accumulator and elt of result list
-> acc -- Initial accumulator
-> [x] -- Input list
-> m (acc, [y]) -- Final accumulator and result list
mapAccumLM f s [] = return (s, [])
mapAccumLM f s (x:xs) = do
(s', y) <- f s x
(s'',ys) <- mapAccumLM f s' xs
return (s'',y:ys)
\end{code}
\begin{code}
data FieldInfo a
= forall i . -- not really needed, but convenient.
FieldInfo
String -- field label
Bool -- True => optional
(String -> Maybe (i,String))
(i -> a -> a)
readTaggedFields :: [FieldInfo a]
-> (String -> a)
-> String
-> ([a],[String])
readTaggedFields finfo init_val = \ str -> go [] [] (consumeWhiteSpace str)
where
go vals errs [] = (reverse vals, reverse errs)
go vals errs str =
case readTaggedField finfo init_val str of
Left (v, rs, warns) -> go (v:vals) (warns ++ errs) (consumeWhiteSpace rs)
Right (_,non_occs, warns, rs, _) ->
let
rs' = dropWhile (/= '}') rs
in
go vals (map missingField non_occs ++ warns ++ errs) (consumeWhiteSpace rs')
readField :: [FieldInfo a]
-> a
-> String
-> Either (a,String,[String])
([String],[String],[String],String,a)
readField finfo val = \ str ->
case (readTags val str [] []) of
(val, occs, errs, rs)
| allOptionsThere occs -> Left (val, rs, errs)
| otherwise -> Right (nub occs, notOccs occs, errs, rs, val)
where
notOccs occs =
filter (\ x -> not (isOptional x) && not (x `elem` occs)) not_opt_labels
allOptionsThere occs = all (\ x -> x `elem` occs) not_opt_labels
isOptional x =
case (filter (\ (FieldInfo y _ _ _) -> y == x) finfo) of
(FieldInfo _ is_opt _ _):_ -> is_opt
_ -> False
not_opt_labels =
map (\ (FieldInfo s _ _ _) -> s) $
filter (\ (FieldInfo _ is_opt _ _) -> not is_opt) finfo
peelOfSeps xs str =
let
str' = consumeWhiteSpace str
go xs [] = xs
go xs (l:ls)
| l `isPrefixOf` xs = dropPrefix l xs
| otherwise = go xs ls
in
go str' xs
peelOfFieldSep = peelOfSeps labSeps
peelOfSep = peelOfSeps [fieldSep]
-- hard-wire these
fieldSep = ";"
labSeps = [":","="]
term_string = "}"
readTags val str occs errs =
let
str' = consumeWhiteSpace str
final_str = dropPrefix term_string str'
in
if term_string `isPrefixOf` str' then
(val, occs, errs, final_str)
else
case (span isIdentChar str') of
(tag,xs) ->
let
str' = consumeWhiteSpace (peelOfFieldSep xs)
-- unrecognised tag; spool its past value and cont..
str'' = peelOfSep (dropWhile (not.isSpace) str')
in
case lookupTag finfo tag of
Nothing -> readTags val str'' occs (unknownTag tag : errs)
Just (is_opt, rd_n_upd) ->
case rd_n_upd str' of
Nothing -> readTags val str'' occs (unknownValue tag str' :errs)
Just (updater,str'') ->
let
new_str = peelOfSep (consumeWhiteSpace str'')
new_val = updater val
in
readTags new_val new_str (tag:occs) errs
readTaggedField :: [FieldInfo a]
-> (String -> a)
-> String
-> Either (a,String,[String])
([String],[String],[String],String,a)
readTaggedField finfo init_val = \ str ->
case span (isIdentChar) str of
(tag, rs) ->
let
val = init_val tag
str' = consumeWhiteSpace (dropPrefix "{" (consumeWhiteSpace rs))
in
readField finfo val str'
isIdentChar :: Char -> Bool
isIdentChar x = isAlphaNum x || x `elem` ['_','\'']
missingField :: String -> String
missingField tag = "required tag " ++ show tag ++ " not found."
unknownTag :: String -> String
unknownTag tag =
"tag " ++ show tag ++ " not found (ignored)."
unknownValue :: String -> String -> String
unknownValue tag str =
"tag " ++ show tag ++ " had illegal field val: " ++ take 10 str
consumeWhiteSpace :: String -> String
consumeWhiteSpace xs =
case (dropWhile isSpace xs) of
'#':xs -> dropWhile (/='\n') xs
ls -> ls
lookupTag :: [FieldInfo a] -> String -> Maybe (Bool, String -> Maybe (a->a, String))
lookupTag [] tag = Nothing
lookupTag (x@(FieldInfo str is_opt _ _):xs) tag
| str == tag =
let
combineFields (FieldInfo _ _ rd upd) =
\ str -> case rd str of { Nothing -> Nothing ; Just (i,str') -> Just (upd
i,str') }
in
Just (is_opt, combineFields x)
| otherwise = lookupTag xs tag
read_int :: String -> Maybe (Int, String)
read_int str =
case reads str of
((x,str'):_) -> Just ((x::Int), str')
_ -> Nothing
read_string :: String -> Maybe (String, String)
read_string str =
case reads str of
((x,str'):_) -> Just ((x::String), str')
_ -> Nothing
read_id :: String -> Maybe (String, String)
read_id str =
case lex str of
((x,str'):_) -> Just ((x::String), str')
_ -> Nothing
read_qid :: String -> Maybe (String, String)
read_qid str =
case lex str of
((x,str'):_) ->
case str' of
'.':xs -> case lex xs of
((y,ys):_) -> Just (x ++ '.':y, ys)
_ -> Just ((x::String), str')
_ -> Just ((x::String), str')
_ -> Nothing
read_bool :: String -> Maybe (Bool, String)
read_bool str =
case reads str of
((x,str'):_) -> Just ((x::Bool), str')
_ -> Nothing
\end{code}