1 ;;; haskell-doc.el --- show function types in echo area
3 ;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
4 ;; Copyright (C) 1997 Hans-Wolfgang Loidl
6 ;; Author: Hans-Wolfgang Loidl <hwloidl@dcs.glasgow.ac.uk>
7 ;; Temporary Maintainer and Hacker: Graeme E Moss <gem@cs.york.ac.uk>
8 ;; Keywords: extensions, minor mode, language mode, Haskell
10 ;; URL: http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/CONTRIB/haskell-modes/emacs/haskell-doc.el?rev=HEAD
15 ;; This program is free software; you can redistribute it and/or modify
16 ;; it under the terms of the GNU General Public License as published by
17 ;; the Free Software Foundation; either version 2, or (at your option)
20 ;; This program is distributed in the hope that it will be useful,
21 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 ;; GNU General Public License for more details.
25 ;; You should have received a copy of the GNU General Public License
26 ;; along with this program; if not, you can either send email to this
27 ;; program's maintainer or write to: The Free Software Foundation,
28 ;; Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA.
33 ;; This program shows the type of the Haskell function under the cursor in the
34 ;; minibuffer. It acts as a kind of "emacs background process", by regularly
35 ;; checking the word under the cursor and matching it against a list of
36 ;; prelude, library, local and global functions.
38 ;; The preferred usage of this package is in combination with
39 ;; `haskell-hugs-mode'.
40 ;; In that case `haskell-doc-mode' checks an internal variable updated by
41 ;; `imenu' to access the types of all local functions. In `haskell-mode' this
42 ;; is not possible. However, types of prelude functions are still shown.
44 ;; To show types of global functions, i.e. functions defined in a module
45 ;; imported by the current module, call the function
46 ;; `turn-on-haskell-doc-global-types'. This automatically loads all modules
47 ;; and builds `imenu' tables to get the types of all functions (again this
48 ;; currently requires `haskell-hugs-mode').
49 ;; Note: The modules are loaded recursively, so you might pull in
50 ;; many modules by just turning on global function support.
51 ;; This features is currently not very well supported.
53 ;; This program was inspired by the `eldoc.el' package by Noah Friedman.
58 ;; One useful way to enable this minor mode is to put the following in your
61 ;; (autoload 'turn-on-haskell-doc-mode "haskell-doc" nil t)
63 ;; and depending on the major mode you use for your Haskell programs:
64 ;; (add-hook 'hugs-mode-hook 'turn-on-haskell-doc-mode) ; hugs-mode
66 ;; (add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode) ; haskell-mode
71 ;; You can control what exactly is shown by setting the following variables to
73 ;; `haskell-doc-show-global-types' (default: nil)
74 ;; `haskell-doc-show-reserved' (default: t)
75 ;; `haskell-doc-show-prelude' (default: t)
76 ;; `haskell-doc-show-strategy' (default: t)
77 ;; `haskell-doc-show-user-defined' (default: t)
79 ;; If you want to define your own strings for some identifiers define an
80 ;; alist of (ID . STRING) and set `haskell-doc-show-user-defined' to t.
83 ;; (setq haskell-doc-show-user-defined t)
84 ;; (setq haskell-doc-user-defined-ids
86 ;; '("main" . "just another pathetic main function")
87 ;; '("foo" . "a very dummy name")
88 ;; '("bar" . "another dummy name")))
90 ;; The following two variables are useful to make the type fit on one line:
91 ;; If `haskell-doc-chop-off-context' is non-nil the context part of the type
92 ;; of a local fct will be eliminated (default: t).
93 ;; If `haskell-doc-chop-off-fctname' is non-nil the function name is not
94 ;; shown together with the type (default: nil).
99 ;; `haskell-doc-mode' is implemented as a minor-mode. So, you can combine it
100 ;; with any other mode. To enable it just type
101 ;; M-x turn-on-haskell-doc-mode
103 ;; These are the names of the functions that can be called directly by the
104 ;; user (with keybindings in `haskell-hugs-mode' and `haskell-mode'):
105 ;; `haskell-doc-mode' ... toggle haskell-doc-mode; with prefix turn it on
106 ;; unconditionally if the prefix is greater 0 otherwise
108 ;; Key: CTRL-c CTRL-o (CTRL-u CTRL-c CTRL-o)
109 ;; `haskell-doc-ask-mouse-for-type' ... show the type of the id under the mouse
110 ;; Key: C-S-M-mouse-3
111 ;; `haskell-doc-show-reserved' ... toggle echoing of reserved id's types
112 ;; `haskell-doc-show-prelude' ... toggle echoing of prelude id's types
113 ;; `haskell-doc-show-strategy' ... toggle echoing of strategy id's types
114 ;; `haskell-doc-show-user-defined' ... toggle echoing of user def id's types
115 ;; `haskell-doc-check-active' ... check whether haskell-doc is active via the
116 ;; `post-command-idle-hook' (for testing);
122 ;; - Fix byte-compile problems in `haskell-doc-prelude-types' for getArgs etc
123 ;; - Write a parser for .hi files and make haskell-doc independent from
124 ;; hugs-mode. Read library interfaces via this parser.
125 ;; - Indicate kind of object with colours
126 ;; - Handle multi-line types
127 ;; - Encode i-am-fct info in the alist of ids and types.
128 ;; - Replace the usage of `post-command-idle-hook' with idle timers
133 ;; - Some prelude fcts aren't displayed properly. This might be due to a
134 ;; name clash of Haskell and Elisp functions (e.g. length) which
135 ;; confuses emacs when reading `haskell-doc-prelude-types'
140 ;; Revision 1.16 2005/11/07 01:28:16 monnier
141 ;; (haskell-doc-xemacs-p, haskell-doc-emacs-p)
142 ;; (haskell-doc-message): Remove.
143 ;; (haskell-doc-is-id-char-at): Remove.
144 ;; (haskell-doc-get-current-word): Rewrite.
146 ;; Revision 1.15 2005/11/04 17:11:12 monnier
149 ;; Revision 1.14 2005/08/24 11:36:32 monnier
150 ;; (haskell-doc-message): Paren typo.
152 ;; Revision 1.13 2005/08/23 19:23:27 monnier
153 ;; (haskell-doc-show-type): Assume that the availability
154 ;; of display-message won't change at runtime.
156 ;; Revision 1.12 2005/07/18 21:04:14 monnier
157 ;; (haskell-doc-message): Remove.
158 ;; (haskell-doc-show-type): inline it. Do nothing for if there's no doc to show.
160 ;; Revision 1.11 2004/12/10 17:33:18 monnier
161 ;; (haskell-doc-minor-mode-string): Make it dynamic.
162 ;; (haskell-doc-install-keymap): Remove conflicting C-c C-o binding.
163 ;; (haskell-doc-mode): Make a nil arg turn the mode ON.
164 ;; (turn-on-haskell-doc-mode): Make it an alias for haskell-doc-mode.
165 ;; (haskell-doc-mode): Don't touch haskell-doc-minor-mode-string.
166 ;; (haskell-doc-show-global-types): Don't touch
167 ;; haskell-doc-minor-mode-string. Call haskell-doc-make-global-fct-index.
168 ;; (haskell-doc-check-active): Fix message.
169 ;; (define-key-after): Don't define.
170 ;; (haskell-doc-install-keymap): Check existence of define-key-after.
172 ;; Revision 1.10 2004/11/25 23:03:23 monnier
173 ;; (haskell-doc-sym-doc): Make even the last char bold.
175 ;; Revision 1.9 2004/11/24 22:14:36 monnier
176 ;; (haskell-doc-install-keymap): Don't blindly assume there's a Hugs menu.
178 ;; Revision 1.8 2004/11/22 10:45:35 simonmar
179 ;; Fix type of getLine
181 ;; Revision 1.7 2004/10/14 22:27:47 monnier
182 ;; (turn-off-haskell-doc-mode, haskell-doc-current-info): Don't autoload.
184 ;; Revision 1.6 2004/10/13 22:45:22 monnier
185 ;; (haskell-doc): New group.
186 ;; (haskell-doc-show-reserved, haskell-doc-show-prelude)
187 ;; (haskell-doc-show-strategy, haskell-doc-show-user-defined)
188 ;; (haskell-doc-chop-off-context, haskell-doc-chop-off-fctname):
189 ;; Make them custom vars.
190 ;; (haskell-doc-keymap): Declare and fill it right there.
191 ;; (haskell-doc-mode): Simplify.
192 ;; (haskell-doc-toggle-var): Make it into what it was supposed to be.
193 ;; (haskell-doc-mode-print-current-symbol-info): Simplify.
194 ;; (haskell-doc-current-info): New autoloaded function.
195 ;; (haskell-doc-sym-doc): New fun extracted from haskell-doc-show-type.
196 ;; (haskell-doc-show-type): Use it.
197 ;; (haskell-doc-wrapped-type-p): Remove unused var `lim'.
198 ;; (haskell-doc-forward-sexp-safe, haskell-doc-current-symbol): Remove. Unused.
199 ;; (haskell-doc-visit-home): Don't require ange-ftp, it's autoloaded.
200 ;; (haskell-doc-install-keymap): Simplify.
202 ;; Revision 1.5 2003/01/09 11:56:26 simonmar
203 ;; Patches from Ville Skyttä <scop@xemacs.org>, the XEmacs maintainer of
206 ;; - Make the auto-mode-alist modifications autoload-only.
208 ;; Revision 1.4 2002/10/14 09:55:03 simonmar
209 ;; Patch to update the Prelude/libraries function names and to remove
210 ;; support for older versions of Haskell.
212 ;; Submitted by: Anders Lau Olsen <alauo@mip.sdu.dk>
214 ;; Revision 1.3 2002/04/30 09:34:37 rrt
215 ;; Remove supporting Haskell 1.4 and 1.2 from the ToDo list. It's Far Too Late.
217 ;; Add (require 'imenu). Thanks to N. Y. Kwok.
219 ;; Revision 1.2 2002/04/23 14:45:10 simonmar
220 ;; Tweaks to the doc strings and support for customization, from
221 ;; Ville Skyttä <scop@xemacs.org>.
223 ;; Revision 1.1 2001/07/19 16:17:36 rrt
224 ;; Add the current version of the Moss/Thorn/Marlow Emacs mode, along with its
225 ;; web pages and sample files. This is now the preferred mode, and the
226 ;; haskell.org pages are being changed to reflect that. Also includes the new
227 ;; GHCi mode from Chris Webb.
229 ;; Revision 1.6 1998/12/10 16:27:25 hwloidl
230 ;; Minor changes ("Doc" as modeline string, mouse-3 moved to C-S-M-mouse-3)
232 ;; Revision 1.5 1998/09/24 14:25:46 gem
233 ;; Fixed minor compatibility bugs with Haskell mode of Moss&Thorn.
234 ;; Disabled M-/ binding.
236 ;; Revision 1.4 1997/11/12 23:51:19 hwloidl
237 ;; Fixed start-up problem under emacs-19.34.
238 ;; Added support for wrapped (multi-line) types and 2 vars to control the
239 ;; behaviour with long fct types
241 ;; Revision 1.3 1997/11/03 00:48:03 hwloidl
242 ;; Major revision for first release.
243 ;; Added alists for showing prelude fcts, haskell syntax, and strategies
244 ;; Added mouse interface to show type under mouse
245 ;; Fixed bug which causes demon to fall over
246 ;; Works now with hugs-mode and haskell-mode under emacs 19.34,20 and xemacs 19.15
253 ;;* Constants and Variables::
254 ;;* Install as minor mode::
255 ;;* Menubar Support::
256 ;;* Haskell Doc Mode::
257 ;;* Switch it on or off::
259 ;;* Top level function::
260 ;;* Mouse interface::
264 ;;* Visit home site::
269 ;;@node top, Constants and Variables, (dir), (dir)
272 ;;@node Constants and Variables, Install as minor mode, top, top
273 ;;@section Constants and Variables
276 ;;* Emacs portability::
277 ;;* Maintenance stuff::
281 ;;* Test membership::
284 ;;@node Emacs portability, Maintenance stuff, Constants and Variables, Constants and Variables
285 ;;@subsection Emacs portability
287 (defgroup haskell-doc nil
288 "Show Haskell function types in echo area."
290 :prefix "haskell-doc-")
292 ;;@node Maintenance stuff, Mode Variable, Emacs portability, Constants and Variables
293 ;;@subsection Maintenance stuff
295 (defconst haskell-doc-version "1.16"
296 "Version of `haskell-doc-mode' as RCS Revision.")
298 (defconst haskell-doc-maintainer
299 "Hans-Wolfgang Loidl <hwloidl@dcs.glasgow.ac.uk>"
300 "Maintainer of `haskell-doc-mode'.")
302 (defconst haskell-doc-ftp-site
303 "/ftp@ftp.dcs.gla.ac.uk:/pub/glasgow-fp/authors/Hans_Loidl/Elisp/"
304 "Main FTP site with latest version of `haskell-doc-mode' and sample files.")
306 ;;@node Mode Variable, Variables, Maintenance stuff, Constants and Variables
307 ;;@subsection Mode Variable
309 (defvar haskell-doc-mode nil
310 "*If non-nil, show the type of the function near point or a related comment.
312 If the identifier near point is a Haskell keyword and the variable
313 `haskell-doc-show-reserved' is non-nil show a one line summary
316 If the identifier near point is a Prelude or one of the standard library
317 functions and `haskell-doc-show-prelude' is non-nil show its type.
319 If the identifier near point is local \(i.e. defined in this module\) check
320 the `imenu' list of functions for the type. This obviously requires that
321 your language mode uses `imenu' \(`haskell-hugs-mode' 0.6 for example\).
323 If the identifier near point is global \(i.e. defined in an imported module\)
324 and the variable `haskell-doc-show-global-types' is non-nil show the type of its
327 If the identifier near point is a standard strategy or a function, type related
328 related to strategies and `haskell-doc-show-strategy' is non-nil show the type
329 of the function. Strategies are special to the parallel execution of Haskell.
330 If you're not interested in that just turn it off.
332 If the identifier near point is a user defined function that occurs as key
333 in the alist `haskell-doc-user-defined-ids' and the variable
334 `haskell-doc-show-user-defined' is non-nil show the type of the function.
336 This variable is buffer-local.")
337 (make-variable-buffer-local 'haskell-doc-mode)
339 (defvar haskell-doc-mode-hook nil
340 "Hook invoked when entering `haskell-doc-mode'.")
342 (defvar haskell-doc-index nil
343 "Variable holding an alist matching file names to fct-type alists.
344 The function `haskell-doc-make-global-fct-index' rebuilds this variables \(similar to an
346 This variable is buffer-local.")
347 (make-variable-buffer-local 'haskell-doc-index)
349 (defcustom haskell-doc-show-global-types nil
350 "If non-nil, search for the types of global functions by loading the files.
351 This variable is buffer-local."
353 (make-variable-buffer-local 'haskell-doc-show-global-types)
355 (defcustom haskell-doc-show-reserved t
356 "If non-nil, show a documentation string for reserved ids.
357 This variable is buffer-local."
359 (make-variable-buffer-local 'haskell-doc-show-reserved)
361 (defcustom haskell-doc-show-prelude t
362 "If non-nil, show a documentation string for prelude functions.
363 This variable is buffer-local."
365 (make-variable-buffer-local 'haskell-doc-show-prelude)
367 (defcustom haskell-doc-show-strategy t
368 "If non-nil, show a documentation string for strategies.
369 This variable is buffer-local."
371 (make-variable-buffer-local 'haskell-doc-show-strategy)
373 (defcustom haskell-doc-show-user-defined t
374 "If non-nil, show a documentation string for user defined ids.
375 This variable is buffer-local."
377 (make-variable-buffer-local 'haskell-doc-show-user-defined)
379 (defcustom haskell-doc-chop-off-context t
380 "If non-nil eliminate the context part in a Haskell type."
383 (defcustom haskell-doc-chop-off-fctname nil
384 "If non-nil omit the function name and show only the type."
387 (defvar haskell-doc-search-distance 40 ; distance in characters
388 "*How far to search when looking for the type declaration of fct under cursor.")
390 ;;@node Variables, Prelude types, Mode Variable, Constants and Variables
391 ;;@subsection Variables
393 (defvar haskell-doc-idle-delay 0.50
394 "*Number of seconds of idle time to wait before printing.
395 If user input arrives before this interval of time has elapsed after the
396 last input, no documentation will be printed.
398 If this variable is set to 0, no idle time is required.")
400 (defvar haskell-doc-argument-case 'identity ; 'upcase
401 "Case to display argument names of functions, as a symbol.
402 This has two preferred values: `upcase' or `downcase'.
403 Actually, any name of a function which takes a string as an argument and
404 returns another string is acceptable.")
406 (defvar haskell-doc-mode-message-commands nil
407 "*Obarray of command names where it is appropriate to print in the echo area.
409 This is not done for all commands since some print their own
410 messages in the echo area, and these functions would instantly overwrite
411 them. But `self-insert-command' as well as most motion commands are good
414 It is probably best to manipulate this data structure with the commands
415 `haskell-doc-add-command' and `haskell-doc-remove-command'.")
417 ;;(cond ((null haskell-doc-mode-message-commands)
418 ;; ;; If you increase the number of buckets, keep it a prime number.
419 ;; (setq haskell-doc-mode-message-commands (make-vector 31 0))
420 ;; (let ((list '("self-insert-command"
421 ;; "next-" "previous-"
422 ;; "forward-" "backward-"
423 ;; "beginning-of-" "end-of-"
429 ;; (setq syms (all-completions (car list) obarray 'fboundp))
430 ;; (setq list (cdr list))
432 ;; (set (intern (car syms) haskell-doc-mode-message-commands) t)
433 ;; (setq syms (cdr syms)))))))
435 ;; Bookkeeping; the car contains the last symbol read from the buffer.
436 ;; The cdr contains the string last displayed in the echo area, so it can
437 ;; be printed again if necessary without reconsing.
438 (defvar haskell-doc-last-data '(nil . nil))
440 (defvar haskell-doc-minor-mode-string
441 '(haskell-doc-show-global-types " DOC" " Doc")
442 "*String to display in mode line when Haskell-Doc Mode is enabled.")
444 (defconst haskell-doc-varlist
448 'haskell-doc-mode-hook
450 'haskell-doc-show-global-types
451 'haskell-doc-show-reserved
452 'haskell-doc-show-prelude
453 'haskell-doc-show-strategy
454 'haskell-doc-show-user-defined
455 'haskell-doc-idle-delay
456 'haskell-doc-argument-case
457 'haskell-doc-mode-message-commands
459 "List of variables sent via `haskell-doc-submit-bug-report'.")
461 ;;@node Prelude types, Test membership, Variables, Constants and Variables
462 ;;@subsection Prelude types
464 ;;@cindex haskell-doc-reserved-ids
466 (defvar haskell-doc-reserved-ids
468 '("case" . "case exp of { alts [;] }")
469 '("class" . "class [context =>] simpleclass [where { cbody [;] }]")
470 '("data" . "data [context =>] simpletype = constrs [deriving]")
471 '("default" . "default (type1 , ... , typen)")
472 '("deriving" . "deriving (dclass | (dclass1, ... , dclassn))") ; used with data or newtype
473 '("do" . "do { stmts [;] } stmts -> exp [; stmts] | pat <- exp ; stmts | let decllist ; stmts")
474 '("else" . "if exp then exp else exp")
475 '("if" . "if exp then exp else exp")
476 '("import" . "import [qualified] modid [as modid] [impspec]")
477 '("in" . "let decllist in exp")
478 '("infix" . "infix [digit] ops")
479 '("infixl" . "infixl [digit] ops")
480 '("infixr" . "infixr [digit] ops")
481 '("instance" . "instance [context =>] qtycls inst [where { valdefs [;] }]")
482 '("let" . "let { decl; ...; decl [;] } in exp")
483 '("module" . "module modid [exports] where body")
484 '("newtype" . "newtype [context =>] simpletype = con atype [deriving]")
485 '("of" . "case exp of { alts [;] }")
486 '("then" . "if exp then exp else exp")
487 '("type" . "type simpletype = type")
488 '("where" . "exp where { decl; ...; decl [;] }") ; check that ; see also class, instance, module
489 '("as" . "import [qualified] modid [as modid] [impspec]")
490 '("qualified" . "import [qualified] modid [as modid] [impspec]")
491 '("hiding" . "hiding ( import1 , ... , importn [ , ] )")
493 "An alist of reserved identifiers and a string describing the construct they are used in.")
495 ;;@cindex haskell-doc-prelude-types
497 (defvar haskell-doc-prelude-types
500 '("!!" . "[a] -> Int -> a")
501 '("$" . "(a -> b) -> a -> b")
502 '("$!" . "(a -> b) -> (a -> b)")
503 '("&&" . "Bool -> Bool -> Bool")
504 '("||" . "Bool -> Bool -> Bool")
505 '("*" . "Num a => a -> a -> a")
506 '("**" . "Floating a => a -> a -> a")
507 '("+" . "Num a => a -> a -> a")
508 '("++" . "[a] -> [a] -> [a]")
509 '("-" . "Num a => a -> a -> a")
510 '("." . "(b -> c) -> (a -> b) -> a -> c")
511 '("/" . "Fractional a => a -> a -> a")
512 '("/=" . "Eq a => a -> a -> Bool")
513 '("<" . "Ord a => a -> a -> Bool")
514 '("<=" . "Ord a => a -> a -> Bool")
515 '("==" . "Eq a => a -> a -> Bool")
516 '("=<<" . "Monad a => (a -> m b) -> m a -> m b")
517 '(">" . "Ord a => a -> a -> Bool")
518 '(">=" . "Ord a => a -> a -> Bool")
519 '(">>" . "Monad m => m a -> m b -> m b")
520 '(">>=" . "Monad m => m a -> (a -> m b) -> m b")
521 '("^" . "(Num a, Integral b) => a -> b -> a")
522 '("^^" . "(Fractional a, Integral b) => a -> b -> a")
523 '("abs" . "Num a => a -> a")
524 '("sequence" . "Monad m => [m a] -> m [a]")
525 '("acos" . "Floating a => a -> a")
526 '("acosh" . "Floating a => a -> a")
527 '("all" . "(a -> Bool) -> [a] -> Bool")
528 '("and" . "[Bool] -> Bool")
529 '("any" . "(a -> Bool) -> [a] -> Bool")
530 '("appendFile" . "FilePath -> String -> IO ()")
531 '("applyM" . "Monad m => (a -> m b) -> m a -> m b")
532 '("asTypeOf" . "a -> a -> a")
533 '("asin" . "Floating a => a -> a")
534 '("asinh" . "Floating a => a -> a")
535 '("atan" . "Floating a => a -> a")
536 '("atan2" . "RealFrac a => a -> a")
537 '("atanh" . "Floating a => a -> a")
538 '("break" . "(a -> Bool) -> [a] -> ([a], [a])")
539 '("catch" . "IO a -> (IOError -> IO a) -> IO a")
540 '("ceiling" . "(RealFrac a, Integral b) => a -> b")
541 '("compare" . "Ord a => a -> a -> Ordering")
542 '("concat" . "MonadPlus m => [m a] -> m a")
543 '("concatMap" . "(a -> [b]) -> [a] -> [b]")
544 '("const" . "a -> b -> a")
545 '("cos" . "Floating a => a -> a")
546 '("cosh" . "Floating a => a -> a")
547 '("curry" . "((a, b) -> c) -> a -> b -> c")
548 '("cycle" . "[a] -> [a]")
549 '("decodeFloat" . "RealFloat a => a -> (Integer, Int)")
550 '("div" . "Integral a => a -> a -> a")
551 '("divMod" . "Integral a => a -> a -> (a, a)")
552 '("drop" . "Int -> [a] -> [a]")
553 '("dropWhile" . "(a -> Bool) -> [a] -> [a]")
554 '("elem" . "Eq a => a -> [a] -> Bool")
555 '("encodeFloat" . "RealFloat a => Integer -> Int -> a")
556 '("enumFrom" . "Enum a => a -> [a]")
557 '("enumFromThen" . "Enum a => a -> a -> [a]")
558 '("enumFromThenTo" . "Enum a => a -> a -> a -> [a]")
559 '("enumFromTo" . "Enum a => a -> a -> [a]")
560 '("error" . "String -> a")
561 '("even" . "Integral a => a -> Bool")
562 '("exp" . "Floating a => a -> a")
563 '("exponent" . "RealFloat a => a -> Int")
564 '("fail" . "Monad m => String -> m a")
565 '("flip" . "(a -> b -> c) -> (b -> a -> c)")
566 '("floatDigits" . "RealFloat a => a -> Int")
567 '("floatRadix" . "RealFloat a => a -> Integer")
568 '("floatRange" . "RealFloat a => a -> (Int, Int)")
569 '("floor" . "(RealFrac a, Integral b) => a -> b")
570 '("foldl" . "(a -> b -> a) -> a -> [b] -> a")
571 '("foldl1" . "(a -> a -> a) -> [a] -> a")
572 '("foldr" . "(a -> b -> b) -> b -> [a] -> b")
573 '("foldr1" . "(a -> a -> a) -> [a] -> a")
574 '("fromEnum" . "Enum a => a -> Int")
575 '("fromInteger" . "Num a => Integer -> a")
576 '("fromIntegral" . "(Integral a, Num b) => a -> b")
577 '("fromRational" . "Fractional a => Rational -> a")
578 '("fst" . "(a, b) -> a")
579 '("gcd" . "(Integral a) => a -> a -> a")
580 '("getChar" . "IO Char")
581 '("getContents" . "IO String")
582 '("getLine" . "IO String")
583 '("head" . "[a] -> a")
585 '("init" . "[a] -> [a]")
586 '("interact" . "(String -> String) -> IO ()")
587 '("ioError" . "IOError -> IO a")
588 '("isDenormalized" . "RealFloat a => a -> Bool")
589 '("isIEEE" . "RealFloat a => a -> Bool")
590 '("isInfinite" . "RealFloat a => a -> Bool")
591 '("isNaN" . "RealFloat a => a -> Bool")
592 '("isNegativeZero" . "RealFloat a => a -> Bool")
593 '("iterate" . "(a -> a) -> a -> [a]")
594 '("last" . "[a] -> a")
595 '("lcm" . "Integral a => a -> a -> a")
596 '("length" . "[a] -> Int")
597 '("lex" . "ReadS String")
598 '("lines" . "String -> [String]")
599 '("log" . "Floating a => a -> a")
600 '("logBase" . "Floating a => a -> a -> a")
601 '("lookup" . "Eq a => a -> [(a, b)] -> Maybe b")
602 '("map" . "Functor f => (a -> b) -> f a -> f b")
603 '("mapM" . "Monad m => (a -> m b) -> [a] -> m [b]")
604 '("mapM_" . "Monad m => (a -> m b) -> [a] -> m ()")
605 '("max" . "Ord a => a -> a -> a")
606 '("maxBound" . "Bounded a => a")
607 '("maximum" . "Ord a => [a] -> a")
608 '("maybe" . "b -> (a -> b) -> Maybe a -> b")
609 '("min" . "Ord a => a -> a -> a")
610 '("minBound" . "Bounded a => a")
611 '("minimum" . "Ord a => [a] -> a")
612 '("mod" . "Integral a => a -> a -> a")
613 '("negate" . "Num a => a -> a")
614 '("not" . "Bool -> Bool")
615 '("notElem" . "Eq a => a -> [a] -> Bool")
616 '("null" . "[a] -> Bool")
617 '("odd" . "Integral a => a -> Bool")
618 '("or" . "[Bool] -> Bool")
619 '("otherwise" . "Bool")
620 '("pi" . "Floating a => a")
621 '("pred" . "Enum a => a -> a")
622 '("print" . "Show a => IO ()")
623 '("product" . "Num a => [a] -> a")
624 '("properFraction" . "(RealFrac a, Integral b) => a -> (b, a)")
625 '("putChar" . "Char -> IO ()")
626 '("putStr" . "String -> IO ()")
627 '("putStrLn" . "String -> IO ()")
628 '("quot" . "Integral a => a -> a -> a")
629 '("quotRem" . "Integral a => a -> a -> (a, a)")
630 '("read" . "Read a => String -> a")
631 '("readFile" . "FilePath -> IO String")
632 '("readIO" . "Read a => String -> IO a")
633 '("readList" . "Read a => ReadS [a]")
634 '("readLn" . "Read a => IO a")
635 '("readParen" . "Bool -> ReadS a -> ReadS a")
636 '("reads" . "Read a => ReadS a")
637 '("readsPrec" . "Read a => Int -> ReadS a")
638 '("realToFrac" . "(Real a, Fractional b) => a -> b")
639 '("recip" . "Fractional a => a -> a")
640 '("rem" . "Integral a => a -> a -> a")
641 '("repeat" . "a -> [a]")
642 '("replicate" . "Int -> a -> [a]")
643 '("return" . "Monad m => a -> m a")
644 '("reverse" . "[a] -> [a]")
645 '("round" . "(RealFrac a, Integral b) => a -> b")
646 '("scaleFloat" . "RealFloat a => Int -> a -> a")
647 '("scanl" . "(a -> b -> a) -> a -> [b] -> [a]")
648 '("scanl1" . "(a -> a -> a) -> [a] -> [a]")
649 '("scanr" . "(a -> b -> b) -> b -> [a] -> [b]")
650 '("scanr1" . "(a -> a -> a) -> [a] -> [a]")
651 '("seq" . "Eval a => a -> a -> b")
652 '("sequence_" . "Monad m => [m a] -> m ()")
653 '("show" . "Show a => a -> String")
654 '("showChar" . "Char -> ShowS")
655 '("showList" . "Show a => [a] -> ShowS")
656 '("showParen" . "Bool -> ShowS -> ShowS")
657 '("showString" . "String -> ShowS")
658 '("shows" . "Show a => a -> ShowS")
659 '("showsPrec" . "Show a => Int -> a -> ShowS")
660 '("significand" . "RealFloat a => a -> a")
661 '("signum" . "Num a => a -> a")
662 '("sin" . "Floating a => a -> a")
663 '("sinh" . "Floating a => a -> a")
664 '("snd" . "(a, b) -> b")
665 '("span" . "(a -> Bool) -> [a] -> ([a], [a])")
666 '("splitAt" . "Int -> [a] -> ([a], [a])")
667 '("sqrt" . "Floating a => a -> a")
668 '("subtract" . "Num a => a -> a -> a")
669 '("succ" . "Enum a => a -> a")
670 '("sum" . "Num a => [a] -> a")
671 '("tail" . "[a] -> [a]")
672 '("take" . "Int -> [a] -> [a]")
673 '("takeWhile" . "(a -> Bool) -> [a] -> [a]")
674 '("tan" . "Floating a => a -> a")
675 '("tanh" . "Floating a => a -> a")
676 '("toEnum" . "Enum a => Int -> a")
677 '("toInteger" . "Integral a => a -> Integer")
678 '("toRational" . "Real a => a -> Rational")
679 '("truncate" . "(RealFrac a, Integral b) => a -> b")
680 '("uncurry" . "(a -> b -> c) -> ((a, b) -> c)")
682 '("unlines" . "[String] -> String")
683 '("until" . "(a -> Bool) -> (a -> a) -> a -> a")
684 '("unwords" . "[String] -> String")
685 '("unzip" . "[(a, b)] -> ([a], [b])")
686 '("unzip3" . "[(a, b, c)] -> ([a], [b], [c])")
687 '("userError" . "String -> IOError")
688 '("words" . "String -> [String]")
689 '("writeFile" . "FilePath -> String -> IO ()")
690 '("zip" . "[a] -> [b] -> [(a, b)]")
691 '("zip3" . "[a] -> [b] -> [c] -> [(a, b, c)]")
692 '("zipWith" . "(a -> b -> c) -> [a] -> [b] -> [c]")
693 '("zipWith3" . "(a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]")
695 '("%" . "(Integral a) => a -> a -> Ratio a")
696 '("numerator" . "(Integral a) => Ratio a -> a")
697 '("denominator" . "(Integral a) => Ratio a -> a")
698 '("approxRational" . "(RealFrac a) => a -> a -> Rational")
700 '("realPart" . "(RealFloat a) => Complex a -> a")
701 '("imagPart" . "(RealFloat a) => Complex a -> a")
702 '("conjugate" . "(RealFloat a) => Complex a -> Complex a")
703 '("mkPolar" . "(RealFloat a) => a -> a -> Complex a")
704 '("cis" . "(RealFloat a) => a -> Complex a")
705 '("polar" . "(RealFloat a) => Complex a -> (a,a)")
706 '("magnitude" . "(RealFloat a) => Complex a -> a")
707 '("phase" . "(RealFloat a) => Complex a -> a")
709 '("fromRat" . "(RealFloat a) => Rational -> a")
710 '("showSigned" . "(Real a) => (a -> ShowS) -> Int -> a -> ShowS")
711 '("showInt" . "Integral a => a -> ShowS")
712 '("readSigned" . "(Real a) => ReadS a -> ReadS a")
713 '("readInt" . "(Integral a) => a -> (Char -> Bool) -> (Char -> Int) -> ReadS a")
714 '("readDec" . "(Integral a) => ReadS a")
715 '("readOct" . "(Integral a) => ReadS a")
716 '("readHex" . "(Integral a) => ReadS a")
717 '("showEFloat" . "(RealFloat a) => Maybe Int -> a -> ShowS")
718 '("showFFloat" . "(RealFloat a) => Maybe Int -> a -> ShowS")
719 '("showGFloat" . "(RealFloat a) => Maybe Int -> a -> ShowS")
720 '("showFloat" . "(RealFloat a) => a -> ShowS")
721 '("floatToDigits" . "(RealFloat a) => Integer -> a -> ([Int], Int)")
722 '("readFloat" . "(RealFloat a) => ReadS a")
723 '("lexDigits" . "ReadS String")
725 '("range" . "(Ix a) => (a,a) -> [a]")
726 '("index" . "(Ix a) => (a,a) -> a -> Int")
727 '("inRange" . "(Ix a) => (a,a) -> a -> Bool")
728 '("rangeSize" . "(Ix a) => (a,a) -> Int")
730 '("array" . "(Ix a) => (a,a) -> [(a,b)] -> Array a b")
731 '("listArray" . "(Ix a) => (a,a) -> [b] -> Array a b")
732 '("!" . "(Ix a) => Array a b -> a -> b")
733 '("bounds" . "(Ix a) => Array a b -> (a,a)")
734 '("indices" . "(Ix a) => Array a b -> [a]")
735 '("elems" . "(Ix a) => Array a b -> [b]")
736 '("assocs" . "(Ix a) => Array a b -> [(a,b)]")
737 '("accumArray" . "(Ix a) => (b -> c -> b) -> b -> (a,a) -> [(a,c)] -> Array a b")
738 '("//" . "(Ix a) => Array a b -> [(a,b)] -> Array a b")
739 '("accum" . "(Ix a) => (b -> c -> b) -> Array a b -> [(a,c)] -> Array a b")
740 '("ixmap" . "(Ix a, Ix b) => (a,a) -> (a -> b) -> Array b c -> Array a c")
742 '("elemIndex" . "Eq a => a -> [a] -> Maybe Int")
743 '("elemIndices" . "Eq a => a -> [a] -> [Int]")
744 '("find" . "(a -> Bool) -> [a] -> Maybe a")
745 '("findIndex" . "(a -> Bool) -> [a] -> Maybe Int")
746 '("findIndices" . "(a -> Bool) -> [a] -> [Int]")
747 '("nub" . "Eq a => [a] -> [a]")
748 '("nubBy" . "(a -> a -> Bool) -> [a] -> [a]")
749 '("delete" . "Eq a => a -> [a] -> [a]")
750 '("deleteBy" . "(a -> a -> Bool) -> a -> [a] -> [a]")
751 '("\\\\" . "Eq a => [a] -> [a] -> [a]")
752 '("deleteFirstsBy" . "(a -> a -> Bool) -> [a] -> [a] -> [a]")
753 '("union" . "Eq a => [a] -> [a] -> [a]")
754 '("unionBy" . "(a -> a -> Bool) -> [a] -> [a] -> [a]")
755 '("intersect" . "Eq a => [a] -> [a] -> [a]")
756 '("intersectBy" . "(a -> a -> Bool) -> [a] -> [a] -> [a]")
757 '("intersperse" . "a -> [a] -> [a]")
758 '("transpose" . "[[a]] -> [[a]]")
759 '("partition" . "(a -> Bool) -> [a] -> ([a],[a])")
760 '("group" . "Eq a => [a] -> [[a]]")
761 '("groupBy" . "(a -> a -> Bool) -> [a] -> [[a]]")
762 '("inits" . "[a] -> [[a]]")
763 '("tails" . "[a] -> [[a]]")
764 '("isPrefixOf" . "Eq a => [a] -> [a] -> Bool")
765 '("isSuffixOf" . "Eq a => [a] -> [a] -> Bool")
766 '("mapAccumL" . "(a -> b -> (a, c)) -> a -> [b] -> (a, [c])")
767 '("mapAccumR" . "(a -> b -> (a, c)) -> a -> [b] -> (a, [c])")
768 '("unfoldr" . "(b -> Maybe (a,b)) -> b -> [a]")
769 '("sort" . "Ord a => [a] -> [a]")
770 '("sortBy" . "(a -> a -> Ordering) -> [a] -> [a]")
771 '("insert" . "Ord a => a -> [a] -> [a]")
772 '("insertBy" . "(a -> a -> Ordering) -> a -> [a] -> [a]")
773 '("maximumBy" . "(a -> a -> Ordering) -> [a] -> a")
774 '("minimumBy" . "(a -> a -> Ordering) -> [a] -> a")
775 '("genericLength" . "Integral a => [b] -> a")
776 '("genericTake" . "Integral a => a -> [b] -> [b]")
777 '("genericDrop" . "Integral a => a -> [b] -> [b]")
778 '("genericSplitAt" . "Integral a => a -> [b] -> ([b],[b])")
779 '("genericIndex" . "Integral a => [b] -> a -> b")
780 '("genericReplicate" . "Integral a => a -> b -> [b]")
781 '("zip4" . "[a] -> [b] -> [c] -> [d] -> [(a,b,c,d)]")
782 '("zip5" . "[a] -> [b] -> [c] -> [d] -> [e] -> [(a,b,c,d,e)]")
783 '("zip6" . "[a] -> [b] -> [c] -> [d] -> [e] -> [f] -> [(a,b,c,d,e,f)]")
784 '("zip7" . "[a] -> [b] -> [c] -> [d] -> [e] -> [f] -> [g] -> [(a,b,c,d,e,f,g)]")
785 '("zipWith4" . "(a->b->c->d->e) -> [a]->[b]->[c]->[d]->[e]")
786 '("zipWith5" . "(a->b->c->d->e->f) -> [a]->[b]->[c]->[d]->[e]->[f]")
787 '("zipWith6" . "(a->b->c->d->e->f->g) -> [a]->[b]->[c]->[d]->[e]->[f]->[g]")
788 '("zipWith7" . "(a->b->c->d->e->f->g->h) -> [a]->[b]->[c]->[d]->[e]->[f]->[g]->[h]")
789 '("unzip4" . "[(a,b,c,d)] -> ([a],[b],[c],[d])")
790 '("unzip5" . "[(a,b,c,d,e)] -> ([a],[b],[c],[d],[e])")
791 '("unzip6" . "[(a,b,c,d,e,f)] -> ([a],[b],[c],[d],[e],[f])")
792 '("unzip7" . "[(a,b,c,d,e,f,g)] -> ([a],[b],[c],[d],[e],[f],[g])")
794 '("isJust" . "Maybe a -> Bool")
795 '("isNothing" . "Maybe a -> Bool")
796 '("fromJust" . "Maybe a -> a")
797 '("fromMaybe" . "a -> Maybe a -> a")
798 '("listToMaybe" . "[a] -> Maybe a")
799 '("maybeToList" . "Maybe a -> [a]")
800 '("catMaybes" . "[Maybe a] -> [a]")
801 '("mapMaybe" . "(a -> Maybe b) -> [a] -> [b]")
803 '("isAscii" . "Char -> Bool")
804 '("isLatin1" . "Char -> Bool")
805 '("isControl" . "Char -> Bool")
806 '("isPrint" . "Char -> Bool")
807 '("isSpace" . "Char -> Bool")
808 '("isUpper" . "Char -> Bool")
809 '("isLower" . "Char -> Bool")
810 '("isAlpha" . "Char -> Bool")
811 '("isDigit" . "Char -> Bool")
812 '("isOctDigit" . "Char -> Bool")
813 '("isHexDigit" . "Char -> Bool")
814 '("isAlphaNum" . "Char -> Bool")
815 '("toUpper" . "Char -> Char")
816 '("toLower" . "Char -> Char")
817 '("digitToInt" . "Char -> Int")
818 '("intToDigit" . "Int -> Char")
819 '("ord" . "Char -> Int")
820 '("chr" . "Int -> Char")
821 '("lexLitChar" . "ReadS String")
822 '("readLitChar" . "ReadS Char")
823 '("showLitChar" . "Char -> ShowS")
825 '("mzero" . "(MonadPlus m) => m a")
826 '("mplus" . "(MonadPlus m) => m a -> m a -> m a")
827 '("join" . "Monad m => m (m a) -> m a")
828 '("guard" . "MonadPlus m => Bool -> m ()")
829 '("when" . "Monad m => Bool -> m () -> m ()")
830 '("unless" . "Monad m => Bool -> m () -> m ()")
831 '("ap" . "Monad m => m (a -> b) -> m a -> m b")
832 '("mapAndUnzipM" . "Monad m => (a -> m (b,c)) -> [a] -> m ([b], [c])")
833 '("zipWithM" . "Monad m => (a -> b -> m c) -> [a] -> [b] -> m [c]")
834 '("zipWithM_" . "Monad m => (a -> b -> m c) -> [a] -> [b] -> m ()")
835 '("foldM" . "Monad m => (a -> b -> m a) -> a -> [b] -> m a")
836 '("filterM" . "Monad m => (a -> m Bool) -> [a] -> m [a]")
837 '("msum" . "MonadPlus m => [m a] -> m a")
838 '("liftM" . "Monad m => (a -> b) -> (m a -> m b)")
839 '("liftM2" . "Monad m => (a -> b -> c) -> (m a -> m b -> m c)")
840 '("liftM3" . "Monad m => (a -> b -> c -> d) -> (m a -> m b -> m c -> m d)")
841 '("liftM4" . "Monad m => (a -> b -> c -> d -> e) -> (m a -> m b -> m c -> m d -> m e)")
842 '("liftM5" . "Monad m => (a -> b -> c -> d -> e -> f) -> (m a -> m b -> m c -> m d -> m e -> m f)")
844 '("stdin" . "Handle")
845 '("stdout" . "Handle")
846 '("stderr" . "Handle")
847 '("openFile" . "FilePath -> IOMode -> IO Handle")
848 '("hClose" . "Handle -> IO ()")
849 '("hFileSize" . "Handle -> IO Integer")
850 '("hIsEOF" . "Handle -> IO Bool")
851 '("isEOF" . "IO Bool")
852 '("hSetBuffering" . "Handle -> BufferMode -> IO ()")
853 '("hGetBuffering" . "Handle -> IO BufferMode")
854 '("hFlush" . "Handle -> IO ()")
855 '("hGetPosn" . "Handle -> IO HandlePosn")
856 '("hSetPosn" . "HandlePosn -> IO ()")
857 '("hSeek" . "Handle -> SeekMode -> Integer -> IO ()")
858 '("hWaitForInput" . "Handle -> Int -> IO Bool")
859 '("hReady" . "Handle -> IO Bool")
860 '("hGetChar" . "Handle -> IO Char")
861 '("hGetLine" . "Handle -> IO String")
862 '("hLookAhead" . "Handle -> IO Char")
863 '("hGetContents" . "Handle -> IO String")
864 '("hPutChar" . "Handle -> Char -> IO ()")
865 '("hPutStr" . "Handle -> String -> IO ()")
866 '("hPutStrLn" . "Handle -> String -> IO ()")
867 '("hPrint" . "Show a => Handle -> a -> IO ()")
868 '("hIsOpen" . "Handle -> IO Bool")
869 '("hIsClosed" . "Handle -> IO Bool")
870 '("hIsReadable" . "Handle -> IO Bool")
871 '("hIsWritable" . "Handle -> IO Bool")
872 '("hIsSeekable" . "Handle -> IO Bool")
873 '("isAlreadyExistsError" . "IOError -> Bool")
874 '("isDoesNotExistError" . "IOError -> Bool")
875 '("isAlreadyInUseError" . "IOError -> Bool")
876 '("isFullError" . "IOError -> Bool")
877 '("isEOFError" . "IOError -> Bool")
878 '("isIllegalOperation" . "IOError -> Bool")
879 '("isPermissionError" . "IOError -> Bool")
880 '("isUserError" . "IOError -> Bool")
881 '("ioeGetErrorString" . "IOError -> String")
882 '("ioeGetHandle" . "IOError -> Maybe Handle")
883 '("ioeGetFileName" . "IOError -> Maybe FilePath")
884 '("try" . "IO a -> Either IOError a")
885 '("bracket" . "IO a -> (a -> IO b) -> (a -> IO c) -> IO c")
886 '("bracket_" . "IO a -> (a -> IO b) -> IO c -> IO c")
888 '("readable" . "Permissions -> Bool")
889 '("writable" . "Permissions -> Bool")
890 '("executable" . "Permissions -> Bool")
891 '("searchable" . "Permissions -> Bool")
892 '("createDirectory" . "FilePath -> IO ()")
893 '("removeDirectory" . "FilePath -> IO ()")
894 '("removeFile" . "FilePath -> IO ()")
895 '("renameDirectory" . "FilePath -> FilePath -> IO ()")
896 '("renameFile" . "FilePath -> FilePath -> IO ()")
897 '("getDirectoryContents" . "FilePath -> IO [FilePath]")
898 '("getCurrentDirectory" . "IO FilePath")
899 '("setCurrentDirectory" . "FilePath -> IO ()")
900 '("doesFileExist" . "FilePath -> IO Bool")
901 '("doesDirectoryExist" . "FilePath -> IO Bool")
902 '("getPermissions" . "FilePath -> IO Permissions")
903 '("setPermissions" . "FilePath -> Permissions -> IO ()")
904 '("getModificationTime" . "FilePath -> IO ClockTime")
906 '("getArgs" . "IO [String]")
907 '("getProgName" . "IO String")
908 '("getEnv" . "String -> IO String")
909 '("system" . "String -> IO ExitCode")
910 '("exitWith" . "ExitCode -> IO a")
911 '("exitFailure" . "IO a")
913 '("ctYear" . "CalendarTime -> Int")
914 '("ctMonth" . "CalendarTime -> Month")
915 '("ctDay" . "CalendarTime -> Int")
916 '("ctHour" . "CalendarTime -> Int")
917 '("ctMin" . "CalendarTime -> Int")
918 '("ctSec" . "CalendarTime -> Int")
919 '("ctPicosec" . "CalendarTime -> Integer")
920 '("ctWDay" . "CalendarTime -> Day")
921 '("ctYDay" . "CalendarTime -> Int")
922 '("ctTZName" . "CalendarTime -> String")
923 '("ctTZ" . "CalendarTime -> Int")
924 '("ctIsDST" . "CalendarTime -> Bool")
925 '("tdYear" . "TimeDiff -> Int")
926 '("tdMonth" . "TimeDiff -> Int")
927 '("tdDay" . "TimeDiff -> Int")
928 '("tdHour" . "TimeDiff -> Int")
929 '("tdMin" . "TimeDiff -> Int")
930 '("tdSec" . "TimeDiff -> Int")
931 '("tdPicosec" . "TimeDiff -> Integer")
932 '("getClockTime" . "IO ClockTime")
933 '("addToClockTime" . "TimeDiff -> ClockTime -> ClockTime")
934 '("diffClockTimes" . "ClockTime -> ClockTime -> TimeDiff")
935 '("toCalendarTime" . "ClockTime -> IO CalendarTime")
936 '("toUTCTime" . "ClockTime -> CalendarTime")
937 '("toClockTime" . "CalendarTime -> ClockTime")
938 '("calendarTimeToString" . "CalendarTime -> String")
939 '("formatCalendarTime" . "TimeLocale -> String -> CalendarTime -> String")
941 '("wDays" . "TimeLocale -> [(String, String)]")
942 '("months" . "TimeLocale -> [(String, String)]")
943 '("amPm" . "TimeLocale -> (String, String)")
944 '("dateTimeFmt" . "TimeLocale -> String")
945 '("dateFmt" . "TimeLocale -> String")
946 '("timeFmt" . "TimeLocale -> String")
947 '("time12Fmt" . "TimeLocale -> String")
948 '("defaultTimeLocale" . "TimeLocale")
950 '("getCPUTime" . "IO Integer")
951 '("cpuTimePrecision" . "Integer")
953 '("next" . "(RandomGen g) => g -> (Int, g)")
954 '("split" . "(RandomGen g) => g -> (g, g)")
955 '("mkStdGen" . "Int -> StdGen")
956 '("randomR" . "(Random a, RandomGen g) => (a, a) -> g -> (a, g)")
957 '("random" . "(Random a, RandomGen g) => g -> (a, g)")
958 '("randomRs" . "(Random a, RandomGen g) => (a, a) -> g -> [a]")
959 '("randoms" . "(Random a, RandomGen g) => g -> [a]")
960 '("randomRIO" . "(Random a) => (a,a) -> IO a")
961 '("randomIO" . "(Random a) => IO a")
962 '("newStdGen" . "IO StdGen")
963 '("setStdGen" . "StdGen -> IO ()")
964 '("getStdGen" . "IO StdGen")
965 '("getStdRandom" . "(StdGen -> (a, StdGen)) -> IO a"))
966 "alist of prelude functions and their types.")
968 ;;@cindex haskell-doc-strategy-ids
970 (defvar haskell-doc-strategy-ids
972 '("par" . "Done -> Done -> Done ; [infixr 0]")
973 '("seq" . "Done -> Done -> Done ; [infixr 1]")
975 '("using" . "a -> Strategy a -> a ; [infixl 0]")
976 '("demanding" . "a -> Done -> a ; [infixl 0]")
977 '("sparking" . "a -> Done -> a ; [infixl 0]")
979 '(">||" . "Done -> Done -> Done ; [infixr 2]")
980 '(">|" . "Done -> Done -> Done ; [infixr 3]")
981 '("$||" . "(a -> b) -> Strategy a -> a -> b ; [infixl 6]")
982 '("$|" . "(a -> b) -> Strategy a -> a -> b ; [infixl 6]")
983 '(".|" . "(b -> c) -> Strategy b -> (a -> b) -> (a -> c) ; [infixl 9]")
984 '(".||" . "(b -> c) -> Strategy b -> (a -> b) -> (a -> c) ; [infixl 9]")
985 '("-|" . "(a -> b) -> Strategy b -> (b -> c) -> (a -> c) ; [infixl 9]")
986 '("-||" . "(a -> b) -> Strategy b -> (b -> c) -> (a -> c) ; [infixl 9]")
988 '("Done" . "type Done = ()")
989 '("Strategy" . "type Strategy a = a -> Done")
991 '("r0" . "Strategy a")
992 '("rwhnf" . "Eval a => Strategy a")
993 '("rnf" . "Strategy a")
994 '("NFData" . "class Eval a => NFData a where rnf :: Strategy a")
995 '("NFDataIntegral" ."class (NFData a, Integral a) => NFDataIntegral a")
996 '("NFDataOrd" . "class (NFData a, Ord a) => NFDataOrd a")
998 '("markStrat" . "Int -> Strategy a -> Strategy a")
1000 '("seqPair" . "Strategy a -> Strategy b -> Strategy (a,b)")
1001 '("parPair" . "Strategy a -> Strategy b -> Strategy (a,b)")
1002 '("seqTriple" . "Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)")
1003 '("parTriple" . "Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)")
1005 '("parList" . "Strategy a -> Strategy [a]")
1006 '("parListN" . "(Integral b) => b -> Strategy a -> Strategy [a]")
1007 '("parListNth" . "Int -> Strategy a -> Strategy [a]")
1008 '("parListChunk" . "Int -> Strategy a -> Strategy [a]")
1009 '("parMap" . "Strategy b -> (a -> b) -> [a] -> [b]")
1010 '("parFlatMap" . "Strategy [b] -> (a -> [b]) -> [a] -> [b]")
1011 '("parZipWith" . "Strategy c -> (a -> b -> c) -> [a] -> [b] -> [c]")
1012 '("seqList" . "Strategy a -> Strategy [a]")
1013 '("seqListN" . "(Integral a) => a -> Strategy b -> Strategy [b]")
1014 '("seqListNth" . "Int -> Strategy b -> Strategy [b]")
1016 '("parBuffer" . "Int -> Strategy a -> [a] -> [a]")
1018 '("seqArr" . "(Ix b) => Strategy a -> Strategy (Array b a)")
1019 '("parArr" . "(Ix b) => Strategy a -> Strategy (Array b a)")
1021 '("fstPairFstList" . "(NFData a) => Strategy [(a,b)]")
1022 '("force" . "(NFData a) => a -> a ")
1023 '("sforce" . "(NFData a) => a -> b -> b")
1025 "alist of strategy functions and their types as defined in Strategies.lhs.")
1027 (defvar haskell-doc-user-defined-ids nil
1028 "alist of functions and strings defined by the user.")
1030 ;;@node Test membership, , Prelude types, Constants and Variables
1031 ;;@subsection Test membership
1033 ;;@cindex haskell-doc-is-of
1034 (defsubst haskell-doc-is-of (fn types)
1035 "Check whether FN is one of the functions in the alist TYPES and return the type."
1038 ;;@node Install as minor mode, Menubar Support, Constants and Variables, top
1039 ;;@section Install as minor mode
1041 ;; Put this minor mode on the global minor-mode-alist.
1042 (or (assq 'haskell-doc-mode (default-value 'minor-mode-alist))
1043 (setq-default minor-mode-alist
1044 (append (default-value 'minor-mode-alist)
1045 '((haskell-doc-mode haskell-doc-minor-mode-string)))))
1048 ;;@node Menubar Support, Haskell Doc Mode, Install as minor mode, top
1049 ;;@section Menubar Support
1054 ;; a dummy definition needed for xemacs (I know, it's horrible :-(
1056 ;;@cindex haskell-doc-install-keymap
1058 (defvar haskell-doc-keymap
1059 (let ((map (make-sparse-keymap)))
1060 (define-key map [visit]
1061 '("Visit FTP home site" . haskell-doc-visit-home))
1062 (define-key map [submit]
1063 '("Submit bug report" . haskell-doc-submit-bug-report))
1064 (define-key map [dummy] '("---" . nil))
1065 (define-key map [make-index]
1066 '("Make global fct index" . haskell-doc-make-global-fct-index))
1067 (define-key map [global-types-on]
1068 '("Toggle display of global types" . haskell-doc-show-global-types))
1069 (define-key map [strategy-on]
1070 '("Toggle display of strategy ids" . haskell-doc-show-strategy))
1071 (define-key map [user-defined-on]
1072 '("Toggle display of user defined ids" . haskell-doc-show-user-defined))
1073 (define-key map [prelude-on]
1074 '("Toggle display of prelude functions" . haskell-doc-show-prelude))
1075 (define-key map [reserved-ids-on]
1076 '("Toggle display of reserved ids" . haskell-doc-show-reserved))
1077 (define-key map [haskell-doc-on]
1078 '("Toggle haskell-doc mode" . haskell-doc-mode))
1081 (defun haskell-doc-install-keymap ()
1082 "Install a menu for `haskell-doc-mode' as a submenu of \"Hugs\"."
1084 ;; Add the menu to the hugs menu as last entry.
1085 (let ((hugsmap (lookup-key (current-local-map) [menu-bar Hugs])))
1086 (if (not (or (featurep 'xemacs) ; XEmacs has problems here
1087 (not (keymapp hugsmap))
1088 (lookup-key hugsmap [haskell-doc])))
1089 (if (functionp 'define-key-after)
1090 (define-key-after hugsmap [haskell-doc]
1091 (cons "Haskell-doc" haskell-doc-keymap)
1092 [Haskell-doc mode]))))
1093 ;; Add shortcuts for these commands.
1094 (local-set-key "\C-c\e/" 'haskell-doc-check-active)
1095 ;; Conflicts with the binding of haskell-insert-otherwise.
1096 ;; (local-set-key "\C-c\C-o" 'haskell-doc-mode)
1097 (local-set-key [(control shift meta mouse-3)]
1098 'haskell-doc-ask-mouse-for-type))
1101 ;;@node Haskell Doc Mode, Switch it on or off, Menubar Support, top
1102 ;;@section Haskell Doc Mode
1104 ;;@cindex haskell-doc-mode
1107 (defun haskell-doc-mode (&optional arg)
1108 "Enter `haskell-doc-mode' for showing fct types in the echo area.
1109 See variable docstring."
1110 (interactive (list (or current-prefix-arg 'toggle)))
1112 ;; Make sure it's on the post-command-idle-hook if defined, otherwise put
1113 ;; it on post-command-hook. The former first appeared in Emacs 19.30.
1114 (setq haskell-doc-mode
1116 ((eq arg 'toggle) (not haskell-doc-mode))
1117 (arg (> (prefix-numeric-value arg) 0))
1122 ;; Turning the mode ON.
1124 ;; ToDo: replace binding of `post-command-idle-hook' by
1125 ;; `run-with-idle-timer'
1126 (add-hook (if (boundp 'post-command-idle-hook)
1127 'post-command-idle-hook
1129 'haskell-doc-mode-print-current-symbol-info nil 'local)
1130 (and haskell-doc-show-global-types
1131 (haskell-doc-make-global-fct-index)) ; build type index for global fcts
1133 (haskell-doc-install-keymap)
1135 (run-hooks 'haskell-doc-mode-hook))
1137 ((not haskell-doc-mode)
1139 (remove-hook (if (boundp 'post-command-idle-hook)
1140 'post-command-idle-hook
1142 'haskell-doc-mode-print-current-symbol-info 'local)))
1144 (and (interactive-p)
1145 (message "haskell-doc-mode is %s"
1146 (if haskell-doc-mode "enabled" "disabled")))
1149 (defmacro haskell-doc-toggle-var (id prefix)
1150 ;; toggle variable or set it based on prefix value
1153 (>= (prefix-numeric-value ,prefix) 0)
1156 ;;@cindex haskell-doc-show-global-types
1157 (defun haskell-doc-show-global-types (&optional prefix)
1158 "Turn on global types information in `haskell-doc-mode'."
1160 (haskell-doc-toggle-var haskell-doc-show-global-types prefix)
1161 (if haskell-doc-show-global-types
1162 (haskell-doc-make-global-fct-index)))
1164 ;;@cindex haskell-doc-show-reserved
1165 (defun haskell-doc-show-reserved (&optional prefix)
1166 "Toggle the automatic display of a doc string for reserved ids."
1168 (haskell-doc-toggle-var haskell-doc-show-reserved prefix))
1170 ;;@cindex haskell-doc-show-prelude
1171 (defun haskell-doc-show-prelude (&optional prefix)
1172 "Toggle the automatic display of a doc string for reserved ids."
1174 (haskell-doc-toggle-var haskell-doc-show-prelude prefix))
1176 ;;@cindex haskell-doc-show-strategy
1177 (defun haskell-doc-show-strategy (&optional prefix)
1178 "Toggle the automatic display of a doc string for strategy ids."
1180 (haskell-doc-toggle-var haskell-doc-show-strategy prefix))
1182 ;;@cindex haskell-doc-show-user-defined
1183 (defun haskell-doc-show-user-defined (&optional prefix)
1184 "Toggle the automatic display of a doc string for user defined ids."
1186 (haskell-doc-toggle-var haskell-doc-show-user-defined prefix))
1188 ;;@node Switch it on or off, Check, Haskell Doc Mode, top
1189 ;;@section Switch it on or off
1191 ;;@cindex turn-on-haskell-doc-mode
1194 (defalias 'turn-on-haskell-doc-mode 'haskell-doc-mode)
1196 ;;@cindex turn-off-haskell-doc-mode
1198 (defun turn-off-haskell-doc-mode ()
1199 "Unequivocally turn off `haskell-doc-mode' (see variable documentation)."
1201 (haskell-doc-mode 0))
1203 ;;@node Check, Top level function, Switch it on or off, top
1206 ;;@cindex haskell-doc-check-active
1208 (defun haskell-doc-check-active ()
1209 "Check whether the print function is hooked in.
1210 Should be the same as the value of `haskell-doc-mode' but alas currently it
1214 (if (memq 'haskell-doc-mode-print-current-symbol-info
1215 (if (boundp 'post-command-idle-hook)
1216 post-command-idle-hook
1218 "haskell-doc is ACTIVE"
1219 (substitute-command-keys
1220 "haskell-doc is not ACTIVE \(Use C-u \\[haskell-doc-mode] to turn it on\)"))))
1222 ;;@node Top level function, Mouse interface, Check, top
1223 ;;@section Top level function
1225 ;;@cindex haskell-doc-mode-print-current-symbol-info
1226 ;; This is the function hooked into the elisp command engine
1227 (defun haskell-doc-mode-print-current-symbol-info ()
1228 "Print the type of the symbol under the cursor.
1230 This function is hooked into the `post-command-idle-hook' to print the type
1231 automatically if `haskell-doc-mode' is turned on. It can also be called
1232 directly to ask for the type of a function."
1234 (and haskell-doc-mode
1235 (not executing-kbd-macro)
1236 ;; Having this mode operate in the minibuffer makes it impossible to
1237 ;; see what you're doing.
1238 (not (eq (selected-window) (minibuffer-window)))
1240 (sit-for haskell-doc-idle-delay)
1241 ;; good morning! read the word under the cursor for breakfast
1242 (haskell-doc-show-type)))
1243 ;; ;; ToDo: find surrounding fct
1244 ;; (cond ((eq current-symbol current-fnsym)
1245 ;; (haskell-doc-show-type current-fnsym))
1247 ;; (or nil ; (haskell-doc-print-var-docstring current-symbol)
1248 ;; (haskell-doc-show-type current-fnsym)))))))
1250 (defun haskell-doc-current-info ()
1251 "Return the info about symbol at point.
1252 Meant for `eldoc-print-current-symbol-info-function'."
1253 (haskell-doc-sym-doc (haskell-doc-get-current-word)))
1256 ;;@node Mouse interface, Print fctsym, Top level function, top
1257 ;;@section Mouse interface for interactive query
1259 ;;@cindex haskell-doc-ask-mouse-for-type
1260 (defun haskell-doc-ask-mouse-for-type (event)
1261 "Read the identifier under the mouse and echo its type.
1262 This uses the same underlying function `haskell-doc-show-type' as the hooked
1263 function. Only the user interface is different."
1266 (select-window (posn-window (event-end event)))
1267 (goto-char (posn-point (event-end event)))
1268 (haskell-doc-show-type)))
1271 ;;@node Print fctsym, Movement, Mouse interface, top
1272 ;;@section Print fctsym
1277 ;;* Global fct type::
1278 ;;* Local fct type::
1281 ;;@node Show type, Aux, Print fctsym, Print fctsym
1282 ;;@subsection Show type
1284 ;;@cindex haskell-doc-show-type
1287 (defun haskell-doc-show-type (&optional sym)
1288 "Show the type of the function near point.
1289 For the function under point, show the type in the echo area.
1290 This information is extracted from the `haskell-doc-prelude-types' alist
1291 of prelude functions and their types, or from the local functions in the
1294 (unless sym (setq sym (haskell-doc-get-current-word)))
1295 ;; if printed before do not print it again
1296 (unless (string= sym (car haskell-doc-last-data))
1297 (let ((doc (haskell-doc-sym-doc sym)))
1299 ;; In emacs 19.29 and later, and XEmacs 19.13 and later, all
1300 ;; messages are recorded in a log. Do not put haskell-doc messages
1301 ;; in that log since they are legion.
1302 (if (eval-when-compile (fboundp 'display-message))
1303 ;; XEmacs 19.13 way of preventing log messages.
1304 ;;(display-message 'no-log (format <args>))
1305 ;; XEmacs 19.15 seems to be a bit different.
1306 (display-message 'message (format "%s" doc))
1307 (let ((message-log-max nil))
1308 (message "%s" doc)))))))
1311 (defun haskell-doc-sym-doc (sym)
1312 "Show the type of the function near point.
1313 For the function under point, show the type in the echo area.
1314 This information is extracted from the `haskell-doc-prelude-types' alist
1315 of prelude functions and their types, or from the local functions in the
1317 (let ((i-am-prelude nil)
1320 (is-reserved (haskell-doc-is-of sym haskell-doc-reserved-ids))
1321 (is-prelude (haskell-doc-is-of sym haskell-doc-prelude-types))
1322 (is-strategy (haskell-doc-is-of sym haskell-doc-strategy-ids))
1323 (is-user-defined (haskell-doc-is-of sym haskell-doc-user-defined-ids))
1324 (is-prelude (haskell-doc-is-of sym haskell-doc-prelude-types)))
1326 ;; if reserved id (i.e. Haskell keyword
1327 ((and haskell-doc-show-reserved
1329 (setq type (cdr is-reserved))
1330 (setcdr haskell-doc-last-data type))
1331 ;; if built-in function get type from docstring
1332 ((and (not (null haskell-doc-show-prelude))
1334 (setq type (cdr is-prelude)) ; (cdr (assoc sym haskell-doc-prelude-types)))
1335 (if (= 2 (length type)) ; horrible hack to remove bad formatting
1336 (setq type (car (cdr type))))
1337 (setq i-am-prelude t)
1339 (setcdr haskell-doc-last-data type))
1340 ((and haskell-doc-show-strategy
1343 (setq type (cdr is-strategy))
1344 (setcdr haskell-doc-last-data type))
1345 ((and haskell-doc-show-user-defined
1347 ;; (setq i-am-fct t)
1348 (setq type (cdr is-user-defined))
1349 (setcdr haskell-doc-last-data type))
1351 (let ( (x (haskell-doc-get-and-format-fct-type sym)) )
1353 (setcdr haskell-doc-last-data nil) ; if not found reset last data
1355 (setq i-am-fct (string= "Variables" (cdr x)))
1356 (if (and haskell-doc-show-global-types (null type))
1357 (setq type (haskell-doc-get-global-fct-type sym)))
1358 (setcdr haskell-doc-last-data type)))) )
1359 ;; ToDo: encode i-am-fct info into alist of types
1361 ;; drop `::' if it's not a fct
1362 (let ( (str (cond ((and i-am-fct (not haskell-doc-chop-off-fctname))
1363 (format "%s :: %s" sym type))
1365 (format "%s" type)))) )
1367 (add-text-properties 0 (length str) '(face bold) str))
1371 ;; ToDo: define your own notion of `near' to find surrounding fct
1372 ;;(defun haskell-doc-fnsym-in-current-sexp ()
1373 ;; (let* ((p (point))
1375 ;; (forward-word -1)
1376 ;; (while (and (forward-word -1) ; (haskell-doc-forward-sexp-safe -1)
1377 ;; (> (point) (point-min))))
1378 ;; (cond ((or (= (point) (point-min))
1379 ;; (memq (or (char-after (point)) 0)
1381 ;; ;; If we hit a quotation mark before a paren, we
1382 ;; ;; are inside a specific string, not a list of
1384 ;; (eq (or (char-after (1- (point))) 0) ?\"))
1386 ;; (t (condition-case nil
1387 ;; (read (current-buffer))
1388 ;; (error nil)))))))
1391 ;; (format "%s" sym)
1394 ;; (and (symbolp sym)
1397 ;;@node Aux, Global fct type, Show type, Print fctsym
1400 ;; ToDo: handle open brackets to decide if it's a wrapped type
1402 ;;@cindex haskell-doc-grab-line
1403 (defun haskell-doc-grab-line (fct-and-pos)
1404 "Get the type of an \(FCT POSITION\) pair from the current buffer."
1405 ;; (if (null fct-and-pos)
1406 ;; "" ; fn is not a local fct
1408 (goto-char (cdr fct-and-pos))
1410 ;; search for start of type (phsp give better bound?)
1411 (if (null (search-forward "::" (+ (point) haskell-doc-search-distance) t))
1413 (setq str (haskell-doc-grab)) ; leaves point at end of line
1414 (while (haskell-doc-wrapped-type-p) ; while in a multi-line type expr
1417 (skip-chars-forward " \t")
1418 (setq str (concat str (haskell-doc-grab))))
1419 (haskell-doc-string-nub-ws ; squeeze string
1420 (if haskell-doc-chop-off-context ; no context
1421 (haskell-doc-chop-off-context str)
1423 ;; (concat (car fct-and-pos) "::" (haskell-doc-string-nub-ws str))))
1425 ;;@cindex haskell-doc-wrapped-type-p
1426 (defun haskell-doc-wrapped-type-p ()
1427 "Check whether the type under the cursor is wrapped over several lines.
1428 The cursor must be at the end of a line, which contains the type.
1429 Currently, only the following is checked:
1430 If this line ends with a `->' or the next starts with an `->' it is a
1431 multi-line type \(same for `=>'\).
1432 `--' comments are ignored.
1433 ToDo: Check for matching parenthesis!. "
1435 (let ( (here (point))
1436 (lim (progn (beginning-of-line) (point)))
1441 (search-backward "--" lim t) ; skip over `--' comment
1442 (skip-chars-backward " \t")
1443 (if (bolp) ; skip empty lines
1447 (setq res (haskell-doc-wrapped-type-p)))
1449 ;; (setq foo (concat foo (char-to-string (preceding-char)) (char-to-string (following-char))))
1450 (if (or (and (or (char-equal (preceding-char) ?-) (char-equal (preceding-char) ?=))
1451 (char-equal (following-char) ?>)) ; (or -!> =!>
1452 (char-equal (following-char) ?,)) ; !,)
1455 (let ((here (point)))
1457 (skip-chars-forward " \t")
1458 (if (looking-at "--") ; it is a comment line
1462 (setq res (haskell-doc-wrapped-type-p)))
1464 ;; (setq foo (concat foo (char-to-string (preceding-char)) (char-to-string (following-char))))
1465 ;; (message "|%s|" foo)
1466 (if (and (or (char-equal (preceding-char) ?-) (char-equal (preceding-char) ?=))
1467 (char-equal (following-char) ?>)) ; -!> or =!>
1471 ;;@cindex haskell-doc-grab
1472 (defun haskell-doc-grab ()
1473 "Return the text from point to the end of the line, chopping off comments.
1474 Leaves point at end of line."
1475 (let* ( (str (buffer-substring-no-properties (point) (progn (end-of-line) (point))))
1476 (i (string-match "--" str)) )
1479 (substring str 0 i))))
1481 ;;@cindex haskell-doc-string-nub-ws
1482 (defun haskell-doc-string-nub-ws (str)
1483 "Replace all sequences of whitespaces in STR by just one whitespace.
1484 ToDo: Also eliminate leading and trainling whitespace."
1490 (setq i (string-match "\\(\\s-+\\)" res i))
1491 (while (not (null i))
1492 (setq res (replace-match " " t t res))
1493 (setq i (string-match "\\(\\s-+\\)" res (1+ i))) )
1496 ;; ToDo: make this more efficient!!
1497 ;;(defun haskell-doc-string-nub-ws (str)
1498 ;; "Replace all sequences of whitespaces in STR by just one whitespace."
1505 ;; (let* ( (c (string-to-char (substring str i (1+ i))))
1506 ;; (is-ws (eq (char-syntax c) ? )) )
1507 ;; (if (not (and in-ws is-ws))
1508 ;; (setq res (concat res (char-to-string c))))
1509 ;; (setq in-ws is-ws)
1510 ;; (setq i (1+ i))))
1513 ;;@cindex haskell-doc-chop-off-context
1514 (defun haskell-doc-chop-off-context (str)
1515 "Eliminate the contex in a type represented by the string STR."
1516 (let ((i (string-match "=>" str)) )
1519 (substring str (+ i 2)))))
1521 ;;@cindex haskell-doc-get-imenu-info
1522 (defun haskell-doc-get-imenu-info (obj kind)
1523 "Returns a string describing OBJ of KIND \(Variables, Types, Data\)."
1524 (cond ((or (eq major-mode 'haskell-hugs-mode)
1525 ;; GEM: Haskell Mode does not work with Haskell Doc
1526 ;; under XEmacs 20.x
1527 (and (eq major-mode 'haskell-mode)
1528 (not (and (featurep 'xemacs)
1529 (string-match "^20" emacs-version)))))
1530 (let* ((imenu-info-alist (cdr (assoc kind imenu--index-alist)))
1531 ;; (names (mapcar 'car imenu-info-alist))
1532 (x (assoc obj imenu-info-alist)))
1534 (haskell-doc-grab-line x)
1537 ;; (error "Cannot get local functions in %s mode, sorry" major-mode))) )
1540 ;;@node Global fct type, Local fct type, Aux, Print fctsym
1541 ;;@subsection Global fct type
1544 ;; - modular way of defining a mapping of module name to file
1545 ;; - use a path to search for file (not just current directory)
1547 ;;@cindex haskell-doc-imported-list
1549 (defun haskell-doc-imported-list (outer-file)
1550 "Return a list of the imported modules in OUTER-FILE."
1551 (interactive "fName of outer `include' file: ") ; (buffer-file-name))
1552 (let ((imported-file-list (list outer-file))
1555 (switch-to-buffer (find-file-noselect outer-file))
1557 (goto-char (point-min))
1558 (while (re-search-forward "^\\s-*import\\s-+" nil t)
1559 (skip-chars-forward " \t")
1560 (setq start (point))
1562 (skip-chars-backward " \t")
1563 (let ( (file (concat (buffer-substring start (point)) ".hs")) )
1564 (if (file-exists-p file)
1565 (setq imported-file-list
1566 (cons file imported-file-list))))
1567 (let ( (file (concat (buffer-substring start (point)) ".lhs")) )
1568 (if (file-exists-p file)
1569 (setq imported-file-list
1570 (cons file imported-file-list))))
1572 (nreverse imported-file-list)
1573 ;;(message imported-file-list)
1576 ;; ToDo: generalise this to "Types" etc (not just "Variables")
1578 ;;@cindex haskell-doc-rescan-files
1580 (defun haskell-doc-rescan-files (filelist)
1581 "Does an `imenu' rescan on every file in FILELIST and returns the fct-list.
1582 This function switches to and potentially loads many buffers."
1584 (switch-to-buffer (find-file-noselect f))
1585 (imenu--make-index-alist)
1586 (let ( (fn-alist (cdr (assoc "Variables" imenu--index-alist)) ) )
1589 `(,(car x) . ,(haskell-doc-grab-line x)) )
1593 ;;@cindex haskell-doc-make-global-fct-index
1595 (defun haskell-doc-make-global-fct-index ()
1596 "Scan imported files for types of global fcts and update `haskell-doc-index'."
1598 (let* ( (this-buffer (current-buffer))
1599 (this-file (buffer-file-name))
1600 (x (haskell-doc-rescan-files (haskell-doc-imported-list this-file) )) )
1601 (switch-to-buffer this-buffer)
1602 ;; haskell-doc-index is buffer local => switch-buffer before setq
1603 (setq haskell-doc-index x) ) )
1605 ;; ToDo: use a separate munge-type function to format type concisely
1607 ;;@cindex haskell-doc-get-global-fct-type
1609 (defun haskell-doc-get-global-fct-type (&optional sym)
1610 "Get type for function symbol SYM by examining `haskell-doc-index'."
1611 (interactive) ; "fName of outer `include' file: \nsFct:")
1613 ;; (switch-to-buffer "*scratch*")
1614 ;; (goto-char (point-max))
1615 ;; ;; Produces a list of fct-type alists
1617 ;; (setq sym (progn (forward-word -1) (read (current-buffer)))))
1620 (let* ( (fn sym) ; (format "%s" sym))
1621 (fal haskell-doc-index)
1623 (while (not (null fal))
1624 (let* ( (l (car fal))
1626 (x (assoc fn (cdr l))) )
1628 (let* ( (ty (cdr x)) ; the type as string
1629 (idx (string-match "::" ty))
1632 (substring ty (+ idx 2)))) )
1633 (setq res (format "[%s] %s" f str))))
1634 (setq fal (cdr fal))))
1635 res))) ; (message res)) )
1637 ;;@node Local fct type, , Global fct type, Print fctsym
1638 ;;@subsection Local fct type
1640 ;;@cindex haskell-doc-get-and-format-fct-type
1642 (defun haskell-doc-get-and-format-fct-type (fn)
1643 "Get the type and kind of FN by checking local and global functions."
1646 (let ((docstring "")
1649 ;; is it a local function?
1650 (setq docstring (haskell-doc-get-imenu-info fn "Variables"))
1651 (if (not (null docstring))
1652 ;; (string-match (format "^%s\\s-+::\\s-+\\(.*\\)$" fn) docstring))
1653 (setq doc `(,docstring . "Variables"))) ; `(,(match-string 1 docstring) . "Variables") ))
1654 ;; is it a type declaration?
1655 (setq docstring (haskell-doc-get-imenu-info fn "Types"))
1656 (if (not (null docstring))
1657 ;; (string-match (format "^\\s-*type\\s-+%s.*$" fn) docstring))
1658 (setq doc `(,docstring . "Types"))) ; `(,(match-string 0 docstring) . "Types")) )
1659 (if (not (null docstring))
1660 ;; (string-match (format "^\\s-*data.*%s.*$" fn) docstring))
1661 (setq doc `(,docstring . "Data"))) ; (setq doc `(,(match-string 0 docstring) . "Data")) )
1662 ;; return the result
1666 ;;@node Movement, Bug Reports, Print fctsym, top
1668 ;; Functions for moving in text and extracting the current word under the cursor
1670 ;; HWL: my attempt at more efficient (current-word)
1672 ;; NB: this function is called from within the hooked print function;
1673 ;; therefore this function must not fail, otherwise the function will
1675 ;; if no word under the cursor return an empty string
1676 ;;@cindex haskell-doc-get-current-word
1677 (defun haskell-doc-get-current-word ()
1678 "Return the word under the cursor, or empty string if no word found."
1680 (buffer-substring-no-properties
1681 (progn (skip-syntax-backward "w_") (point))
1682 (progn (skip-syntax-forward "w_") (point)))))
1684 ;;@node Bug Reports, Visit home site, Movement, top
1685 ;;@section Bug Reports
1687 ;;@cindex haskell-doc-submit-bug-report
1688 ;; send a bug report
1689 (defun haskell-doc-submit-bug-report ()
1690 "Send email to the maintainer of `haskell-doc-mode'."
1692 ;; In case we can't find reporter...
1696 (and (y-or-n-p "Do you really want to submit a bug report? ")
1697 (reporter-submit-bug-report
1698 haskell-doc-maintainer ; address
1699 (concat "haskell-doc.el " haskell-doc-version) ; package
1700 haskell-doc-varlist ; varlist
1701 nil nil ; pre-/post-hooks
1702 "I have detected the following strange behaviour/bug in `haskell-doc-mode':\n")))
1703 ;; ...fail gracefully.
1706 (message "Sorry, reporter.el not found."))))
1708 ;;@node Visit home site, Index, Bug Reports, top
1709 ;;@section Visit home site
1711 ;;@cindex haskell-doc-visit-home
1713 (defun haskell-doc-visit-home ()
1714 "Jump to the main FTP site for `haskell-doc-mode'."
1716 (if (featurep 'xemacs)
1719 (dired-other-window haskell-doc-ftp-site))
1723 ;;@node Index, Token, Visit home site, top
1727 ;;* haskell-doc-ask-mouse-for-type::
1728 ;;* haskell-doc-check-active::
1729 ;;* haskell-doc-chop-off-context::
1730 ;;* haskell-doc-get-and-format-fct-type::
1731 ;;* haskell-doc-get-current-word::
1732 ;;* haskell-doc-get-global-fct-type::
1733 ;;* haskell-doc-get-imenu-info::
1734 ;;* haskell-doc-grab::
1735 ;;* haskell-doc-grab-line::
1736 ;;* haskell-doc-imported-list::
1737 ;;* haskell-doc-install-keymap::
1738 ;;* haskell-doc-is-of::
1739 ;;* haskell-doc-make-global-fct-index::
1740 ;;* haskell-doc-mode::
1741 ;;* haskell-doc-mode-print-current-symbol-info::
1742 ;;* haskell-doc-prelude-types::
1743 ;;* haskell-doc-rescan-files::
1744 ;;* haskell-doc-reserved-ids::
1745 ;;* haskell-doc-show-global-types::
1746 ;;* haskell-doc-show-prelude::
1747 ;;* haskell-doc-show-reserved::
1748 ;;* haskell-doc-show-strategy::
1749 ;;* haskell-doc-show-type::
1750 ;;* haskell-doc-show-user-defined::
1751 ;;* haskell-doc-strategy-ids::
1752 ;;* haskell-doc-string-nub-ws::
1753 ;;* haskell-doc-submit-bug-report::
1754 ;;* haskell-doc-visit-home::
1755 ;;* haskell-doc-wrapped-type-p::
1756 ;;* turn-off-haskell-doc-mode::
1757 ;;* turn-on-haskell-doc-mode::
1760 ;;@node Token, , Index, top
1763 (provide 'haskell-doc)
1765 ;;; haskell-doc.el ends here