bizarre syntax error
I ran into a unfortunate syntax error just now. I figured I'd share it because it's the weirdest message I've ever gotten out of ghc. The broken code is case t of TyApply tv types -> do (tvl, cases) <- lookupDatatype prog tv let tenv = Map.fromList (zip tvl types) -- GHC POINTS HERE caseType (c,vl,e') | Just tl <- List.lookup c cases = if length vl == a then expr prog global (foldl (\e (v,t) -> Map.insert v t e) env (zip vl (map (subst tenv) tl))) e' else typeError ("arity mismatch in pattern: "++show (pretty c)++" expected "++show a++" argument"++(if a == 1 then "" else "s") ++" but got ["++concat (intersperse ", " (map (show . pretty) vl))++"]") where a = length tl -- THIS IS THE PROBLEM | otherwise = typeError ("datatype "++show (pretty tv)++" has no constructor "++show (pretty c)) defaultType Nothing = return [] defaultType (Just (v,e')) = expr prog global (Map.insert v t env) e' >>=. \t -> [t] join t1 t2 | Just t <- unifyS t1 t2 = return t | otherwise = typeError ("failed to unify types "++show (pretty t1)++" and "++show (pretty t2)++" from different case branches") caseResults <- mapM caseType pl defaultResults <- defaultType def foldM1 join (caseResults ++ defaultResults) _ -> typeError ("expected datatype, got "++show (pretty t)) ghc complains that "The last statement in a 'do' construct must be an expression" and points to the line declaring "tenv". The actual problem is that you can't put a "where" block in between two pattern guards. :) Geoffrey
On Jun 27, 2009, at 20:37 , Geoffrey Irving wrote:
"The last statement in a 'do' construct must be an expression"
Right, the "where" terminates the entire expression, you can't use it in the middle like that. I'm pretty sure that's mandatory per the standard, and nobody really wants to open the can of worms involved with allowing its nested use as an extension. (Layout is hard enough to parse already; IIRC, strictly speaking, the behavior specified in the standard is impossible to implement, and even "almost right" is extremely difficult.) Use a subsidiary "let" instead:
caseType (c,vl,e') | Just tl <- let a = length tl in List.lookup c cases = if length vl == a then expr prog global (foldl (\e (v,t) -> Map.insert v t e) env (zip vl (map (subst tenv) tl))) e' else typeError ("arity mismatch in pattern: "++show (pretty c)++"expected"++show a++" argument"++(if a == 1 then "" else "s") ++" but got ["++concat (intersperse ", " (map (show . pretty) vl))++"]")
-- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH
participants (2)
-
Brandon S. Allbery KF8NH -
Geoffrey Irving