1 (* Title: Tools/code/code_haskell.ML
2 Author: Florian Haftmann, TU Muenchen
4 Serializer for Haskell.
7 signature CODE_HASKELL =
9 val setup: theory -> theory
12 structure Code_Haskell : CODE_HASKELL =
15 val target = "Haskell";
17 open Basic_Code_Thingol;
24 (** Haskell serializer **)
26 fun print_haskell_stmt labelled_name syntax_class syntax_tyco syntax_const
27 reserved deresolve contr_classparam_typs deriving_show =
29 val deresolve_base = Long_Name.base_name o deresolve;
30 fun class_name class = case syntax_class class
31 of NONE => deresolve class
32 | SOME class => class;
33 fun print_typcontext tyvars vs = case maps (fn (v, sort) => map (pair v) sort) vs
35 | classbinds => enum "," "(" ")" (
37 str (class_name class ^ " " ^ lookup_var tyvars v)) classbinds)
39 fun print_typforall tyvars vs = case map fst vs
41 | vnames => str "forall " :: Pretty.breaks
42 (map (str o lookup_var tyvars) vnames) @ str "." @@ Pretty.brk 1;
43 fun print_tyco_expr tyvars fxy (tyco, tys) =
44 brackify fxy (str tyco :: map (print_typ tyvars BR) tys)
45 and print_typ tyvars fxy (tycoexpr as tyco `%% tys) = (case syntax_tyco tyco
46 of NONE => print_tyco_expr tyvars fxy (deresolve tyco, tys)
47 | SOME (i, print) => print (print_typ tyvars) fxy tys)
48 | print_typ tyvars fxy (ITyVar v) = (str o lookup_var tyvars) v;
49 fun print_typdecl tyvars (vs, tycoexpr) =
50 Pretty.block (print_typcontext tyvars vs @| print_tyco_expr tyvars NOBR tycoexpr);
51 fun print_typscheme tyvars (vs, ty) =
52 Pretty.block (print_typforall tyvars vs @ print_typcontext tyvars vs @| print_typ tyvars NOBR ty);
53 fun print_term tyvars thm vars fxy (IConst c) =
54 print_app tyvars thm vars fxy (c, [])
55 | print_term tyvars thm vars fxy (t as (t1 `$ t2)) =
56 (case Code_Thingol.unfold_const_app t
57 of SOME app => print_app tyvars thm vars fxy app
60 print_term tyvars thm vars NOBR t1,
61 print_term tyvars thm vars BR t2
63 | print_term tyvars thm vars fxy (IVar NONE) =
65 | print_term tyvars thm vars fxy (IVar (SOME v)) =
66 (str o lookup_var vars) v
67 | print_term tyvars thm vars fxy (t as _ `|=> _) =
69 val (binds, t') = Code_Thingol.unfold_pat_abs t;
70 val (ps, vars') = fold_map (print_bind tyvars thm BR o fst) binds vars;
71 in brackets (str "\\" :: ps @ str "->" @@ print_term tyvars thm vars' NOBR t') end
72 | print_term tyvars thm vars fxy (ICase (cases as (_, t0))) =
73 (case Code_Thingol.unfold_const_app t0
74 of SOME (c_ts as ((c, _), _)) => if is_none (syntax_const c)
75 then print_case tyvars thm vars fxy cases
76 else print_app tyvars thm vars fxy c_ts
77 | NONE => print_case tyvars thm vars fxy cases)
78 and print_app_expr tyvars thm vars ((c, (_, tys)), ts) = case contr_classparam_typs c
79 of [] => (str o deresolve) c :: map (print_term tyvars thm vars BR) ts
81 val ts_fingerprint = ts ~~ take (length ts) fingerprint;
82 val needs_annotation = forall (fn (_, NONE) => true | (t, SOME _) =>
83 (not o Code_Thingol.locally_monomorphic) t) ts_fingerprint;
84 fun print_term_anno (t, NONE) _ = print_term tyvars thm vars BR t
85 | print_term_anno (t, SOME _) ty =
86 brackets [print_term tyvars thm vars NOBR t, str "::", print_typ tyvars NOBR ty];
88 if needs_annotation then
89 (str o deresolve) c :: map2 print_term_anno ts_fingerprint (take (length ts) tys)
90 else (str o deresolve) c :: map (print_term tyvars thm vars BR) ts
92 and print_app tyvars = gen_print_app (print_app_expr tyvars) (print_term tyvars) syntax_const
93 and print_bind tyvars thm fxy p = gen_print_bind (print_term tyvars) thm fxy p
94 and print_case tyvars thm vars fxy (cases as ((_, [_]), _)) =
96 val (binds, body) = Code_Thingol.unfold_let (ICase cases);
97 fun print_match ((pat, ty), t) vars =
99 |> print_bind tyvars thm BR pat
100 |>> (fn p => semicolon [p, str "=", print_term tyvars thm vars NOBR t])
101 val (ps, vars') = fold_map print_match binds vars;
102 in brackify_block fxy (str "let {")
104 (concat [str "}", str "in", print_term tyvars thm vars' NOBR body])
106 | print_case tyvars thm vars fxy (((t, ty), clauses as _ :: _), _) =
108 fun print_select (pat, body) =
110 val (p, vars') = print_bind tyvars thm NOBR pat vars;
111 in semicolon [p, str "->", print_term tyvars thm vars' NOBR body] end;
112 in brackify_block fxy
113 (concat [str "case", print_term tyvars thm vars NOBR t, str "of", str "{"])
114 (map print_select clauses)
117 | print_case tyvars thm vars fxy ((_, []), _) =
118 (brackify fxy o Pretty.breaks o map str) ["error", "\"empty case\""];
119 fun print_stmt (name, Code_Thingol.Fun (_, ((vs, ty), raw_eqs))) =
121 val tyvars = intro_vars (map fst vs) reserved;
124 (str o deresolve_base) name
125 :: map str (replicate n "_")
128 @@ (str o ML_Syntax.print_string
129 o Long_Name.base_name o Long_Name.qualifier) name
131 fun print_eqn ((ts, t), (thm, _)) =
133 val consts = fold Code_Thingol.add_constnames (t :: ts) [];
136 (is_none o syntax_const) deresolve consts
137 |> intro_vars ((fold o Code_Thingol.fold_varnames)
138 (insert (op =)) ts []);
141 (str o deresolve_base) name
142 :: map (print_term tyvars thm vars BR) ts
144 @@ print_term tyvars thm vars NOBR t
150 (str o suffix " ::" o deresolve_base) name,
151 print_typscheme tyvars (vs, ty)
153 :: (case filter (snd o snd) raw_eqs
154 of [] => [print_err ((length o fst o Code_Thingol.unfold_fun) ty)]
155 | eqs => map print_eqn eqs)
158 | print_stmt (name, Code_Thingol.Datatype (_, (vs, []))) =
160 val tyvars = intro_vars (map fst vs) reserved;
164 print_typdecl tyvars (vs, (deresolve_base name, map (ITyVar o fst) vs))
167 | print_stmt (name, Code_Thingol.Datatype (_, (vs, [(co, [ty])]))) =
169 val tyvars = intro_vars (map fst vs) reserved;
173 :: print_typdecl tyvars (vs, (deresolve_base name, map (ITyVar o fst) vs))
175 :: (str o deresolve_base) co
176 :: print_typ tyvars BR ty
177 :: (if deriving_show name then [str "deriving (Read, Show)"] else [])
180 | print_stmt (name, Code_Thingol.Datatype (_, (vs, co :: cos))) =
182 val tyvars = intro_vars (map fst vs) reserved;
183 fun print_co (co, tys) =
185 (str o deresolve_base) co
186 :: map (print_typ tyvars BR) tys
191 :: print_typdecl tyvars (vs, (deresolve_base name, map (ITyVar o fst) vs))
194 :: map ((fn p => Pretty.block [str "| ", p]) o print_co) cos
195 @ (if deriving_show name then [str "deriving (Read, Show)"] else [])
198 | print_stmt (name, Code_Thingol.Class (_, (v, (superclasses, classparams)))) =
200 val tyvars = intro_vars [v] reserved;
201 fun print_classparam (classparam, ty) =
203 (str o deresolve_base) classparam,
205 print_typ tyvars NOBR ty
208 Pretty.block_enclose (
211 Pretty.block (print_typcontext tyvars [(v, map fst superclasses)]),
212 str (deresolve_base name ^ " " ^ lookup_var tyvars v),
216 ) (map print_classparam classparams)
218 | print_stmt (_, Code_Thingol.Classinst ((class, (tyco, vs)), (_, classparam_insts))) =
220 val tyvars = intro_vars (map fst vs) reserved;
221 fun print_instdef ((classparam, c_inst), (thm, _)) = case syntax_const classparam
222 of NONE => semicolon [
223 (str o deresolve_base) classparam,
225 print_app tyvars thm reserved NOBR (c_inst, [])
229 val (c_inst_name, (_, tys)) = c_inst;
230 val const = if (is_some o syntax_const) c_inst_name
231 then NONE else (SOME o Long_Name.base_name o deresolve) c_inst_name;
232 val proto_rhs = Code_Thingol.eta_expand k (c_inst, []);
233 val (vs, rhs) = (apfst o map) fst (Code_Thingol.unfold_abs proto_rhs);
235 |> intro_vars (the_list const)
236 |> intro_vars (map_filter I vs);
237 val lhs = IConst (classparam, (([], []), tys)) `$$ map IVar vs;
238 (*dictionaries are not relevant at this late stage*)
241 print_term tyvars thm vars NOBR lhs,
243 print_term tyvars thm vars NOBR rhs
247 Pretty.block_enclose (
250 Pretty.block (print_typcontext tyvars vs),
251 str (class_name class ^ " "),
252 print_typ tyvars BR (tyco `%% map (ITyVar o fst) vs),
256 ) (map print_instdef classparam_insts)
260 fun haskell_program_of_program labelled_name module_name module_prefix reserved raw_module_alias program =
262 val module_alias = if is_some module_name then K module_name else raw_module_alias;
263 val reserved = Name.make_context reserved;
264 val mk_name_module = mk_name_module reserved module_prefix module_alias program;
265 fun add_stmt (name, (stmt, deps)) =
267 val (module_name, base) = dest_name name;
268 val module_name' = mk_name_module module_name;
269 val mk_name_stmt = yield_singleton Name.variants;
270 fun add_fun upper (nsp_fun, nsp_typ) =
272 val (base', nsp_fun') =
273 mk_name_stmt (if upper then first_upper base else base) nsp_fun
274 in (base', (nsp_fun', nsp_typ)) end;
275 fun add_typ (nsp_fun, nsp_typ) =
277 val (base', nsp_typ') = mk_name_stmt (first_upper base) nsp_typ
278 in (base', (nsp_fun, nsp_typ')) end;
279 val add_name = case stmt
280 of Code_Thingol.Fun _ => add_fun false
281 | Code_Thingol.Datatype _ => add_typ
282 | Code_Thingol.Datatypecons _ => add_fun true
283 | Code_Thingol.Class _ => add_typ
284 | Code_Thingol.Classrel _ => pair base
285 | Code_Thingol.Classparam _ => add_fun false
286 | Code_Thingol.Classinst _ => pair base;
287 fun add_stmt' base' = case stmt
288 of Code_Thingol.Datatypecons _ =>
289 cons (name, (Long_Name.append module_name' base', NONE))
290 | Code_Thingol.Classrel _ => I
291 | Code_Thingol.Classparam _ =>
292 cons (name, (Long_Name.append module_name' base', NONE))
293 | _ => cons (name, (Long_Name.append module_name' base', SOME stmt));
295 Symtab.map_default (module_name', ([], ([], (reserved, reserved))))
296 (apfst (fold (insert (op = : string * string -> bool)) deps))
297 #> `(fn program => add_name ((snd o snd o the o Symtab.lookup program) module_name'))
298 #-> (fn (base', names) =>
299 (Symtab.map_entry module_name' o apsnd) (fn (stmts, _) =>
300 (add_stmt' base' stmts, names)))
302 val hs_program = fold add_stmt (AList.make (fn name =>
303 (Graph.get_node program name, Graph.imm_succs program name))
304 (Graph.strong_conn program |> flat)) Symtab.empty;
305 fun deresolver name = (fst o the o AList.lookup (op =) ((fst o snd o the
306 o Symtab.lookup hs_program) ((mk_name_module o fst o dest_name) name))) name
307 handle Option => error ("Unknown statement name: " ^ labelled_name name);
308 in (deresolver, hs_program) end;
310 fun serialize_haskell module_prefix raw_module_name string_classes labelled_name
311 raw_reserved includes raw_module_alias
312 syntax_class syntax_tyco syntax_const (code_of_pretty, code_writeln) program cs destination =
314 val stmt_names = Code_Target.stmt_names_of_destination destination;
315 val module_name = if null stmt_names then raw_module_name else SOME "Code";
316 val reserved = fold (insert (op =) o fst) includes raw_reserved;
317 val (deresolver, hs_program) = haskell_program_of_program labelled_name
318 module_name module_prefix reserved raw_module_alias program;
319 val contr_classparam_typs = Code_Thingol.contr_classparam_typs program;
320 fun deriving_show tyco =
322 fun deriv _ "fun" = false
323 | deriv tycos tyco = not (tyco = Code_Thingol.fun_tyco)
324 andalso (member (op =) tycos tyco
325 orelse case try (Graph.get_node program) tyco
326 of SOME (Code_Thingol.Datatype (_, (_, cs))) => forall (deriv' (tyco :: tycos))
329 and deriv' tycos (tyco `%% tys) = deriv tycos tyco
330 andalso forall (deriv' tycos) tys
331 | deriv' _ (ITyVar _) = true
332 in deriv [] tyco end;
333 val reserved = make_vars reserved;
334 fun print_stmt qualified = print_haskell_stmt labelled_name
335 syntax_class syntax_tyco syntax_const reserved
336 (if qualified then deresolver else Long_Name.base_name o deresolver)
337 contr_classparam_typs
338 (if string_classes then deriving_show else K false);
339 fun print_module name content =
340 (name, Pretty.chunks [
341 str ("module " ^ name ^ " where {"),
347 fun serialize_module1 (module_name', (deps, (stmts, _))) =
349 val stmt_names = map fst stmts;
350 val qualified = is_none module_name;
351 val imports = subtract (op =) stmt_names deps
353 |> map_filter (try deresolver)
354 |> map Long_Name.qualifier
356 fun print_import_include (name, _) = str ("import qualified " ^ name ^ ";");
357 fun print_import_module name = str ((if qualified
358 then "import qualified "
359 else "import ") ^ name ^ ";");
360 val import_ps = map print_import_include includes @ map print_import_module imports
361 val content = Pretty.chunks2 ((if null import_ps then [] else [Pretty.chunks import_ps])
363 (fn (name, (_, SOME stmt)) => SOME (print_stmt qualified (name, stmt))
364 | (_, (_, NONE)) => NONE) stmts
366 in print_module module_name' content end;
367 fun serialize_module2 (_, (_, (stmts, _))) = Pretty.chunks2 (map_filter
368 (fn (name, (_, SOME stmt)) => if null stmt_names
369 orelse member (op =) stmt_names name
370 then SOME (print_stmt false (name, stmt))
372 | (_, (_, NONE)) => NONE) stmts);
373 val serialize_module =
374 if null stmt_names then serialize_module1 else pair "" o serialize_module2;
375 fun check_destination destination =
376 (File.check destination; destination);
377 fun write_module destination (modlname, content) =
379 val filename = case modlname
380 of "" => Path.explode "Main.hs"
381 | _ => (Path.ext "hs" o Path.explode o implode o separate "/"
382 o Long_Name.explode) modlname;
383 val pathname = Path.append destination filename;
384 val _ = File.mkdir (Path.dir pathname);
385 in File.write pathname
386 ("{-# OPTIONS_GHC -fglasgow-exts #-}\n\n"
387 ^ code_of_pretty content)
390 Code_Target.mk_serialization target NONE
391 (fn NONE => K () o map (code_writeln o snd) | SOME file => K () o map
392 (write_module (check_destination file)))
393 (rpair [] o cat_lines o map (code_of_pretty o snd))
394 (map (uncurry print_module) includes
395 @ map serialize_module (Symtab.dest hs_program))
402 val s = ML_Syntax.print_char c;
403 in if s = "'" then "\\'" else s end;
404 fun numeral_haskell k = if k >= 0 then string_of_int k
405 else Library.enclose "(" ")" (signed_string_of_int k);
407 literal_char = Library.enclose "'" "'" o char_haskell,
408 literal_string = quote o translate_string char_haskell,
409 literal_numeral = numeral_haskell,
410 literal_positive_numeral = numeral_haskell,
411 literal_naive_numeral = numeral_haskell,
412 literal_list = enum "," "[" "]",
413 infix_cons = (5, ":")
417 (** optional monad syntax **)
419 fun pretty_haskell_monad c_bind =
421 fun dest_bind t1 t2 = case Code_Thingol.split_pat_abs t2
422 of SOME ((pat, ty), t') =>
423 SOME ((SOME ((pat, ty), true), t1), t')
425 fun dest_monad c_bind_name (IConst (c, _) `$ t1 `$ t2) =
426 if c = c_bind_name then dest_bind t1 t2
428 | dest_monad _ t = case Code_Thingol.split_let t
429 of SOME (((pat, ty), tbind), t') =>
430 SOME ((SOME ((pat, ty), false), tbind), t')
432 fun implode_monad c_bind_name = Code_Thingol.unfoldr (dest_monad c_bind_name);
433 fun print_monad print_bind print_term (NONE, t) vars =
434 (semicolon [print_term vars NOBR t], vars)
435 | print_monad print_bind print_term (SOME ((bind, _), true), t) vars = vars
436 |> print_bind NOBR bind
437 |>> (fn p => semicolon [p, str "<-", print_term vars NOBR t])
438 | print_monad print_bind print_term (SOME ((bind, _), false), t) vars = vars
439 |> print_bind NOBR bind
440 |>> (fn p => semicolon [str "let", p, str "=", print_term vars NOBR t]);
441 fun pretty _ [c_bind'] print_term thm vars fxy [(t1, _), (t2, _)] = case dest_bind t1 t2
442 of SOME (bind, t') => let
443 val (binds, t'') = implode_monad c_bind' t'
444 val (ps, vars') = fold_map (print_monad (gen_print_bind (K print_term) thm) print_term)
445 (bind :: binds) vars;
447 (brackify fxy o single o enclose "do {" "}" o Pretty.breaks)
448 (ps @| print_term vars' NOBR t'')
450 | NONE => brackify_infix (1, L) fxy
451 [print_term vars (INFX (1, L)) t1, str ">>=", print_term vars (INFX (1, X)) t2]
452 in (2, ([c_bind], pretty)) end;
454 fun add_monad target' raw_c_bind thy =
456 val c_bind = Code.read_const thy raw_c_bind;
457 in if target = target' then
459 |> Code_Target.add_syntax_const target c_bind
460 (SOME (pretty_haskell_monad c_bind))
461 else error "Only Haskell target allows for monad syntax" end;
466 fun isar_seri_haskell module_name =
467 Code_Target.parse_args (Scan.option (Args.$$$ "root" -- Args.colon |-- Args.name)
468 -- Scan.optional (Args.$$$ "string_classes" >> K true) false
469 >> (fn (module_prefix, string_classes) =>
470 serialize_haskell module_prefix module_name string_classes));
473 OuterSyntax.command "code_monad" "define code syntax for monads" OuterKeyword.thy_decl (
474 OuterParse.term_group -- OuterParse.name >> (fn (raw_bind, target) =>
475 Toplevel.theory (add_monad target raw_bind))
479 Code_Target.add_target (target, (isar_seri_haskell, literals))
480 #> Code_Target.add_syntax_tyco target "fun" (SOME (2, fn print_typ => fn fxy => fn [ty1, ty2] =>
481 brackify_infix (1, R) fxy [
482 print_typ (INFX (1, X)) ty1,
484 print_typ (INFX (1, R)) ty2
486 #> fold (Code_Target.add_reserved target) [
487 "hiding", "deriving", "where", "case", "of", "infix", "infixl", "infixr",
488 "import", "default", "forall", "let", "in", "class", "qualified", "data",
489 "newtype", "instance", "if", "then", "else", "type", "as", "do", "module"
491 #> fold (Code_Target.add_reserved target) [
492 "Prelude", "Main", "Bool", "Maybe", "Either", "Ordering", "Char", "String", "Int",
493 "Integer", "Float", "Double", "Rational", "IO", "Eq", "Ord", "Enum", "Bounded",
494 "Num", "Real", "Integral", "Fractional", "Floating", "RealFloat", "Monad", "Functor",
495 "AlreadyExists", "ArithException", "ArrayException", "AssertionFailed", "AsyncException",
496 "BlockedOnDeadMVar", "Deadlock", "Denormal", "DivideByZero", "DotNetException", "DynException",
497 "Dynamic", "EOF", "EQ", "EmptyRec", "ErrorCall", "ExitException", "ExitFailure",
498 "ExitSuccess", "False", "GT", "HeapOverflow",
499 "IOError", "IOException", "IllegalOperation",
500 "IndexOutOfBounds", "Just", "Key", "LT", "Left", "LossOfPrecision", "NoMethodError",
501 "NoSuchThing", "NonTermination", "Nothing", "Obj", "OtherError", "Overflow",
502 "PatternMatchFail", "PermissionDenied", "ProtocolError", "RecConError", "RecSelError",
503 "RecUpdError", "ResourceBusy", "ResourceExhausted", "Right", "StackOverflow",
504 "ThreadKilled", "True", "TyCon", "TypeRep", "UndefinedElement", "Underflow",
505 "UnsupportedOperation", "UserError", "abs", "absReal", "acos", "acosh", "all",
506 "and", "any", "appendFile", "asTypeOf", "asciiTab", "asin", "asinh", "atan",
507 "atan2", "atanh", "basicIORun", "blockIO", "boundedEnumFrom", "boundedEnumFromThen",
508 "boundedEnumFromThenTo", "boundedEnumFromTo", "boundedPred", "boundedSucc", "break",
509 "catch", "catchException", "ceiling", "compare", "concat", "concatMap", "const",
510 "cos", "cosh", "curry", "cycle", "decodeFloat", "denominator", "div", "divMod",
511 "doubleToRatio", "doubleToRational", "drop", "dropWhile", "either", "elem",
512 "emptyRec", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo",
513 "enumFromTo", "error", "even", "exp", "exponent", "fail", "filter", "flip",
514 "floatDigits", "floatProperFraction", "floatRadix", "floatRange", "floatToRational",
515 "floor", "fmap", "foldl", "foldl'", "foldl1", "foldr", "foldr1", "fromDouble",
516 "fromEnum", "fromEnum_0", "fromInt", "fromInteger", "fromIntegral", "fromObj",
517 "fromRational", "fst", "gcd", "getChar", "getContents", "getLine", "head",
518 "id", "inRange", "index", "init", "intToRatio", "interact", "ioError", "isAlpha",
519 "isAlphaNum", "isDenormalized", "isDigit", "isHexDigit", "isIEEE", "isInfinite",
520 "isLower", "isNaN", "isNegativeZero", "isOctDigit", "isSpace", "isUpper", "iterate", "iterate'",
521 "last", "lcm", "length", "lex", "lexDigits", "lexLitChar", "lexmatch", "lines", "log",
522 "logBase", "lookup", "loop", "map", "mapM", "mapM_", "max", "maxBound", "maximum",
523 "maybe", "min", "minBound", "minimum", "mod", "negate", "nonnull", "not", "notElem",
524 "null", "numerator", "numericEnumFrom", "numericEnumFromThen", "numericEnumFromThenTo",
525 "numericEnumFromTo", "odd", "or", "otherwise", "pi", "pred",
526 "print", "product", "properFraction", "protectEsc", "putChar", "putStr", "putStrLn",
527 "quot", "quotRem", "range", "rangeSize", "rationalToDouble", "rationalToFloat",
528 "rationalToRealFloat", "read", "readDec", "readField", "readFieldName", "readFile",
529 "readFloat", "readHex", "readIO", "readInt", "readList", "readLitChar", "readLn",
530 "readOct", "readParen", "readSigned", "reads", "readsPrec", "realFloatToRational",
531 "realToFrac", "recip", "reduce", "rem", "repeat", "replicate", "return", "reverse",
532 "round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq", "sequence",
533 "sequence_", "show", "showChar", "showException", "showField", "showList",
534 "showLitChar", "showParen", "showString", "shows", "showsPrec", "significand",
535 "signum", "signumReal", "sin", "sinh", "snd", "span", "splitAt", "sqrt", "subtract",
536 "succ", "sum", "tail", "take", "takeWhile", "takeWhile1", "tan", "tanh", "threadToIOResult",
537 "throw", "toEnum", "toInt", "toInteger", "toObj", "toRational", "truncate", "uncurry",
538 "undefined", "unlines", "unsafeCoerce", "unsafeIndex", "unsafeRangeSize", "until", "unwords",
539 "unzip", "unzip3", "userError", "words", "writeFile", "zip", "zip3", "zipWith", "zipWith3"
540 ] (*due to weird handling of ':', we can't do anything else than to import *all* prelude symbols*);