https://wiki.haskell.org/api.php?action=feedcontributions&user=Hvr&feedformat=atomHaskellWiki - User contributions [en]2022-05-26T01:23:30ZUser contributionsMediaWiki 1.31.7https://wiki.haskell.org/index.php?title=Fairbairn_threshold&diff=62787Fairbairn threshold2019-02-23T19:41:54Z<p>Hvr: </p>
<hr />
<div>== Fairbairn Threshold ==<br />
<br />
Quoting Edward Kmett [https://mail.haskell.org/pipermail/libraries/2012-February/017548.html (src)]:<br />
<br />
----<br />
<br />
<blockquote><br />
The Fairbairn threshold is the point at which the effort of looking up or<br />
keeping track of the definition is outweighed by the effort of rederiving<br />
it or inlining it.<br />
<br />
The term was in much more common use several years ago.<br />
<br />
Adding every variant on every operation to the Prelude is certainly<br />
possible given infinite time, but this of course imposes a sort of indexing<br />
overhead mentally.<br />
<br />
The primary use of the Fairbairn threshold is as a litmus test to avoid<br />
giving names to trivial compositions, as there are a potentially explosive<br />
number of them. In particular any method whose definition isn't much longer<br />
than its name (e.g. fooBar = foo . bar) falls below the threshold.<br />
<br />
There are reasonable exceptions for especially common idioms, but it does<br />
provide a good rule of thumb.<br />
<br />
The effect is to encourage simple combinators that can be used in multiple<br />
situations, while avoiding naming the explosive number of combinations of<br />
those combinators.<br />
<br />
Given n combinators I can probably combine two of them in something like<br />
O(n^2) ways, so without the threshold as a rule of thumb you wind up with a<br />
much larger library, but no real greater utility and much higher cognitive<br />
overhead to track all the combinations.<br />
<br />
Further, the existence of some combinations tends to drive you to look for<br />
other ever larger combinations rather than learn how to compose combinators<br />
or spot the more general usage patterns yourself, so from a [https://en.wikipedia.org/wiki/POSIWID POSIWID]<br />
perspective, the threshold encourages better use of the functional<br />
programming style as well.<br />
</blockquote><br />
<br />
----</div>Hvrhttps://wiki.haskell.org/index.php?title=Fairbairn_threshold&diff=62786Fairbairn threshold2019-02-23T19:40:59Z<p>Hvr: Created page with "== Fairbairn threshold Quoting Edward Kmett [https://mail.haskell.org/pipermail/libraries/2012-February/017548.html (src)]: ---- <blockquote> The Fairbairn threshold is the..."</p>
<hr />
<div>== Fairbairn threshold<br />
<br />
Quoting Edward Kmett [https://mail.haskell.org/pipermail/libraries/2012-February/017548.html (src)]:<br />
<br />
----<br />
<br />
<blockquote><br />
The Fairbairn threshold is the point at which the effort of looking up or<br />
keeping track of the definition is outweighed by the effort of rederiving<br />
it or inlining it.<br />
<br />
The term was in much more common use several years ago.<br />
<br />
Adding every variant on every operation to the Prelude is certainly<br />
possible given infinite time, but this of course imposes a sort of indexing<br />
overhead mentally.<br />
<br />
The primary use of the Fairbairn threshold is as a litmus test to avoid<br />
giving names to trivial compositions, as there are a potentially explosive<br />
number of them. In particular any method whose definition isn't much longer<br />
than its name (e.g. fooBar = foo . bar) falls below the threshold.<br />
<br />
There are reasonable exceptions for especially common idioms, but it does<br />
provide a good rule of thumb.<br />
<br />
The effect is to encourage simple combinators that can be used in multiple<br />
situations, while avoiding naming the explosive number of combinations of<br />
those combinators.<br />
<br />
Given n combinators I can probably combine two of them in something like<br />
O(n^2) ways, so without the threshold as a rule of thumb you wind up with a<br />
much larger library, but no real greater utility and much higher cognitive<br />
overhead to track all the combinations.<br />
<br />
Further, the existence of some combinations tends to drive you to look for<br />
other ever larger combinations rather than learn how to compose combinators<br />
or spot the more general usage patterns yourself, so from a [https://en.wikipedia.org/wiki/POSIWID POSIWID]<br />
perspective, the threshold encourages better use of the functional<br />
programming style as well.<br />
</blockquote><br />
<br />
----</div>Hvrhttps://wiki.haskell.org/index.php?title=Cabal/NewBuild&diff=62536Cabal/NewBuild2018-06-23T18:31:56Z<p>Hvr: Created page with " This page provides information about <code>cabal new-build</code>, the main entry point into Cabal's new Nix-style local builds facility. == Official documentation == The l..."</p>
<hr />
<div><br />
This page provides information about <code>cabal new-build</code>, the main entry point into Cabal's new Nix-style local builds facility.<br />
<br />
== Official documentation ==<br />
<br />
The latest official documentation can be found in the Cabal User Guide, in chapter [http://cabal.readthedocs.io/en/latest/nix-local-build-overview.html 5. Nix-style Local Builds].<br />
<br />
== Additional Resources ==<br />
<br />
* Haskell at Work's [https://haskell-at-work.com/episodes/2018-05-13-introduction-to-cabal.html "Introduction to Cabal" screencast] includes an introduction to basic use of some of the <code>new-*</code> commands.</div>Hvrhttps://wiki.haskell.org/index.php?title=Haskell_in_5_steps&diff=62486Haskell in 5 steps2018-05-20T14:29:25Z<p>Hvr: Undo unethical revision 61013 by Snoyberg (talk)</p>
<hr />
<div>Haskell is a general purpose, purely functional programming language.<br />
This page will help you get started as quickly as possible.<br />
<br />
__TOC__<br />
<br />
== Install Haskell ==<br />
<br />
The recommended way to get started with programming Haskell is the [http://hackage.haskell.org/platform/ Haskell Platform]. The Platform comes with GHC, the de-facto standard Haskell compiler, with many useful tools that will let you program Haskell painlessly. The installation should be easy and simple enough on most operating systems.<br />
<br />
[http://tryhaskell.org/ Try Haskell] provides a less complete but quicker way to give Haskell a shot.<br />
<br />
== Start Haskell ==<br />
<br />
If you have installed the Haskell Platform, open a terminal and type '''ghci''' (the name of the executable of the GHC interpreter) at the command prompt. Alternatively, if you are on Windows, you may choose '''WinGHCi''' in the Start menu.<br />
<br />
<pre><br />
$ ghci<br />
GHCi, version 6.12.3: http://www.haskell.org/ghc/ :? for help<br />
Loading package base ... linking ... done.<br />
Prelude><br />
</pre><br />
<br />
And you are presented with a prompt. The Haskell system now attentively<br />
awaits your input.<br />
<br />
== Write your first Haskell program ==<br />
<br />
If you've learned to program another language, your first program<br />
probably was "Hello, world!", so let's do that:<br />
<br />
<haskell><br />
Prelude> "Hello, World!"<br />
"Hello, World!"<br />
</haskell><br />
<br />
The Haskell system evaluated the string, and printed the result. <br />
Or we can try a variation to print directly to standard output:<br />
<br />
<haskell><br />
Prelude> putStrLn "Hello World"<br />
Hello World<br />
</haskell><br />
<br />
Using a Haskell compiler, such as [http://haskell.org/ghc GHC], you can<br />
compile the code to a standalone executable. Create a source file<br />
'''hello.hs''' containing:<br />
<br />
<haskell><br />
main = putStrLn "Hello, World!"<br />
</haskell><br />
<br />
And compile it with:<br />
<br />
<pre><br />
$ ghc -o hello hello.hs<br />
</pre><br />
<br />
You can then run the executable ('''./hello''' on Unix systems, '''hello.exe''' on Windows):<br />
<br />
<pre><br />
$ ./hello<br />
Hello, World!<br />
</pre><br />
<br />
== Haskell the calculator ==<br />
<br />
Let's do something fun. In Haskell, your first true program is the<br />
factorial function. So back to the interpreter now and let's define it:<br />
<br />
<haskell><br />
Prelude> let fac n = if n == 0 then 1 else n * fac (n-1)<br />
</haskell><br />
<br />
This defines a new function called '''fac''' which computes the<br />
factorial of an integer.<br />
<br />
We can now run '''fac''' on some argument:<br />
<haskell><br />
Prelude> fac 42<br />
1405006117752879898543142606244511569936384000000000<br />
</haskell><br />
<br />
'''Congratulations!''' Programming made easy. Note that if you're using<br />
Hugs, you'll need to load the definition of '''fac''' from a file,<br />
'''fac.hs''', containing:<br />
<br />
<haskell><br />
fac n = if n == 0 then 1 else n * fac (n-1)<br />
</haskell><br />
<br />
And run it with Hugs as follows (this also works in GHCi):<br />
<br />
<haskell><br />
Hugs.Base> :load fac.hs<br />
Main> fac 42<br />
1405006117752879898543142606244511569936384000000000<br />
</haskell><br />
<br />
We can of course compile this program, to produce a standalone<br />
executable. In the file '''fac.hs''' we can write (and let's use<br />
elegant pattern matching syntax just for fun):<br />
<br />
<haskell><br />
fac 0 = 1<br />
fac n = n * fac (n-1)<br />
<br />
main = print (fac 42)<br />
</haskell><br />
<br />
which can then be compiled and run:<br />
<br />
<pre><br />
$ ghc -o fac fac.hs<br />
$ ./fac<br />
1405006117752879898543142606244511569936384000000000<br />
</pre><br />
<br />
'''Great!'''<br />
<br />
===Write your first parallel Haskell program===<br />
<br />
Haskell has good support for parallel and multicore programming. We can write a parallel program by adding `par` to expressions, like so:<br />
<br />
<haskell><br />
import Control.Parallel<br />
<br />
main = a `par` b `par` c `pseq` print (a + b + c)<br />
where<br />
a = ack 3 10<br />
b = fac 42<br />
c = fib 34<br />
<br />
fac 0 = 1<br />
fac n = n * fac (n-1)<br />
<br />
ack 0 n = n+1<br />
ack m 0 = ack (m-1) 1<br />
ack m n = ack (m-1) (ack m (n-1))<br />
<br />
fib 0 = 0<br />
fib 1 = 1<br />
fib n = fib (n-1) + fib (n-2)<br />
</haskell><br />
<br />
Compiling with -threaded and optimizations on:<br />
<br />
<pre><br />
$ ghc -O2 --make A.hs -threaded -rtsopts<br />
[1 of 1] Compiling Main ( A.hs, A.o )<br />
Linking A ...<br />
</pre><br />
<br />
''Note that in versions of GHC prior to GHC 7, you can leave off the -rtsopts flag''<br />
<br />
And now we can run our multicore program. Here across two cores:<br />
<br />
<pre><br />
$ time ./A +RTS -N2<br />
1405006117752879898543142606244511569936384005711076<br />
./A +RTS -N2 2.14s user 0.02s system 149% cpu 1.449 total<br />
</pre><br />
<br />
Congratulations! You are now programming your multicore!<br />
<br />
== Where to go from here ==<br />
<br />
There are many good Haskell tutorials and books. Here are some we recommend:<br />
<br />
'''Tutorials'''<br />
* [http://book.realworldhaskell.org/ Real World Haskell]<br />
* [[Learn_Haskell_in_10_minutes|Haskell in 10 minutes]]<br />
* [http://darcs.haskell.org/yaht/yaht.pdf Yet Another Haskell Tutorial] (English)<br />
* [http://www.haskell.org/tutorial/ A Gentle Introduction to Haskell] (English, [[Image:GentleFR.pdf|French PDF]])<br />
* [http://learnyouahaskell.com/ Learn You A Haskell For Great Good!]<br />
<br />
For a complete list of textbooks, references and tutorials:<br />
<br />
* [[Books and tutorials]]<br />
<br />
'''Join the community!'''<br />
<br />
Talk to others in the Haskell [[User_groups|community]].<br />
<br />
[[Category:Tutorials]]<br />
<br />
Languages: [[Haskell in 5 Schritten|de]] [[5 adımda Haskell|tur]] [[Cn/Haskell 入门五步走|zh/cn]] [[Tw/Haskell入門的5個步驟|zh/tw]] [[Haskell入門 5ステップ|ja]]</div>Hvrhttps://wiki.haskell.org/index.php?title=GHC/As_a_library&diff=62257GHC/As a library2017-12-22T15:40:54Z<p>Hvr: update links for ghc/ghc-paths packages</p>
<hr />
<div>''For instructions on the GHC API with GHC 6.8 or older please refer to [[GHC/As a library (up to 6.8)]]''<br />
<br />
__TOC__<br />
<br />
== Introduction ==<br />
<br />
GHC's functionality can be useful for more things than just compiling Haskell programs. Important use cases are programs that analyse (and perhaps transform) Haskell code. Others include loading Haskell code dynamically in a GHCi-like manner. For this reason, a lot of GHC's features can be accessed by programs which import the <tt>ghc</tt> package.<br />
<br />
The instructions on this page concern the API of GHC 6.10.1 and above. Please note that the GHC API is still in flux and may change quite significantly between major releases while we (the GHC team) provide new features or simplify certain aspects.<br />
<br />
<br />
== Getting Started ==<br />
<br />
To use the GHC API you need GHC 6.10.1 or above and import the [https://hackage.haskell.org/package/ghc <tt>ghc</tt> package].<br />
<pre><br />
ghc -package ghc my_program.hs<br />
</pre><br />
In most cases you probably also want to use the [http://hackage.haskell.org/package/ghc-paths <tt>ghc-paths</tt> package].<br />
<br />
Most of the common functionality is provided by the <tt>GHC</tt> module, but occasionally you may have to import other modules. See the GHC's [https://downloads.haskell.org/~ghc/latest/docs/html/libraries/ haddock documentation] for a list of these modules. One good entry point into the docs is [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html GHC].<br />
<br />
== A Simple Example ==<br />
<br />
The following little program essentially does what <tt>ghc --make</tt> does.<br />
<br />
<haskell><br />
{-# LANGUAGE CPP #-}<br />
import GHC<br />
import GHC.Paths ( libdir )<br />
import DynFlags<br />
<br />
main = <br />
#if __GLASGOW_HASKELL__ > 704<br />
defaultErrorHandler defaultFatalMessager defaultFlushOut $ do<br />
#else<br />
defaultErrorHandler defaultLogAction $ do<br />
#endif<br />
runGhc (Just libdir) $ do<br />
dflags <- getSessionDynFlags<br />
setSessionDynFlags dflags<br />
target <- guessTarget "test_main.hs" Nothing<br />
setTargets [target]<br />
load LoadAllTargets<br />
</haskell><br />
<br />
The outermost function, <tt>defaultErrorHandler</tt>, sets up proper exception handlers and prints an error message and exits with exit code 1 if it encounters one of these exceptions.<br />
<br />
Most of GHC's high-level API requires access to a current session. Therefore, these functions require to be called inside a monad that is an instance of the <tt>GhcMonad</tt> typeclass. Two default implementations of this typeclass are <tt>Ghc</tt> and <tt>GhcT</tt>. In the above example we used the <tt>Ghc</tt> monad since we don't need to track any extra state.<br />
<br />
The argument to <tt>runGhc</tt> is a bit tricky. GHC needs this to find its libraries, so the argument must refer to the directory that is printed by <tt>ghc --print-libdir</tt> for the ''same'' version of GHC that the program is being compiled with. Above we therefore use the <tt>ghc-paths</tt> package which provides this for us.<br />
<br />
== Another example ==<br />
<br />
Here we demonstrate calling [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:parseModule parseModule], [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:typecheckModule typecheckModule], [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:desugarModule desugarModule], [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:getNamesInScope getNamesInScope], and [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:getModuleGraph getModuleGraph]. This works for haskell-platform, ghc-7.0.3 to ghc-7.6.x. It also demonstrates how to enable some extensions.<br />
<br />
<haskell><br />
--A.hs<br />
--invoke: ghci -package ghc A.hs<br />
<br />
{-# LANGUAGE CPP #-}<br />
import GHC<br />
import Outputable<br />
<br />
import GHC.Paths ( libdir )<br />
--GHC.Paths is available via cabal install ghc-paths<br />
<br />
import DynFlags<br />
targetFile = "B.hs"<br />
<br />
main :: IO ()<br />
main = do<br />
res <- example<br />
#if __GLASGOW_HASKELL__ > 704<br />
str <- runGhc (Just libdir) $ do<br />
dflags <- getSessionDynFlags<br />
return $ showSDoc dflags $ ppr res<br />
putStrLn str<br />
#else<br />
putStrLn $ showSDoc ( ppr res )<br />
#endif<br />
<br />
example = <br />
#if __GLASGOW_HASKELL__ > 704<br />
defaultErrorHandler defaultFatalMessager defaultFlushOut $ do<br />
#else<br />
defaultErrorHandler defaultLogAction $ do<br />
#endif<br />
runGhc (Just libdir) $ do<br />
dflags <- getSessionDynFlags<br />
let dflags' = foldl xopt_set dflags<br />
[Opt_Cpp, Opt_ImplicitPrelude, Opt_MagicHash]<br />
setSessionDynFlags dflags'<br />
target <- guessTarget targetFile Nothing<br />
setTargets [target]<br />
load LoadAllTargets<br />
modSum <- getModSummary $ mkModuleName "B"<br />
p <- parseModule modSum<br />
t <- typecheckModule p<br />
d <- desugarModule t<br />
l <- loadModule d<br />
n <- getNamesInScope<br />
c <- return $ coreModule d<br />
<br />
g <- getModuleGraph<br />
mapM showModule g <br />
return $ (parsedSource d,"/n-----/n", typecheckedSource d)<br />
</haskell><br />
<br />
<haskell><br />
--B.hs<br />
module B where<br />
<br />
main = print "Hello, World!"<br />
<br />
</haskell><br />
<br />
== Running interactive statements ==<br />
<br />
Once you've loaded your module, you can run statements in that context, much as GHCi does, using the [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:runStmt runStmt] function.<br />
<br />
Given the modSum ModSummary obtained earlier, you can dump the results of your statement, if the result type is a Show instance:<br />
<haskell><br />
run :: GhcMonad m => ModSummary -> String -> m ()<br />
run modSum expr = do<br />
#if __GLASGOW_HASKELL__ < 704<br />
setContext [ms_mod modSum] []<br />
#else<br />
#if __GLASGOW_HASKELL__ < 706<br />
setContext [IIModule $ ms_mod modSum]<br />
#else<br />
setContext [IIModule $ moduleName $ ms_mod modSum] <br />
#endif <br />
#endif<br />
rr<- runStmt expr RunToCompletion<br />
case rr of<br />
RunOk ns-><br />
do<br />
let q=(qualName &&& qualModule) defaultUserStyle<br />
mapM_ (\n -> do<br />
mty <- lookupName n<br />
case mty of<br />
Just (AnId aid) -> do<br />
df <- getSessionDynFlags<br />
t <- gtry $ obtainTermFromId maxBound True aid<br />
evalDoc <- case t of<br />
Right term -> showTerm term<br />
Left exn -> return (text "*** Exception:" <+><br />
text (show (exn :: SomeException)))<br />
liftIO $ putStrLn $ showSDocForUser df q evalDoc<br />
return ()<br />
_ -> return ()<br />
) ns<br />
RunException e -> liftIO $ print e<br />
_ -> return () <br />
</haskell><br />
<br />
Note the call to [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:setContext setContext]. Basically then runStmt return the names bound by the statement, which you then lookup via [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:lookupName lookupName] and [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:obtainTermFromId obtainTermFromId] and print via [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/Debugger.html#v:showTerm showTerm].<br />
<br />
=== Session parameters for interactive evaluation ===<br />
<br />
The [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#t:DynFlags DynFlags] contain different flags that may be useful when working with the API, mainly to avoid generating the linker output. You need to be careful when you set them, though, since they can have long ranging effects. A common setting would be:<br />
<br />
<haskell><br />
setSessionDynFlags oldFlgs {hscTarget = HscInterpreted, ghcLink = LinkInMemory , ghcMode = CompManager }<br />
</haskell><br />
<br />
* '''HscInterpreted''' means you can still get TemplateHaskell support but you're not generating output code<br />
* '''LinkInMemory''' is required to be able to reload modules properly. Using '''NoLink''' will break that: reloading a module won't allow allow to run interactive statements on the new version of the module<br />
* '''CompManager''' ensures dependent modules are built and loaded if needed.<br />
<br />
<br />
== Libraries ==<br />
<br />
* [https://hackage.haskell.org/package/plugins plugins], dynamic linking and runtime evaluation of Haskell, and C, including dependency chasing and package resolution. The current version (2017-01-26, version 1.5.5.0) is not compilable on Windows systems, or with GHC >= 8<br />
* [https://hackage.haskell.org/package/hint hint], this library defines an Interpreter monad. It allows to load Haskell modules, browse them, type-check and evaluate strings with Haskell expressions and even coerce them into values.<br />
<br />
<br />
== Further reading ==<br />
<br />
* [https://downloads.haskell.org/~ghc/latest/docs/html/ GHC API documentation] (click on the GHC API link on that page.)<br />
* Blog posts from "(parentheses)": [http://parenz.wordpress.com/2013/08/17/ghc-api-interpreted-compiled-and-package-modules/ GHC API: Interpreted, compiled and package modules], [http://parenz.wordpress.com/2013/07/29/ghc-packagedb/ Adding a package database to the GHC API session], [http://parenz.wordpress.com/2013/07/23/on-custom-error-handlers-for-ghc-api/ On custom error handlers for the GHC API].<br />
* [http://mistuke.wordpress.com/category/vsx/ Great blog post] about using the GHC API to get "QuickInfo" in a Visual Studio binding for Haskell.</div>Hvrhttps://wiki.haskell.org/index.php?title=Pvp&diff=61147Pvp2016-10-02T20:31:47Z<p>Hvr: Redirected page to pvp:</p>
<hr />
<div>#REDIRECT [[PVP:]]</div>Hvrhttps://wiki.haskell.org/index.php?title=Package_versioning_policy&diff=61146Package versioning policy2016-10-02T20:31:18Z<p>Hvr: Redirected page to pvp:</p>
<hr />
<div>#REDIRECT [[PVP:]]<br />
<br />
----<br />
<br />
<big>'''This document has moved. Please refer to http://pvp.haskell.org/ for its new location.'''</big><br />
<br />
----<br />
<br />
== Rationale ==<br />
<br />
The goal of a versioning system is to inform clients of a package of changes to that package that might affect them, and to provide a way for clients to specify a particular version or range of versions of a dependency that they are compatible with.<br />
<br />
[http://haskell.org/cabal Cabal] provides the raw materials for versioning: it allows packages to specify their own version, and it allows dependencies that specify which versions of the dependent package are acceptable. Cabal will select dependencies based on the constraints.<br />
<br />
What is missing from this picture is a ''policy'' that tells the library developer how to set their version numbers, and tells a client how to write a dependency that means their package will not try to compile against an incompatible dependency. For some time there has been an informal policy in use in the Haskell community, but it became clear that we were running into trouble with incorrectly-specified dependencies and unbuildable packages, so this page is an attempt to formalize the policy.<br />
<br />
== Version numbers ==<br />
<br />
[[File:PVP.svg|thumb|A handy unfinished (!) draft of a reference describing the PVP decision tree]]<br />
<br />
A package version number should have the form ''A.B.C'', and may optionally have any number of additional components, for example 2.1.0.4 (in this case, ''A''=2, ''B''=1, ''C=0''). This policy defines the meaning of the first three components ''A-C'', the other components can be used in any way the package maintainer sees fit.<br />
<br />
Version number ordering is already defined by Cabal as the lexicographic ordering of the components. For example, 2.0.1 > 1.3.2, and 2.0.1.0 > 2.0.1. (The <tt>Data.Version.Version</tt> type and its <tt>Ord</tt> instance embody this ordering).<br />
<br />
''A.B'' is known as the ''major'' version number, and ''C'' the ''minor'' version number. When a package is updated, the following rules govern how the version number must change relative to the previous version:<br />
<br />
# If any entity was removed, or the types of any entities or the definitions of datatypes or classes were changed, or [[orphan instance]]s were added or any instances were removed, then the new ''A.B'' must be greater than the previous ''A.B''. Note that modifying imports or depending on a newer version of another package may cause extra orphan instances to be exported and thus force a major version change.<br />
# Otherwise, if only new bindings, types, classes, non-orphan instances or modules (but see below) were added to the interface, then ''A.B'' may remain the same but the new ''C'' must be greater than the old ''C''. Note that modifying imports or depending on a newer version of another package may cause extra non-orphan instances to be exported and thus force a minor version change.<br />
# Otherwise, ''A.B.C'' may remain the same (other version components may change).<br />
<br />
Hence ''A.B.C'' uniquely identifies the API. A client that wants to specify that they depend on a particular version of the API can specify a particular ''A.B.C'' and be sure of getting that API only. For example, <tt>build-depends: mypkg >= 2.1.1 && < 2.1.2</tt>.<br />
<br />
Often a package maintainer wants to add to an API without breaking backwards compatibility, and in that case they can follow the rules of point 2, and increase only ''C''. A client can specify that they are [[Import modules properly|insensitive to additions to the API]] by allowing a range of ''C'' values, e.g. <tt>build-depends: base >= 2.1.1 && < 2.2</tt>.<br />
<br />
If a package defines an orphan instance, it must depend on the minor version of the packages that define the data type and the type class to be backwards compatible. For example, <tt>build-depends: mypkg >= 2.1.1 && < 2.1.2</tt>.<br />
<br />
=== Deprecation ===<br />
<br />
Deprecated entities (via a <tt>DEPRECATED</tt> pragma) should probably be counted as removed for the purposes of upgrading the API, because packages that use <tt>-Werror</tt> will be broken by the deprecation.<br />
<br />
=== Adding new modules ===<br />
<br />
Adding new modules might cause an unavoidable name collision in dependent code. However, this is usually pretty unlikely, especially if you keep to your own namespace, so only an increase of the minor version number is required. If, however, your added module name is taken from another package (e.g. when <tt>network-bytestring</tt> was merged into <tt>network</tt>) or is quite general (<tt>Data.Set</tt> or something similar) then the version increase should be major.<br />
<br />
=== Leaking instances ===<br />
<br />
There is a case where addition or removal of an instance in a package, that the user doesn't depend on directly, can still lead to compilation failures. Consider these three packages:<br />
<br />
Package A:<br />
<haskell><br />
module PackageA where<br />
<br />
class Monad m => MonadLogger m<br />
instance MonadLogger IO<br />
</haskell><br />
<br />
Package B, depends on package A:<br />
<haskell><br />
module PackageB where<br />
<br />
import PackageA<br />
<br />
f :: MonadLogger m => Int -> m String<br />
f = return . show<br />
</haskell><br />
<br />
Package C, depends on package B:<br />
<haskell><br />
module Package C where<br />
<br />
import PackageB<br />
<br />
main :: IO ()<br />
main = f 5 >>= print<br />
</haskell><br />
<br />
Now consider this scenario:<br />
<br />
# Package A removes the <hask>IO</hask> instance and gets its major version number bumped, as required by the PVP.<br />
# Package B, which can still work with the old and new version of package A, changes its dependency on package A to allow for both versions. Package B only gets a patch-level bump.<br />
# Package C might or might not compile, depending on which patch-level version of package B is used.<br />
<br />
The PVP could require that package B bumps its major version number as it now (re-)exports one fewer instances. This will however require more frequent version bumps in the whole ecosystem. As a pragmatic solution, for now the PVP doesn't required a major version bump in this case and instead leaves it to package C to add a dependency on package A to handle this situation.<br />
<br />
=== Version tags ===<br />
<br />
The components of the version number must be numbers! Historically Cabal supported version numbers with string tags at the end, e.g. <tt>1.0-beta</tt> This proved not to work well because the ordering for tags was not well defined. Version tags are [https://github.com/haskell/cabal/issues/890 no longer supported] and mostly ignored, however some tools will fail in some circumstances if they encounter them.<br />
<br />
This can sometimes trip you up if you accidentally stumble into using the deprecated tags syntax without realising it, for example a version number with a date like <tt>1.0.2014-01-27</tt> would be interpreted as the version <tt>1.0.2014</tt> with tags <tt>01</tt> and <tt>27</tt>.<br />
<br />
== Dependencies in Cabal ==<br />
<br />
When publishing a Cabal package, you should ensure that your dependencies in the <tt>build-depends</tt> field are accurate. This means specifying not only lower bounds, but also upper bounds on every dependency. <br />
<br />
At some point in the future, Hackage may refuse to accept packages that do not follow this convention. The aim is that before this happens, we will put in place tool support that makes it easier to follow the convention and less painful when dependencies are updated.<br />
<br />
To minimize breakage when new package versions are released, you can use dependencies that are insensitive to minor version changes (e.g. <tt>foo >= 1.2.1 && < 1.3</tt>). However, note that this approach is slightly risky: when a package exports more things than before, there is a chance that your code will fail to compile due to new name-clash errors. The risk from new name clashes may be small, but you are on the safe side if you [[Import modules properly|import identifiers explicitly or using qualification]].<br />
<br />
== Version syntax ==<br />
<br />
Since Cabal 1.6, you can specify an exact API version according to this policy with the special syntax <tt>package == 1.1.4.*</tt> or an API version up to additions with <tt>package == 1.1.*</tt>. The former translates into <tt>package >= 1.1.4 && < 1.1.5</tt>, for example - notice that 1.1.4 ''is'' included, rather than just including 1.1.4.0.<br />
<br />
== Tools ==<br />
<br />
* script to check for API changes in gtk2hs: http://code.haskell.org/gtk2hs/tools/apidiff/<br />
* [http://hackage.haskell.org/package/precis precis] - a simple tool for a first approximation of package API differences, see the [http://www.haskell.org/pipermail/haskell-cafe/2010-April/077023.html announcement]<br />
* {{HackagePackage|id=check-pvp}} is a program that checks for consistency between package dependencies and import style.<br />
<br />
== Related ==<br />
<br />
* [[Sven Moritz Hallberg]], "[[The_Monad.Reader/Issue2/EternalCompatibilityInTheory|Eternal compatibility in theory]]," [[The Monad.Reader]], [[The Monad.Reader/Issue2|Issue 2]]<br />
* [http://semver.org/ Semantic Versioning] is similar, but allows for version tags and defines how tags affect the ordering.</div>Hvrhttps://wiki.haskell.org/index.php?title=Package_versioning_policy&diff=60925Package versioning policy2016-07-20T16:52:06Z<p>Hvr: add signpost to pvp.haskell.org</p>
<hr />
<div>----<br />
<br />
<big>'''This document has moved. Please refer to http://pvp.haskell.org/ for its new location.'''</big><br />
<br />
----<br />
<br />
== Rationale ==<br />
<br />
The goal of a versioning system is to inform clients of a package of changes to that package that might affect them, and to provide a way for clients to specify a particular version or range of versions of a dependency that they are compatible with.<br />
<br />
[http://haskell.org/cabal Cabal] provides the raw materials for versioning: it allows packages to specify their own version, and it allows dependencies that specify which versions of the dependent package are acceptable. Cabal will select dependencies based on the constraints.<br />
<br />
What is missing from this picture is a ''policy'' that tells the library developer how to set their version numbers, and tells a client how to write a dependency that means their package will not try to compile against an incompatible dependency. For some time there has been an informal policy in use in the Haskell community, but it became clear that we were running into trouble with incorrectly-specified dependencies and unbuildable packages, so this page is an attempt to formalize the policy.<br />
<br />
== Version numbers ==<br />
<br />
[[File:PVP.svg|thumb|A handy unfinished (!) draft of a reference describing the PVP decision tree]]<br />
<br />
A package version number should have the form ''A.B.C'', and may optionally have any number of additional components, for example 2.1.0.4 (in this case, ''A''=2, ''B''=1, ''C=0''). This policy defines the meaning of the first three components ''A-C'', the other components can be used in any way the package maintainer sees fit.<br />
<br />
Version number ordering is already defined by Cabal as the lexicographic ordering of the components. For example, 2.0.1 > 1.3.2, and 2.0.1.0 > 2.0.1. (The <tt>Data.Version.Version</tt> type and its <tt>Ord</tt> instance embody this ordering).<br />
<br />
''A.B'' is known as the ''major'' version number, and ''C'' the ''minor'' version number. When a package is updated, the following rules govern how the version number must change relative to the previous version:<br />
<br />
# If any entity was removed, or the types of any entities or the definitions of datatypes or classes were changed, or [[orphan instance]]s were added or any instances were removed, then the new ''A.B'' must be greater than the previous ''A.B''. Note that modifying imports or depending on a newer version of another package may cause extra orphan instances to be exported and thus force a major version change.<br />
# Otherwise, if only new bindings, types, classes, non-orphan instances or modules (but see below) were added to the interface, then ''A.B'' may remain the same but the new ''C'' must be greater than the old ''C''. Note that modifying imports or depending on a newer version of another package may cause extra non-orphan instances to be exported and thus force a minor version change.<br />
# Otherwise, ''A.B.C'' may remain the same (other version components may change).<br />
<br />
Hence ''A.B.C'' uniquely identifies the API. A client that wants to specify that they depend on a particular version of the API can specify a particular ''A.B.C'' and be sure of getting that API only. For example, <tt>build-depends: mypkg >= 2.1.1 && < 2.1.2</tt>.<br />
<br />
Often a package maintainer wants to add to an API without breaking backwards compatibility, and in that case they can follow the rules of point 2, and increase only ''C''. A client can specify that they are [[Import modules properly|insensitive to additions to the API]] by allowing a range of ''C'' values, e.g. <tt>build-depends: base >= 2.1.1 && < 2.2</tt>.<br />
<br />
If a package defines an orphan instance, it must depend on the minor version of the packages that define the data type and the type class to be backwards compatible. For example, <tt>build-depends: mypkg >= 2.1.1 && < 2.1.2</tt>.<br />
<br />
=== Deprecation ===<br />
<br />
Deprecated entities (via a <tt>DEPRECATED</tt> pragma) should probably be counted as removed for the purposes of upgrading the API, because packages that use <tt>-Werror</tt> will be broken by the deprecation.<br />
<br />
=== Adding new modules ===<br />
<br />
Adding new modules might cause an unavoidable name collision in dependent code. However, this is usually pretty unlikely, especially if you keep to your own namespace, so only an increase of the minor version number is required. If, however, your added module name is taken from another package (e.g. when <tt>network-bytestring</tt> was merged into <tt>network</tt>) or is quite general (<tt>Data.Set</tt> or something similar) then the version increase should be major.<br />
<br />
=== Leaking instances ===<br />
<br />
There is a case where addition or removal of an instance in a package, that the user doesn't depend on directly, can still lead to compilation failures. Consider these three packages:<br />
<br />
Package A:<br />
<haskell><br />
module PackageA where<br />
<br />
class Monad m => MonadLogger m<br />
instance MonadLogger IO<br />
</haskell><br />
<br />
Package B, depends on package A:<br />
<haskell><br />
module PackageB where<br />
<br />
import PackageA<br />
<br />
f :: MonadLogger m => Int -> m String<br />
f = return . show<br />
</haskell><br />
<br />
Package C, depends on package B:<br />
<haskell><br />
module Package C where<br />
<br />
import PackageB<br />
<br />
main :: IO ()<br />
main = f 5 >>= print<br />
</haskell><br />
<br />
Now consider this scenario:<br />
<br />
# Package A removes the <hask>IO</hask> instance and gets its major version number bumped, as required by the PVP.<br />
# Package B, which can still work with the old and new version of package A, changes its dependency on package A to allow for both versions. Package B only gets a patch-level bump.<br />
# Package C might or might not compile, depending on which patch-level version of package B is used.<br />
<br />
The PVP could require that package B bumps its major version number as it now (re-)exports one fewer instances. This will however require more frequent version bumps in the whole ecosystem. As a pragmatic solution, for now the PVP doesn't required a major version bump in this case and instead leaves it to package C to add a dependency on package A to handle this situation.<br />
<br />
=== Version tags ===<br />
<br />
The components of the version number must be numbers! Historically Cabal supported version numbers with string tags at the end, e.g. <tt>1.0-beta</tt> This proved not to work well because the ordering for tags was not well defined. Version tags are [https://github.com/haskell/cabal/issues/890 no longer supported] and mostly ignored, however some tools will fail in some circumstances if they encounter them.<br />
<br />
This can sometimes trip you up if you accidentally stumble into using the deprecated tags syntax without realising it, for example a version number with a date like <tt>1.0.2014-01-27</tt> would be interpreted as the version <tt>1.0.2014</tt> with tags <tt>01</tt> and <tt>27</tt>.<br />
<br />
== Dependencies in Cabal ==<br />
<br />
When publishing a Cabal package, you should ensure that your dependencies in the <tt>build-depends</tt> field are accurate. This means specifying not only lower bounds, but also upper bounds on every dependency. <br />
<br />
At some point in the future, Hackage may refuse to accept packages that do not follow this convention. The aim is that before this happens, we will put in place tool support that makes it easier to follow the convention and less painful when dependencies are updated.<br />
<br />
To minimize breakage when new package versions are released, you can use dependencies that are insensitive to minor version changes (e.g. <tt>foo >= 1.2.1 && < 1.3</tt>). However, note that this approach is slightly risky: when a package exports more things than before, there is a chance that your code will fail to compile due to new name-clash errors. The risk from new name clashes may be small, but you are on the safe side if you [[Import modules properly|import identifiers explicitly or using qualification]].<br />
<br />
== Version syntax ==<br />
<br />
Since Cabal 1.6, you can specify an exact API version according to this policy with the special syntax <tt>package == 1.1.4.*</tt> or an API version up to additions with <tt>package == 1.1.*</tt>. The former translates into <tt>package >= 1.1.4 && < 1.1.5</tt>, for example - notice that 1.1.4 ''is'' included, rather than just including 1.1.4.0.<br />
<br />
== Tools ==<br />
<br />
* script to check for API changes in gtk2hs: http://code.haskell.org/gtk2hs/tools/apidiff/<br />
* [http://hackage.haskell.org/package/precis precis] - a simple tool for a first approximation of package API differences, see the [http://www.haskell.org/pipermail/haskell-cafe/2010-April/077023.html announcement]<br />
* {{HackagePackage|id=check-pvp}} is a program that checks for consistency between package dependencies and import style.<br />
<br />
== Related ==<br />
<br />
* [[Sven Moritz Hallberg]], "[[The_Monad.Reader/Issue2/EternalCompatibilityInTheory|Eternal compatibility in theory]]," [[The Monad.Reader]], [[The Monad.Reader/Issue2|Issue 2]]<br />
* [http://semver.org/ Semantic Versioning] is similar, but allows for version tags and defines how tags affect the ordering.</div>Hvrhttps://wiki.haskell.org/index.php?title=Functor-Applicative-Monad_Proposal&diff=60290Functor-Applicative-Monad Proposal2015-10-24T11:46:41Z<p>Hvr: /* Future-proofing current code */</p>
<hr />
<div>Haskell calls a couple of historical accidents its own. While some of them, such as the "number classes" hierarchy, can be justified by pragmatism or lack of a strictly better suggestion, there is one thing that stood out as, well, not that: Applicative not being a superclass of Monad.<br />
<br />
The topic has been discussed multiple times in the past (cf. link section at the very end). '''This article describes the Haskell 2014 Applicative => Monad proposal (AMP)''', which was then implemented in GHC 7.10.<br />
<br />
Some relevant links:<br />
* [https://github.com/quchen/articles/blob/master/applicative_monad.md Initial text of the Haskell 2014 AMP]<br />
* [http://thread.gmane.org/gmane.comp.lang.haskell.libraries/19482 AMP mailing list discussion]<br />
* Phase one: ticket [http://hackage.haskell.org/trac/ghc/ticket/8004 #8004]<br />
<br />
<br />
<br />
== Proposal contents ==<br />
<br />
The list of changes is as follows:<br />
<br />
# Applicative becomes a superclass of Monad, and is added to the Prelude.<br />
# Alternative becomes a superclass of MonadPlus (in addition to Monad, of course).<br />
# <s><hask>join</hask> is promoted into the Monad typeclass.</s> - Left out due to [https://ghc.haskell.org/trac/ghc/wiki/Roles2#join nontrivial breaking interaction] with [[Roles]]. Will "probably be fixed in the future", but for now it's off the table.<br />
<br />
The general rationale behind these changes:<br />
<br />
# ''Break as little code as possible.'' For example, do not move <hask>return</hask> to Applicative and remove <hask>pure</hask>. Instead, leave <hask>return</hask> in Monad, and give it <hask>pure</hask> as default implementation.<br />
# ''Change only things that are closely related to the proposal.'' For example, using <hask>join</hask> in a monad definition requires it to be a functor, so it goes hand in hand with the AMP. On the other hand, removing <hask>fail</hask> has nothing to do with what we're trying to accomplish.<br />
<br />
== Future-proofing current code ==<br />
<br />
GHC 7.8 will issue two types of warnings in order to encourage wide-scale code fixing. The following describes how to get rid of them, and as a result ensures your code builds both now and after the AMP is finished. For a more extensive and up-to-date guide, see also the [https://ghc.haskell.org/trac/ghc/wiki/Migration/7.10#base-4.8.0.0 GHC 7.10 migration guide].<br />
<br />
=== Missing superclasses ===<br />
<br />
(Warnings of the type "Warning: X is an instance of C, but not D")<br />
<br />
* Add Applicative/Functor instances for all your Monads. You can simply derive these instances from the Monad by adding the following code:<br />
<haskell><br />
import Control.Applicative (Applicative(..))<br />
import Control.Monad (liftM, ap)<br />
<br />
-- Monad m<br />
<br />
instance Functor m where<br />
fmap = liftM<br />
<br />
instance Applicative m where<br />
pure = {- move the definition of `return` from the `Monad` instance here -}<br />
(<*>) = ap<br />
<br />
instance Monad m where<br />
return = pure -- redundant since GHC 7.10 due to default impl<br />
</haskell><br />
<br />
Moreover, there are some subtle issues regarding the <code>(>>)</code> operator, see [https://ghc.haskell.org/trac/ghc/wiki/Migration/7.10#base-4.8.0.0] for more details.<br />
<br />
* Add an Alternative instance for all instances of MonadPlus. This can again be done easily using<br />
<haskell><br />
import Control.Applicative (Alternative(..))<br />
import Control.Monad (mzero, mplus)<br />
<br />
-- MonadPlus m<br />
<br />
instance Alternative m where<br />
(<|>) = mplus<br />
empty = mzero<br />
</haskell><br />
<br />
=== Future Prelude names ===<br />
<br />
"The name X clashes with a future Prelude name" - Prelude will export functions called <hask><*></hask>, <hask>join</hask> and <hask>pure</hask>, so if a module defines its own versions of them, there will be name clashes. There are multiple ways of getting rid of this type of warning (in a future-proof way).<br />
<br />
# Change your code to not define functions named <hask><*></hask>, <hask>join</hask> or <hask>pure</hask>.<br />
# Import Prelude definitions you need explicitly. For example, <hask>import Prelude (map, (+))</hask> would not import <hask>join</hask>, so no warning is issued as the module is compatible with the Prelude exporting <hask>join</hask>. <hask>hiding</hask>.<br />
# Due to GHC internals, you cannot use <hask>hiding (join, (<*>), pure)</hask> to silence the warnings, although this method would be future-proof. If you want to use <hask>hiding</hask>, you will have to silence the warnings using a sledgehammer <code>-fno-warn-amp</code> compiler flag. (If you do so make sure you know what you're doing, otherwise your module ''will'' break in 7.10.) To make 7.10 not complain about the then unrecognized flag, it's best to specify it in a CPP block,<br />
<haskell><br />
{-# LANGUAGE CPP #-}<br />
#if __GLASGOW_HASKELL__ >= 707 && __GLASGOW_HASKELL__ < 710<br />
{-# OPTIONS_GHC -fno-warn-amp #-}<br />
#endif<br />
</haskell><br />
<br />
== Discussion and consequences ==<br />
<br />
<br />
=== It's the right thing to do™ ===<br />
<br />
Math. You've all heard this one, it's good and compelling so I don't need to spell it out.<br />
<br />
<br />
=== Redundant functions ===<br />
<br />
* <hask>pure</hask> and <hask>return</hask> do the same thing.<br />
* <hask>>></hask> and <hask>*></hask> are identical.<br />
* <hask>liftM</hask> and <hask>liftA</hask> are <hask>fmap</hask>. The <hask>liftM*</hask> are <hask>liftA*</hask>, <hask><*></hask> is <hask>ap</hask>.<br />
* Prelude's <hask>sequence</hask> requires <hask>Monad</hask> right now, while <hask>Applicative</hask> is sufficient to implement it. The more general version of this issue is captured by <hask>Data.Traversable</hask>, whose main typeclass implements the *same* functionality twice, namely <hask>traverse</hask> and <hask>mapM</hask>, and <hask>sequenceA</hask> and <hask>sequence</hask>.<br />
* The <hask>WrappedMonad</hask> type from <hask>Control.Applicative</hask> provides a semi-automatic way to using Functor/Applicative/Alternative functions for Monad/MonadPlus instances as a makeshift patch.<br />
<br />
That very much violates the "don't repeat yourself" principle, and even more so it ''forces'' the programmer to repeat himself to achieve maximal generality. It may be too late to take all redundancies out, but at least we can prevent new ones from being created.<br />
<br />
(Note that it is not proposed to remove any functions for compatibility reasons. Maybe some of them can be phased out in the long run, but that's beyond scope here.)<br />
<br />
<br />
=== Using Functor/Applicative functions in monadic code ===<br />
<br />
Whenever there's Monad code, you can use Functor/Applicative functions, without introducing an additional constraint. Keep in mind that "Functor/Applicative functions" does not only include what their typeclasses define but many more, for example <hask>void</hask>, <hask>(<$>)</hask>, <hask>(<**>)</hask>.<br />
<br />
Even if you think you have monadic code, strictly using the least restrictive functions may result in something that requires only Applicative. This is similar to writing a function that needs <hask>Int</hask>, but it turns out any <hask>Integral</hask> will do - more polymorphism for free.<br />
<br />
<br />
=== Compatibility issues ===<br />
<br />
These are the kinds of issues to be expected:<br />
<br />
# Monads lacking Functor or Applicative instances. This is easily fixable by either setting <hask>fmap = liftM</hask>, <hask>pure = return</hask> and <hask>(<*>) = ap</hask>, although more efficient implementations may exist, or by moving an already existing definition from <hask>Control.Applicative</hask> to the appropriate module.<br />
# This one is specific to building GHC: importing <hask>Control.Monad/Applicative</hask> introduces a circular module dependency. In this case, one can rely on handwritten implementations of the desired function, e.g. <hask>ap f x = f >>= ...</hask>.<br />
# Libraries using their own <hask>(<*>)</hask>. This one is potentially the most laborious consequence. For building GHC though, this only concerns Hoopl, and a handful of renames.<br />
<br />
<br />
<br />
=== Beginner friendliness ===<br />
<br />
How often did you say ...<br />
<br />
* "A Monad is always an Applicative but due to historical reasons it's not but you can easily verify it by setting <hask>pure = return</hask> and <hask>(<*>) = ap</hask>"<br />
* "<hask>liftM</hask> is <hask>fmap</hask> but not really." - "So when should I use <hask>fmap</hask> and when <hask>liftM</hask>?" - ''sigh''<br />
<br />
With the new hierarchy, the answer would ''always'' be "use the least restrictive one".<br />
<br />
== Applying the AMP to GHC and then Haskell in practice ==<br />
<br />
Proposed is a gradual introduction of the AMP in three phases:<br />
<br />
<br />
=== Prepare GHC ===<br />
<br />
Using a GHC fork with the full patch applied, find and fix all compilation errors introduced by the change by adding Functor/Applicative instances for all Monads.<br />
<br />
According to SPJ, adding an ad-hoc warning of sorts "Monad without Applicative detected" is not a problem, which will be crucial for the next phase. More specifically, issue a warning if:<br />
<br />
* Monad without Applicative<br />
* MonadPlus without Alternative<br />
* One of <hask><*></hask>, <hask>pure</hask>, <hask>join</hask> is defined in a different context to avoid naming conflicts, as these functions will go into the Prelude<br />
<br />
=== Prepare Hackage ===<br />
<br />
The warning just mentioned will hint to all authors that they should fix (or help others fix) the non-complying packages. This will ideally lead to libraries eventually adding Applicative instances, and changing their APIs if they redefine operators like <hask><*></hask>.<br />
<br />
After enough time has passed by so libraries adapted to the circumstances, move on to the next phase.<br />
<br />
<br />
=== Apply the proposal ===<br />
<br />
Once Hackage is prepared, applying the changes to the Base package is painless. However, this is not primarily a GHC, but a Haskell change. The previous steps were basically preparing the landscape, and when we've (hopefully) found out that it is a good idea to go through with it, it can be proposed to go into the Report. If we make it this far, the AMP should pass quite easily.<br />
<br />
<br />
<br />
== Previous proposals ==<br />
<br />
* Early 2011: [http://hackage.haskell.org/trac/ghc/ticket/4834 GHC ticket] &ndash; changes similar to this proposal, but closed as "not GHC, but Haskell". See [http://thread.gmane.org/gmane.comp.lang.haskell.libraries/14883/focus=14905 here] for the associated discussion.<br />
* [[The Other Prelude]]<br />
<br />
<br />
[[Category:Proposals]]<br />
[[Category:Functor]]<br />
[[Category:Applicative Functor]]<br />
[[Category:Monad]]</div>Hvrhttps://wiki.haskell.org/index.php?title=Functor-Applicative-Monad_Proposal&diff=60289Functor-Applicative-Monad Proposal2015-10-24T11:44:16Z<p>Hvr: /* Missing superclasses */</p>
<hr />
<div>Haskell calls a couple of historical accidents its own. While some of them, such as the "number classes" hierarchy, can be justified by pragmatism or lack of a strictly better suggestion, there is one thing that stood out as, well, not that: Applicative not being a superclass of Monad.<br />
<br />
The topic has been discussed multiple times in the past (cf. link section at the very end). '''This article describes the Haskell 2014 Applicative => Monad proposal (AMP)''', which was then implemented in GHC 7.10.<br />
<br />
Some relevant links:<br />
* [https://github.com/quchen/articles/blob/master/applicative_monad.md Initial text of the Haskell 2014 AMP]<br />
* [http://thread.gmane.org/gmane.comp.lang.haskell.libraries/19482 AMP mailing list discussion]<br />
* Phase one: ticket [http://hackage.haskell.org/trac/ghc/ticket/8004 #8004]<br />
<br />
<br />
<br />
== Proposal contents ==<br />
<br />
The list of changes is as follows:<br />
<br />
# Applicative becomes a superclass of Monad, and is added to the Prelude.<br />
# Alternative becomes a superclass of MonadPlus (in addition to Monad, of course).<br />
# <s><hask>join</hask> is promoted into the Monad typeclass.</s> - Left out due to [https://ghc.haskell.org/trac/ghc/wiki/Roles2#join nontrivial breaking interaction] with [[Roles]]. Will "probably be fixed in the future", but for now it's off the table.<br />
<br />
The general rationale behind these changes:<br />
<br />
# ''Break as little code as possible.'' For example, do not move <hask>return</hask> to Applicative and remove <hask>pure</hask>. Instead, leave <hask>return</hask> in Monad, and give it <hask>pure</hask> as default implementation.<br />
# ''Change only things that are closely related to the proposal.'' For example, using <hask>join</hask> in a monad definition requires it to be a functor, so it goes hand in hand with the AMP. On the other hand, removing <hask>fail</hask> has nothing to do with what we're trying to accomplish.<br />
<br />
== Future-proofing current code ==<br />
<br />
GHC 7.8 will issue two types of warnings in order to encourage wide-scale code fixing. The following describes how to get rid of them, and as a result ensures your code builds both now and after the AMP is finished.<br />
<br />
=== Missing superclasses ===<br />
<br />
(Warnings of the type "Warning: X is an instance of C, but not D")<br />
<br />
* Add Applicative/Functor instances for all your Monads. You can simply derive these instances from the Monad by adding the following code:<br />
<haskell><br />
import Control.Applicative (Applicative(..))<br />
import Control.Monad (liftM, ap)<br />
<br />
-- Monad m<br />
<br />
instance Functor m where<br />
fmap = liftM<br />
<br />
instance Applicative m where<br />
pure = {- move the definition of `return` from the `Monad` instance here -}<br />
(<*>) = ap<br />
<br />
instance Monad m where<br />
return = pure -- redundant since GHC 7.10 due to default impl<br />
</haskell><br />
<br />
Moreover, there are some subtle issues regarding the <code>(>>)</code> operator, see [https://ghc.haskell.org/trac/ghc/wiki/Migration/7.10#base-4.8.0.0] for more details.<br />
<br />
* Add an Alternative instance for all instances of MonadPlus. This can again be done easily using<br />
<haskell><br />
import Control.Applicative (Alternative(..))<br />
import Control.Monad (mzero, mplus)<br />
<br />
-- MonadPlus m<br />
<br />
instance Alternative m where<br />
(<|>) = mplus<br />
empty = mzero<br />
</haskell><br />
<br />
=== Future Prelude names ===<br />
<br />
"The name X clashes with a future Prelude name" - Prelude will export functions called <hask><*></hask>, <hask>join</hask> and <hask>pure</hask>, so if a module defines its own versions of them, there will be name clashes. There are multiple ways of getting rid of this type of warning (in a future-proof way).<br />
<br />
# Change your code to not define functions named <hask><*></hask>, <hask>join</hask> or <hask>pure</hask>.<br />
# Import Prelude definitions you need explicitly. For example, <hask>import Prelude (map, (+))</hask> would not import <hask>join</hask>, so no warning is issued as the module is compatible with the Prelude exporting <hask>join</hask>. <hask>hiding</hask>.<br />
# Due to GHC internals, you cannot use <hask>hiding (join, (<*>), pure)</hask> to silence the warnings, although this method would be future-proof. If you want to use <hask>hiding</hask>, you will have to silence the warnings using a sledgehammer <code>-fno-warn-amp</code> compiler flag. (If you do so make sure you know what you're doing, otherwise your module ''will'' break in 7.10.) To make 7.10 not complain about the then unrecognized flag, it's best to specify it in a CPP block,<br />
<haskell><br />
{-# LANGUAGE CPP #-}<br />
#if __GLASGOW_HASKELL__ >= 707 && __GLASGOW_HASKELL__ < 710<br />
{-# OPTIONS_GHC -fno-warn-amp #-}<br />
#endif<br />
</haskell><br />
<br />
== Discussion and consequences ==<br />
<br />
<br />
=== It's the right thing to do™ ===<br />
<br />
Math. You've all heard this one, it's good and compelling so I don't need to spell it out.<br />
<br />
<br />
=== Redundant functions ===<br />
<br />
* <hask>pure</hask> and <hask>return</hask> do the same thing.<br />
* <hask>>></hask> and <hask>*></hask> are identical.<br />
* <hask>liftM</hask> and <hask>liftA</hask> are <hask>fmap</hask>. The <hask>liftM*</hask> are <hask>liftA*</hask>, <hask><*></hask> is <hask>ap</hask>.<br />
* Prelude's <hask>sequence</hask> requires <hask>Monad</hask> right now, while <hask>Applicative</hask> is sufficient to implement it. The more general version of this issue is captured by <hask>Data.Traversable</hask>, whose main typeclass implements the *same* functionality twice, namely <hask>traverse</hask> and <hask>mapM</hask>, and <hask>sequenceA</hask> and <hask>sequence</hask>.<br />
* The <hask>WrappedMonad</hask> type from <hask>Control.Applicative</hask> provides a semi-automatic way to using Functor/Applicative/Alternative functions for Monad/MonadPlus instances as a makeshift patch.<br />
<br />
That very much violates the "don't repeat yourself" principle, and even more so it ''forces'' the programmer to repeat himself to achieve maximal generality. It may be too late to take all redundancies out, but at least we can prevent new ones from being created.<br />
<br />
(Note that it is not proposed to remove any functions for compatibility reasons. Maybe some of them can be phased out in the long run, but that's beyond scope here.)<br />
<br />
<br />
=== Using Functor/Applicative functions in monadic code ===<br />
<br />
Whenever there's Monad code, you can use Functor/Applicative functions, without introducing an additional constraint. Keep in mind that "Functor/Applicative functions" does not only include what their typeclasses define but many more, for example <hask>void</hask>, <hask>(<$>)</hask>, <hask>(<**>)</hask>.<br />
<br />
Even if you think you have monadic code, strictly using the least restrictive functions may result in something that requires only Applicative. This is similar to writing a function that needs <hask>Int</hask>, but it turns out any <hask>Integral</hask> will do - more polymorphism for free.<br />
<br />
<br />
=== Compatibility issues ===<br />
<br />
These are the kinds of issues to be expected:<br />
<br />
# Monads lacking Functor or Applicative instances. This is easily fixable by either setting <hask>fmap = liftM</hask>, <hask>pure = return</hask> and <hask>(<*>) = ap</hask>, although more efficient implementations may exist, or by moving an already existing definition from <hask>Control.Applicative</hask> to the appropriate module.<br />
# This one is specific to building GHC: importing <hask>Control.Monad/Applicative</hask> introduces a circular module dependency. In this case, one can rely on handwritten implementations of the desired function, e.g. <hask>ap f x = f >>= ...</hask>.<br />
# Libraries using their own <hask>(<*>)</hask>. This one is potentially the most laborious consequence. For building GHC though, this only concerns Hoopl, and a handful of renames.<br />
<br />
<br />
<br />
=== Beginner friendliness ===<br />
<br />
How often did you say ...<br />
<br />
* "A Monad is always an Applicative but due to historical reasons it's not but you can easily verify it by setting <hask>pure = return</hask> and <hask>(<*>) = ap</hask>"<br />
* "<hask>liftM</hask> is <hask>fmap</hask> but not really." - "So when should I use <hask>fmap</hask> and when <hask>liftM</hask>?" - ''sigh''<br />
<br />
With the new hierarchy, the answer would ''always'' be "use the least restrictive one".<br />
<br />
== Applying the AMP to GHC and then Haskell in practice ==<br />
<br />
Proposed is a gradual introduction of the AMP in three phases:<br />
<br />
<br />
=== Prepare GHC ===<br />
<br />
Using a GHC fork with the full patch applied, find and fix all compilation errors introduced by the change by adding Functor/Applicative instances for all Monads.<br />
<br />
According to SPJ, adding an ad-hoc warning of sorts "Monad without Applicative detected" is not a problem, which will be crucial for the next phase. More specifically, issue a warning if:<br />
<br />
* Monad without Applicative<br />
* MonadPlus without Alternative<br />
* One of <hask><*></hask>, <hask>pure</hask>, <hask>join</hask> is defined in a different context to avoid naming conflicts, as these functions will go into the Prelude<br />
<br />
=== Prepare Hackage ===<br />
<br />
The warning just mentioned will hint to all authors that they should fix (or help others fix) the non-complying packages. This will ideally lead to libraries eventually adding Applicative instances, and changing their APIs if they redefine operators like <hask><*></hask>.<br />
<br />
After enough time has passed by so libraries adapted to the circumstances, move on to the next phase.<br />
<br />
<br />
=== Apply the proposal ===<br />
<br />
Once Hackage is prepared, applying the changes to the Base package is painless. However, this is not primarily a GHC, but a Haskell change. The previous steps were basically preparing the landscape, and when we've (hopefully) found out that it is a good idea to go through with it, it can be proposed to go into the Report. If we make it this far, the AMP should pass quite easily.<br />
<br />
<br />
<br />
== Previous proposals ==<br />
<br />
* Early 2011: [http://hackage.haskell.org/trac/ghc/ticket/4834 GHC ticket] &ndash; changes similar to this proposal, but closed as "not GHC, but Haskell". See [http://thread.gmane.org/gmane.comp.lang.haskell.libraries/14883/focus=14905 here] for the associated discussion.<br />
* [[The Other Prelude]]<br />
<br />
<br />
[[Category:Proposals]]<br />
[[Category:Functor]]<br />
[[Category:Applicative Functor]]<br />
[[Category:Monad]]</div>Hvrhttps://wiki.haskell.org/index.php?title=Foldable_Traversable_In_Prelude&diff=59283Foldable Traversable In Prelude2015-02-04T09:52:28Z<p>Hvr: more semantic markup</p>
<hr />
<div>This page is a FAQ for the FTP (Foldable/Traversable in Prelude proposal) otherwise known as (part of) the BBP (Burning Bridges Proposal), slated for inclusion in the core libraries of GHC 7.10. While elements of this proposal may still be under discussion, this page is intended to summarize the proposal as it now stands as of 28 January, 2015. It is a work in progress, done as best as possible, but should not be taken as necessarily a full statement by the libraries committee on every aspect of this proposal.<br />
<br />
== Where did the FTP come from? ==<br />
<br />
The FTP was proposed in the context of a very lengthy [http://osdir.com/ml/libraries@haskell.org/2013-05/msg00280.html "Burning Bridges"] thread on the haskell libraries list in the summer of 2013.<br />
<br />
Over the course of this thread and subsequent and related discussions it was revealed there was a large appetite in the community to "modernize" the Prelude and bring it into line with the current widespread usage of classes such as Applicative, Foldable, and Traversable. Out of these discussions, a "Core Libraries Committee" was formed to manage and steward such large changes in a way to vet them thoroughly and ensure minimal breakage in carrying them out.<br />
<br />
== What does the FTP do? ==<br />
<br />
The FTP does what it says. It brings Foldable and Traversable into the Prelude. Along with this, it replaces Prelude functions that clash with Foldable and Traversable with their more polymorphic versions as drawn from those two classes and their associated methods. One goal here is that people should be able to use methods from these modules without the need of a qualified import -- i.e. to prevent clash in the namespace, by resolving such in favor of the more generalized versions. Additionally, there are some new methods added to the Foldable class because it seems to be the "right" thing. This proposal is semi-independent from the rest of FTP, but the changes tend to have been discussed under the same general umbrella.<br />
<br />
== Does the FTP change any behaviour? ==<br />
<br />
No (almost). By design, nearly any code that compiles under these changes should operate exactly as prior to these changes. If you believe you have found an area where these changes cause a semantic difference, it is a bug and should be reported.<br />
<br />
There are, however, changes to the behaviour of <code>Data.Foldable.sum</code>, <code>Data.Foldable.product</code>, <code>Data.Foldable.maximum</code>, and <code>Data.Foldable.minimum</code> on lists and only on lists, in order to bring them into accord with the prelude.<br />
<br />
== So does the FTP break any code? ==<br />
<br />
As little as possible. Many of the seemingly "odd" aspects of FTP come from engineering choices made specifically so as to minimize code breakage. In particular, a few packages may be broken by new exports from the prelude such as <code>mconcat</code> and <code>foldMap</code>. A few more may be broken by the export of new additions to the <code>Foldable</code> class. And finally, there are a few packages that may be broken by the new generalized signature in the prelude not being sufficient to pin down some otherwise already polymorphic code (particularly in the case of using the <code>{-# LANGUAGE OverloadedStrings #-}</code> extension).<br />
<br />
On the other hand, 569 packages in Stackage, including the core of it, build without problems. According to Edward Kmett, "of the 50-100 that remain, most are awaiting author feedback on already-filed issues / fixes or are broken by a small change downstream." [TODO: Please clarify if the failures of the remaining packages seem to be caused by FTP or not, in general.]<br />
<br />
== What are the concrete changes in the FTP? ==<br />
Here is a diff of the relevant changes. Note that there are other changes, not listed here, notably those introduced by the "AMP", which makes Applicative a superclass of Monad.<br />
<br />
<nowiki><br />
Control.Monad<br />
- foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a<br />
+ foldM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b<br />
- foldM_ :: Monad m => (a -> b -> m a) -> a -> [b] -> m ()<br />
+ foldM_ :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m ()<br />
- forM :: Monad m => [a] -> (a -> m b) -> m [b]<br />
+ forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)<br />
- forM_ :: Monad m => [a] -> (a -> m b) -> m ()<br />
+ forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()<br />
- mapM :: Monad m => (a -> m b) -> [a] -> m [b]<br />
+ mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)<br />
- mapM_ :: Monad m => (a -> m b) -> [a] -> m ()<br />
+ mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()<br />
- msum :: MonadPlus m => [m a] -> m a<br />
+ msum :: (Foldable t, MonadPlus m) => t (m a) -> m a<br />
- sequence :: Monad m => [m a] -> m [a]<br />
+ sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)<br />
- sequence_ :: Monad m => [m a] -> m ()<br />
+ sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()<br />
<br />
Data.List<br />
- all :: (a -> Bool) -> [a] -> Bool<br />
+ all :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- and :: [Bool] -> Bool<br />
+ and :: Foldable t => t Bool -> Bool<br />
- any :: (a -> Bool) -> [a] -> Bool<br />
+ any :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- concat :: [[a]] -> [a]<br />
+ concat :: Foldable t => t [a] -> [a]<br />
- concatMap :: (a -> [b]) -> [a] -> [b]<br />
+ concatMap :: Foldable t => (a -> [b]) -> t a -> [b]<br />
- elem :: Eq a => a -> [a] -> Bool<br />
+ elem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- find :: (a -> Bool) -> [a] -> Maybe a<br />
+ find :: Foldable t => (a -> Bool) -> t a -> Maybe a<br />
- foldl :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl' :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl' :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl1 :: (a -> a -> a) -> [a] -> a<br />
+ foldl1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- foldr :: (a -> b -> b) -> b -> [a] -> b<br />
+ foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b<br />
- foldr1 :: (a -> a -> a) -> [a] -> a<br />
+ foldr1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
+ isSubsequenceOf :: (Eq a) => [a] -> [a] -> Bool<br />
- length :: [a] -> Int<br />
+ length :: Foldable t => t a -> Int<br />
- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])<br />
+ mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
- mapAccumR :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])<br />
+ mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
- maximum :: Ord a => [a] -> a<br />
+ maximum :: (Foldable t, Ord a) => t a -> a<br />
- maximumBy :: (a -> a -> Ordering) -> [a] -> a<br />
+ maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a<br />
- minimum :: Ord a => [a] -> a<br />
+ minimum :: (Foldable t, Ord a) => t a -> a<br />
- minimumBy :: (a -> a -> Ordering) -> [a] -> a<br />
+ minimumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a<br />
- notElem :: Eq a => a -> [a] -> Bool<br />
+ notElem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- null :: [a] -> Bool<br />
+ null :: Foldable t => t a -> Bool<br />
- or :: [Bool] -> Bool<br />
+ or :: Foldable t => t Bool -> Bool<br />
- product :: Num a => [a] -> a<br />
+ product :: (Foldable t, Num a) => t a -> a<br />
+ scanl' :: (b -> a -> b) -> b -> [a] -> [b]<br />
+ sortOn :: Ord b => (a -> b) -> [a] -> [a]<br />
- sum :: Num a => [a] -> a<br />
+ sum :: (Foldable t, Num a) => t a -> a<br />
+ uncons :: [a] -> Maybe (a, [a])<br />
<br />
Prelude<br />
- all :: (a -> Bool) -> [a] -> Bool<br />
+ all :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- and :: [Bool] -> Bool<br />
+ and :: Foldable t => t Bool -> Bool<br />
- any :: (a -> Bool) -> [a] -> Bool<br />
+ any :: Foldable t => (a -> Bool) -> t a -> Bool<br />
+ class Monoid a<br />
+ class Foldable t<br />
+ class (Functor t, Foldable t) => Traversable t<br />
- concat :: [[a]] -> [a]<br />
+ concat :: Foldable t => t [a] -> [a]<br />
- concatMap :: (a -> [b]) -> [a] -> [b]<br />
+ concatMap :: Foldable t => (a -> [b]) -> t a -> [b]<br />
- elem :: Eq a => a -> [a] -> Bool<br />
+ elem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
+ foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m<br />
- foldl :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl1 :: (a -> a -> a) -> [a] -> a<br />
+ foldl1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- foldr :: (a -> b -> b) -> b -> [a] -> b<br />
+ foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b<br />
- foldr1 :: (a -> a -> a) -> [a] -> a<br />
+ foldr1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- length :: [a] -> Int<br />
+ length :: Foldable t => t a -> Int<br />
- mapM :: Monad m => (a -> m b) -> [a] -> m [b]<br />
+ mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)<br />
- mapM_ :: Monad m => (a -> m b) -> [a] -> m ()<br />
+ mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()<br />
+ mappend :: Monoid a => a -> a -> a<br />
- maximum :: Ord a => [a] -> a<br />
+ maximum :: (Foldable t, Ord a) => t a -> a<br />
+ mconcat :: Monoid a => [a] -> a<br />
+ mempty :: Monoid a => a<br />
- minimum :: Ord a => [a] -> a<br />
+ minimum :: (Foldable t, Ord a) => t a -> a<br />
- notElem :: Eq a => a -> [a] -> Bool<br />
+ notElem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- null :: [a] -> Bool<br />
+ null :: Foldable t => t a -> Bool<br />
- or :: [Bool] -> Bool<br />
+ or :: Foldable t => t Bool -> Bool<br />
- product :: Num a => [a] -> a<br />
+ product :: (Foldable t, Num a) => t a -> a<br />
- sequence :: Monad m => [m a] -> m [a]<br />
+ sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)<br />
+ sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)<br />
- sequence_ :: Monad m => [m a] -> m ()<br />
+ sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()<br />
- sum :: Num a => [a] -> a<br />
+ sum :: (Foldable t, Num a) => t a -> a<br />
+ traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)<br />
<br />
Data.Foldable<br />
+ length :: Foldable t => t a -> Int<br />
+ null :: Foldable t => t a -> Bool<br />
</nowiki><br />
<br />
Additionally, <code>toList</code>, <code>elem</code>, <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code>, before given as methods on <code>Foldable</code> items are now optional methods in the <code>Foldable</code> class.<br />
<br />
Finally, note that the addition of <code>length</code>, <code>null</code>, <code>toList</code>, and <code>elem</code> to <code>Foldable</code> are technically [https://ghc.haskell.org/trac/ghc/ticket/9621 a separate proposal] but are often discussed in conjunction with the FTP. Meanwhile the addition of <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code> are considered part of the FTP, as will be discussed below.<br />
<br />
== Wow, that's a lot of changes! ==<br />
<br />
Well, yes and no. As you can see, these changes are all essentially strict generalizations of existing functions, which was indeed the goal.<br />
<br />
== But, why does Control.Monad also generalize its functions? ==<br />
<br />
Many people import <code>Control.Monad</code> unqualified. If we continued to export the monomorphic functions from <code>Control.Monad</code>, this would lead to many clashes, and much code would break. Now, all that remaining code still works!<br />
<br />
We could instead drop those functions from <code>Control.Monad</code> instead of reexporting their more polymorphic versions. But this would cause breakages for those who imported them explicitly or qualified. Now that code still works too!<br />
<br />
== But, why does Data.List also generalize its functions? ==<br />
<br />
Many people import <code>Data.List</code> unqualified. If we continued to export the monomorphic functions from <code>Data.List</code>, this would lead to many clashes, and much code would break. Now, all that remaining code still works!<br />
<br />
We could instead drop those functions from <code>Data.List</code> instead of reexporting their more polymorphic versions. But this would cause breakages for those who imported them explicitly or qualified. Now that code still works too!<br />
<br />
== OK, but why does the Foldable class have so many methods in it? ==<br />
<br />
Well, <code>Foldable</code> cannot just be given by <code>toList</code>, much as we might think of it as such. <code>foldMap</code> lets us fold over not only potentially right-infinite structures as with <code>foldr</code>, but potentially left-infinite ones (as with <code>foldl</code>) and even "both-infinite" ones such as rooted but infinitely branching trees!<br />
<br />
Other methods in the <code>Foldable</code> class, such as <code>foldl</code> and <code>foldr</code> exist for historical reasons, and to allow the possibility of more efficient implementations. <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code> were added because their prelude versions were performed with a <code>foldl</code>, while their general versions with a <code>foldMap</code>. Moving them into the class allowed Prelude behaviour to be preserved in the case of lists without altering behaviour otherwise in the case of other structures. This has led to the one semantic change in the FTP -- now that these Foldable methods on lists are in accord with the Prelude specification, this means that (unavoidably) their Foldable methods on lists have now changed behaviour.<br />
<br />
Finally, <code>toList</code> and <code>elem</code> were pulled into the class and <code>length</code> and <code>null</code> were added to both the module and the class because they permit potentially more efficient implementations on many structures (with null and length being sometimes, for example ''O(1)''), and it seemed desirable to allow users to take advantage of this asymptotically more efficient behaviour.<br />
<br />
== Now I'm getting unused import warnings. Help? ==<br />
<br />
Suppose your code had <code>import Foldable</code> in it, but you only used things that are now available from the prelude. After the FTP you'll be getting unused import warnings.<br />
<br />
You can go delete the import, but now your code doesn't work for pre-FTP versions! There is a trick to avoid these warnings while remaining compatible across versions. <br />
<br />
Stick <code>import Prelude</code> at the '''bottom''' of your imports list.<br />
<br />
This works because GHC checks that the imports provide something "new" that is used by the module in a top-down fashion, and you are almost certainly using something from Prelude that didn't come from one of the modules above.<br />
<br />
[[Category:FAQ]]<br />
[[Category:How to]]</div>Hvrhttps://wiki.haskell.org/index.php?title=Foldable_Traversable_In_Prelude&diff=59282Foldable Traversable In Prelude2015-02-04T09:51:21Z<p>Hvr: more semantic markup</p>
<hr />
<div>This page is a FAQ for the FTP (Foldable/Traversable in Prelude proposal) otherwise known as (part of) the BBP (Burning Bridges Proposal), slated for inclusion in the core libraries of GHC 7.10. While elements of this proposal may still be under discussion, this page is intended to summarize the proposal as it now stands as of 28 January, 2015. It is a work in progress, done as best as possible, but should not be taken as necessarily a full statement by the libraries committee on every aspect of this proposal.<br />
<br />
== Where did the FTP come from? ==<br />
<br />
The FTP was proposed in the context of a very lengthy [http://osdir.com/ml/libraries@haskell.org/2013-05/msg00280.html "Burning Bridges"] thread on the haskell libraries list in the summer of 2013.<br />
<br />
Over the course of this thread and subsequent and related discussions it was revealed there was a large appetite in the community to "modernize" the Prelude and bring it into line with the current widespread usage of classes such as Applicative, Foldable, and Traversable. Out of these discussions, a "Core Libraries Committee" was formed to manage and steward such large changes in a way to vet them thoroughly and ensure minimal breakage in carrying them out.<br />
<br />
== What does the FTP do? ==<br />
<br />
The FTP does what it says. It brings Foldable and Traversable into the Prelude. Along with this, it replaces Prelude functions that clash with Foldable and Traversable with their more polymorphic versions as drawn from those two classes and their associated methods. One goal here is that people should be able to use methods from these modules without the need of a qualified import -- i.e. to prevent clash in the namespace, by resolving such in favor of the more generalized versions. Additionally, there are some new methods added to the Foldable class because it seems to be the "right" thing. This proposal is semi-independent from the rest of FTP, but the changes tend to have been discussed under the same general umbrella.<br />
<br />
== Does the FTP change any behaviour? ==<br />
<br />
No (almost). By design, nearly any code that compiles under these changes should operate exactly as prior to these changes. If you believe you have found an area where these changes cause a semantic difference, it is a bug and should be reported.<br />
<br />
There are, however, changes to the behaviour of Data.Foldable.sum, Data.Foldable.product, Data.Foldable.maximum, and Data.Foldable.minimum on lists and only on lists, in order to bring them into accord with the prelude.<br />
<br />
== So does the FTP break any code? ==<br />
<br />
As little as possible. Many of the seemingly "odd" aspects of FTP come from engineering choices made specifically so as to minimize code breakage. In particular, a few packages may be broken by new exports from the prelude such as <code>mconcat</code> and <code>foldMap</code>. A few more may be broken by the export of new additions to the <code>Foldable</code> class. And finally, there are a few packages that may be broken by the new generalized signature in the prelude not being sufficient to pin down some otherwise already polymorphic code (particularly in the case of using the <code>{-# LANGUAGE OverloadedStrings #-}</code> extension).<br />
<br />
On the other hand, 569 packages in Stackage, including the core of it, build without problems. According to Edward Kmett, "of the 50-100 that remain, most are awaiting author feedback on already-filed issues / fixes or are broken by a small change downstream." [TODO: Please clarify if the failures of the remaining packages seem to be caused by FTP or not, in general.]<br />
<br />
== What are the concrete changes in the FTP? ==<br />
Here is a diff of the relevant changes. Note that there are other changes, not listed here, notably those introduced by the "AMP", which makes Applicative a superclass of Monad.<br />
<br />
<nowiki><br />
Control.Monad<br />
- foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a<br />
+ foldM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b<br />
- foldM_ :: Monad m => (a -> b -> m a) -> a -> [b] -> m ()<br />
+ foldM_ :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m ()<br />
- forM :: Monad m => [a] -> (a -> m b) -> m [b]<br />
+ forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)<br />
- forM_ :: Monad m => [a] -> (a -> m b) -> m ()<br />
+ forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()<br />
- mapM :: Monad m => (a -> m b) -> [a] -> m [b]<br />
+ mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)<br />
- mapM_ :: Monad m => (a -> m b) -> [a] -> m ()<br />
+ mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()<br />
- msum :: MonadPlus m => [m a] -> m a<br />
+ msum :: (Foldable t, MonadPlus m) => t (m a) -> m a<br />
- sequence :: Monad m => [m a] -> m [a]<br />
+ sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)<br />
- sequence_ :: Monad m => [m a] -> m ()<br />
+ sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()<br />
<br />
Data.List<br />
- all :: (a -> Bool) -> [a] -> Bool<br />
+ all :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- and :: [Bool] -> Bool<br />
+ and :: Foldable t => t Bool -> Bool<br />
- any :: (a -> Bool) -> [a] -> Bool<br />
+ any :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- concat :: [[a]] -> [a]<br />
+ concat :: Foldable t => t [a] -> [a]<br />
- concatMap :: (a -> [b]) -> [a] -> [b]<br />
+ concatMap :: Foldable t => (a -> [b]) -> t a -> [b]<br />
- elem :: Eq a => a -> [a] -> Bool<br />
+ elem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- find :: (a -> Bool) -> [a] -> Maybe a<br />
+ find :: Foldable t => (a -> Bool) -> t a -> Maybe a<br />
- foldl :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl' :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl' :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl1 :: (a -> a -> a) -> [a] -> a<br />
+ foldl1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- foldr :: (a -> b -> b) -> b -> [a] -> b<br />
+ foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b<br />
- foldr1 :: (a -> a -> a) -> [a] -> a<br />
+ foldr1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
+ isSubsequenceOf :: (Eq a) => [a] -> [a] -> Bool<br />
- length :: [a] -> Int<br />
+ length :: Foldable t => t a -> Int<br />
- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])<br />
+ mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
- mapAccumR :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])<br />
+ mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
- maximum :: Ord a => [a] -> a<br />
+ maximum :: (Foldable t, Ord a) => t a -> a<br />
- maximumBy :: (a -> a -> Ordering) -> [a] -> a<br />
+ maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a<br />
- minimum :: Ord a => [a] -> a<br />
+ minimum :: (Foldable t, Ord a) => t a -> a<br />
- minimumBy :: (a -> a -> Ordering) -> [a] -> a<br />
+ minimumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a<br />
- notElem :: Eq a => a -> [a] -> Bool<br />
+ notElem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- null :: [a] -> Bool<br />
+ null :: Foldable t => t a -> Bool<br />
- or :: [Bool] -> Bool<br />
+ or :: Foldable t => t Bool -> Bool<br />
- product :: Num a => [a] -> a<br />
+ product :: (Foldable t, Num a) => t a -> a<br />
+ scanl' :: (b -> a -> b) -> b -> [a] -> [b]<br />
+ sortOn :: Ord b => (a -> b) -> [a] -> [a]<br />
- sum :: Num a => [a] -> a<br />
+ sum :: (Foldable t, Num a) => t a -> a<br />
+ uncons :: [a] -> Maybe (a, [a])<br />
<br />
Prelude<br />
- all :: (a -> Bool) -> [a] -> Bool<br />
+ all :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- and :: [Bool] -> Bool<br />
+ and :: Foldable t => t Bool -> Bool<br />
- any :: (a -> Bool) -> [a] -> Bool<br />
+ any :: Foldable t => (a -> Bool) -> t a -> Bool<br />
+ class Monoid a<br />
+ class Foldable t<br />
+ class (Functor t, Foldable t) => Traversable t<br />
- concat :: [[a]] -> [a]<br />
+ concat :: Foldable t => t [a] -> [a]<br />
- concatMap :: (a -> [b]) -> [a] -> [b]<br />
+ concatMap :: Foldable t => (a -> [b]) -> t a -> [b]<br />
- elem :: Eq a => a -> [a] -> Bool<br />
+ elem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
+ foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m<br />
- foldl :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl1 :: (a -> a -> a) -> [a] -> a<br />
+ foldl1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- foldr :: (a -> b -> b) -> b -> [a] -> b<br />
+ foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b<br />
- foldr1 :: (a -> a -> a) -> [a] -> a<br />
+ foldr1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- length :: [a] -> Int<br />
+ length :: Foldable t => t a -> Int<br />
- mapM :: Monad m => (a -> m b) -> [a] -> m [b]<br />
+ mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)<br />
- mapM_ :: Monad m => (a -> m b) -> [a] -> m ()<br />
+ mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()<br />
+ mappend :: Monoid a => a -> a -> a<br />
- maximum :: Ord a => [a] -> a<br />
+ maximum :: (Foldable t, Ord a) => t a -> a<br />
+ mconcat :: Monoid a => [a] -> a<br />
+ mempty :: Monoid a => a<br />
- minimum :: Ord a => [a] -> a<br />
+ minimum :: (Foldable t, Ord a) => t a -> a<br />
- notElem :: Eq a => a -> [a] -> Bool<br />
+ notElem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- null :: [a] -> Bool<br />
+ null :: Foldable t => t a -> Bool<br />
- or :: [Bool] -> Bool<br />
+ or :: Foldable t => t Bool -> Bool<br />
- product :: Num a => [a] -> a<br />
+ product :: (Foldable t, Num a) => t a -> a<br />
- sequence :: Monad m => [m a] -> m [a]<br />
+ sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)<br />
+ sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)<br />
- sequence_ :: Monad m => [m a] -> m ()<br />
+ sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()<br />
- sum :: Num a => [a] -> a<br />
+ sum :: (Foldable t, Num a) => t a -> a<br />
+ traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)<br />
<br />
Data.Foldable<br />
+ length :: Foldable t => t a -> Int<br />
+ null :: Foldable t => t a -> Bool<br />
</nowiki><br />
<br />
Additionally, <code>toList</code>, <code>elem</code>, <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code>, before given as methods on <code>Foldable</code> items are now optional methods in the <code>Foldable</code> class.<br />
<br />
Finally, note that the addition of <code>length</code>, <code>null</code>, <code>toList</code>, and <code>elem</code> to <code>Foldable</code> are technically [https://ghc.haskell.org/trac/ghc/ticket/9621 a separate proposal] but are often discussed in conjunction with the FTP. Meanwhile the addition of <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code> are considered part of the FTP, as will be discussed below.<br />
<br />
== Wow, that's a lot of changes! ==<br />
<br />
Well, yes and no. As you can see, these changes are all essentially strict generalizations of existing functions, which was indeed the goal.<br />
<br />
== But, why does Control.Monad also generalize its functions? ==<br />
<br />
Many people import <code>Control.Monad</code> unqualified. If we continued to export the monomorphic functions from <code>Control.Monad</code>, this would lead to many clashes, and much code would break. Now, all that remaining code still works!<br />
<br />
We could instead drop those functions from <code>Control.Monad</code> instead of reexporting their more polymorphic versions. But this would cause breakages for those who imported them explicitly or qualified. Now that code still works too!<br />
<br />
== But, why does Data.List also generalize its functions? ==<br />
<br />
Many people import <code>Data.List</code> unqualified. If we continued to export the monomorphic functions from <code>Data.List</code>, this would lead to many clashes, and much code would break. Now, all that remaining code still works!<br />
<br />
We could instead drop those functions from <code>Data.List</code> instead of reexporting their more polymorphic versions. But this would cause breakages for those who imported them explicitly or qualified. Now that code still works too!<br />
<br />
== OK, but why does the Foldable class have so many methods in it? ==<br />
<br />
Well, <code>Foldable</code> cannot just be given by <code>toList</code>, much as we might think of it as such. <code>foldMap</code> lets us fold over not only potentially right-infinite structures as with <code>foldr</code>, but potentially left-infinite ones (as with <code>foldl</code>) and even "both-infinite" ones such as rooted but infinitely branching trees!<br />
<br />
Other methods in the <code>Foldable</code> class, such as <code>foldl</code> and <code>foldr</code> exist for historical reasons, and to allow the possibility of more efficient implementations. <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code> were added because their prelude versions were performed with a <code>foldl</code>, while their general versions with a <code>foldMap</code>. Moving them into the class allowed Prelude behaviour to be preserved in the case of lists without altering behaviour otherwise in the case of other structures. This has led to the one semantic change in the FTP -- now that these Foldable methods on lists are in accord with the Prelude specification, this means that (unavoidably) their Foldable methods on lists have now changed behaviour.<br />
<br />
Finally, <code>toList</code> and <code>elem</code> were pulled into the class and <code>length</code> and <code>null</code> were added to both the module and the class because they permit potentially more efficient implementations on many structures (with null and length being sometimes, for example ''O(1)''), and it seemed desirable to allow users to take advantage of this asymptotically more efficient behaviour.<br />
<br />
== Now I'm getting unused import warnings. Help? ==<br />
<br />
Suppose your code had <code>import Foldable</code> in it, but you only used things that are now available from the prelude. After the FTP you'll be getting unused import warnings.<br />
<br />
You can go delete the import, but now your code doesn't work for pre-FTP versions! There is a trick to avoid these warnings while remaining compatible across versions. <br />
<br />
Stick <code>import Prelude</code> at the '''bottom''' of your imports list.<br />
<br />
This works because GHC checks that the imports provide something "new" that is used by the module in a top-down fashion, and you are almost certainly using something from Prelude that didn't come from one of the modules above.<br />
<br />
[[Category:FAQ]]<br />
[[Category:How to]]</div>Hvrhttps://wiki.haskell.org/index.php?title=Foldable_Traversable_In_Prelude&diff=59281Foldable Traversable In Prelude2015-02-04T09:50:01Z<p>Hvr: minor markup tweak</p>
<hr />
<div>This page is a FAQ for the FTP (Foldable/Traversable in Prelude proposal) otherwise known as (part of) the BBP (Burning Bridges Proposal), slated for inclusion in the core libraries of GHC 7.10. While elements of this proposal may still be under discussion, this page is intended to summarize the proposal as it now stands as of 28 January, 2015. It is a work in progress, done as best as possible, but should not be taken as necessarily a full statement by the libraries committee on every aspect of this proposal.<br />
<br />
== Where did the FTP come from? ==<br />
<br />
The FTP was proposed in the context of a very lengthy [http://osdir.com/ml/libraries@haskell.org/2013-05/msg00280.html "Burning Bridges"] thread on the haskell libraries list in the summer of 2013.<br />
<br />
Over the course of this thread and subsequent and related discussions it was revealed there was a large appetite in the community to "modernize" the Prelude and bring it into line with the current widespread usage of classes such as Applicative, Foldable, and Traversable. Out of these discussions, a "Core Libraries Committee" was formed to manage and steward such large changes in a way to vet them thoroughly and ensure minimal breakage in carrying them out.<br />
<br />
== What does the FTP do? ==<br />
<br />
The FTP does what it says. It brings Foldable and Traversable into the Prelude. Along with this, it replaces Prelude functions that clash with Foldable and Traversable with their more polymorphic versions as drawn from those two classes and their associated methods. One goal here is that people should be able to use methods from these modules without the need of a qualified import -- i.e. to prevent clash in the namespace, by resolving such in favor of the more generalized versions. Additionally, there are some new methods added to the Foldable class because it seems to be the "right" thing. This proposal is semi-independent from the rest of FTP, but the changes tend to have been discussed under the same general umbrella.<br />
<br />
== Does the FTP change any behaviour? ==<br />
<br />
No (almost). By design, nearly any code that compiles under these changes should operate exactly as prior to these changes. If you believe you have found an area where these changes cause a semantic difference, it is a bug and should be reported.<br />
<br />
There are, however, changes to the behaviour of Data.Foldable.sum, Data.Foldable.product, Data.Foldable.maximum, and Data.Foldable.minimum on lists and only on lists, in order to bring them into accord with the prelude.<br />
<br />
== So does the FTP break any code? ==<br />
<br />
As little as possible. Many of the seemingly "odd" aspects of FTP come from engineering choices made specifically so as to minimize code breakage. In particular, a few packages may be broken by new exports from the prelude such as mconcat and foldMap. A few more may be broken by the export of new additions to the Foldable class. And finally, there are a few packages that may be broken by the new generalized signature in the prelude not being sufficient to pin down some otherwise already polymorphic code (particularly in the case of using the <code>{-# LANGUAGE OverloadedStrings #-}</code> extension).<br />
<br />
On the other hand, 569 packages in Stackage, including the core of it, build without problems. According to Edward Kmett, "of the 50-100 that remain, most are awaiting author feedback on already-filed issues / fixes or are broken by a small change downstream." [TODO: Please clarify if the failures of the remaining packages seem to be caused by FTP or not, in general.]<br />
<br />
== What are the concrete changes in the FTP? ==<br />
Here is a diff of the relevant changes. Note that there are other changes, not listed here, notably those introduced by the "AMP", which makes Applicative a superclass of Monad.<br />
<br />
<nowiki><br />
Control.Monad<br />
- foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a<br />
+ foldM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b<br />
- foldM_ :: Monad m => (a -> b -> m a) -> a -> [b] -> m ()<br />
+ foldM_ :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m ()<br />
- forM :: Monad m => [a] -> (a -> m b) -> m [b]<br />
+ forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)<br />
- forM_ :: Monad m => [a] -> (a -> m b) -> m ()<br />
+ forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()<br />
- mapM :: Monad m => (a -> m b) -> [a] -> m [b]<br />
+ mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)<br />
- mapM_ :: Monad m => (a -> m b) -> [a] -> m ()<br />
+ mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()<br />
- msum :: MonadPlus m => [m a] -> m a<br />
+ msum :: (Foldable t, MonadPlus m) => t (m a) -> m a<br />
- sequence :: Monad m => [m a] -> m [a]<br />
+ sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)<br />
- sequence_ :: Monad m => [m a] -> m ()<br />
+ sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()<br />
<br />
Data.List<br />
- all :: (a -> Bool) -> [a] -> Bool<br />
+ all :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- and :: [Bool] -> Bool<br />
+ and :: Foldable t => t Bool -> Bool<br />
- any :: (a -> Bool) -> [a] -> Bool<br />
+ any :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- concat :: [[a]] -> [a]<br />
+ concat :: Foldable t => t [a] -> [a]<br />
- concatMap :: (a -> [b]) -> [a] -> [b]<br />
+ concatMap :: Foldable t => (a -> [b]) -> t a -> [b]<br />
- elem :: Eq a => a -> [a] -> Bool<br />
+ elem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- find :: (a -> Bool) -> [a] -> Maybe a<br />
+ find :: Foldable t => (a -> Bool) -> t a -> Maybe a<br />
- foldl :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl' :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl' :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl1 :: (a -> a -> a) -> [a] -> a<br />
+ foldl1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- foldr :: (a -> b -> b) -> b -> [a] -> b<br />
+ foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b<br />
- foldr1 :: (a -> a -> a) -> [a] -> a<br />
+ foldr1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
+ isSubsequenceOf :: (Eq a) => [a] -> [a] -> Bool<br />
- length :: [a] -> Int<br />
+ length :: Foldable t => t a -> Int<br />
- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])<br />
+ mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
- mapAccumR :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])<br />
+ mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
- maximum :: Ord a => [a] -> a<br />
+ maximum :: (Foldable t, Ord a) => t a -> a<br />
- maximumBy :: (a -> a -> Ordering) -> [a] -> a<br />
+ maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a<br />
- minimum :: Ord a => [a] -> a<br />
+ minimum :: (Foldable t, Ord a) => t a -> a<br />
- minimumBy :: (a -> a -> Ordering) -> [a] -> a<br />
+ minimumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a<br />
- notElem :: Eq a => a -> [a] -> Bool<br />
+ notElem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- null :: [a] -> Bool<br />
+ null :: Foldable t => t a -> Bool<br />
- or :: [Bool] -> Bool<br />
+ or :: Foldable t => t Bool -> Bool<br />
- product :: Num a => [a] -> a<br />
+ product :: (Foldable t, Num a) => t a -> a<br />
+ scanl' :: (b -> a -> b) -> b -> [a] -> [b]<br />
+ sortOn :: Ord b => (a -> b) -> [a] -> [a]<br />
- sum :: Num a => [a] -> a<br />
+ sum :: (Foldable t, Num a) => t a -> a<br />
+ uncons :: [a] -> Maybe (a, [a])<br />
<br />
Prelude<br />
- all :: (a -> Bool) -> [a] -> Bool<br />
+ all :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- and :: [Bool] -> Bool<br />
+ and :: Foldable t => t Bool -> Bool<br />
- any :: (a -> Bool) -> [a] -> Bool<br />
+ any :: Foldable t => (a -> Bool) -> t a -> Bool<br />
+ class Monoid a<br />
+ class Foldable t<br />
+ class (Functor t, Foldable t) => Traversable t<br />
- concat :: [[a]] -> [a]<br />
+ concat :: Foldable t => t [a] -> [a]<br />
- concatMap :: (a -> [b]) -> [a] -> [b]<br />
+ concatMap :: Foldable t => (a -> [b]) -> t a -> [b]<br />
- elem :: Eq a => a -> [a] -> Bool<br />
+ elem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
+ foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m<br />
- foldl :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl1 :: (a -> a -> a) -> [a] -> a<br />
+ foldl1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- foldr :: (a -> b -> b) -> b -> [a] -> b<br />
+ foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b<br />
- foldr1 :: (a -> a -> a) -> [a] -> a<br />
+ foldr1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- length :: [a] -> Int<br />
+ length :: Foldable t => t a -> Int<br />
- mapM :: Monad m => (a -> m b) -> [a] -> m [b]<br />
+ mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)<br />
- mapM_ :: Monad m => (a -> m b) -> [a] -> m ()<br />
+ mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()<br />
+ mappend :: Monoid a => a -> a -> a<br />
- maximum :: Ord a => [a] -> a<br />
+ maximum :: (Foldable t, Ord a) => t a -> a<br />
+ mconcat :: Monoid a => [a] -> a<br />
+ mempty :: Monoid a => a<br />
- minimum :: Ord a => [a] -> a<br />
+ minimum :: (Foldable t, Ord a) => t a -> a<br />
- notElem :: Eq a => a -> [a] -> Bool<br />
+ notElem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- null :: [a] -> Bool<br />
+ null :: Foldable t => t a -> Bool<br />
- or :: [Bool] -> Bool<br />
+ or :: Foldable t => t Bool -> Bool<br />
- product :: Num a => [a] -> a<br />
+ product :: (Foldable t, Num a) => t a -> a<br />
- sequence :: Monad m => [m a] -> m [a]<br />
+ sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)<br />
+ sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)<br />
- sequence_ :: Monad m => [m a] -> m ()<br />
+ sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()<br />
- sum :: Num a => [a] -> a<br />
+ sum :: (Foldable t, Num a) => t a -> a<br />
+ traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)<br />
<br />
Data.Foldable<br />
+ length :: Foldable t => t a -> Int<br />
+ null :: Foldable t => t a -> Bool<br />
</nowiki><br />
<br />
Additionally, <code>toList</code>, <code>elem</code>, <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code>, before given as methods on <code>Foldable</code> items are now optional methods in the <code>Foldable</code> class.<br />
<br />
Finally, note that the addition of <code>length</code>, <code>null</code>, <code>toList</code>, and <code>elem</code> to <code>Foldable</code> are technically [https://ghc.haskell.org/trac/ghc/ticket/9621 a separate proposal] but are often discussed in conjunction with the FTP. Meanwhile the addition of <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code> are considered part of the FTP, as will be discussed below.<br />
<br />
== Wow, that's a lot of changes! ==<br />
<br />
Well, yes and no. As you can see, these changes are all essentially strict generalizations of existing functions, which was indeed the goal.<br />
<br />
== But, why does Control.Monad also generalize its functions? ==<br />
<br />
Many people import <code>Control.Monad</code> unqualified. If we continued to export the monomorphic functions from <code>Control.Monad</code>, this would lead to many clashes, and much code would break. Now, all that remaining code still works!<br />
<br />
We could instead drop those functions from <code>Control.Monad</code> instead of reexporting their more polymorphic versions. But this would cause breakages for those who imported them explicitly or qualified. Now that code still works too!<br />
<br />
== But, why does Data.List also generalize its functions? ==<br />
<br />
Many people import <code>Data.List</code> unqualified. If we continued to export the monomorphic functions from <code>Data.List</code>, this would lead to many clashes, and much code would break. Now, all that remaining code still works!<br />
<br />
We could instead drop those functions from <code>Data.List</code> instead of reexporting their more polymorphic versions. But this would cause breakages for those who imported them explicitly or qualified. Now that code still works too!<br />
<br />
== OK, but why does the Foldable class have so many methods in it? ==<br />
<br />
Well, <code>Foldable</code> cannot just be given by <code>toList</code>, much as we might think of it as such. <code>foldMap</code> lets us fold over not only potentially right-infinite structures as with <code>foldr</code>, but potentially left-infinite ones (as with <code>foldl</code>) and even "both-infinite" ones such as rooted but infinitely branching trees!<br />
<br />
Other methods in the <code>Foldable</code> class, such as <code>foldl</code> and <code>foldr</code> exist for historical reasons, and to allow the possibility of more efficient implementations. <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code> were added because their prelude versions were performed with a <code>foldl</code>, while their general versions with a <code>foldMap</code>. Moving them into the class allowed Prelude behaviour to be preserved in the case of lists without altering behaviour otherwise in the case of other structures. This has led to the one semantic change in the FTP -- now that these Foldable methods on lists are in accord with the Prelude specification, this means that (unavoidably) their Foldable methods on lists have now changed behaviour.<br />
<br />
Finally, <code>toList</code> and <code>elem</code> were pulled into the class and <code>length</code> and <code>null</code> were added to both the module and the class because they permit potentially more efficient implementations on many structures (with null and length being sometimes, for example ''O(1)''), and it seemed desirable to allow users to take advantage of this asymptotically more efficient behaviour.<br />
<br />
== Now I'm getting unused import warnings. Help? ==<br />
<br />
Suppose your code had <code>import Foldable</code> in it, but you only used things that are now available from the prelude. After the FTP you'll be getting unused import warnings.<br />
<br />
You can go delete the import, but now your code doesn't work for pre-FTP versions! There is a trick to avoid these warnings while remaining compatible across versions. <br />
<br />
Stick <code>import Prelude</code> at the '''bottom''' of your imports list.<br />
<br />
This works because GHC checks that the imports provide something "new" that is used by the module in a top-down fashion, and you are almost certainly using something from Prelude that didn't come from one of the modules above.<br />
<br />
[[Category:FAQ]]<br />
[[Category:How to]]</div>Hvrhttps://wiki.haskell.org/index.php?title=Foldable_Traversable_In_Prelude&diff=59280Foldable Traversable In Prelude2015-02-04T09:47:29Z<p>Hvr: this wiki doesn't support the <ref> tag it seems...</p>
<hr />
<div>This page is a FAQ for the FTP (Foldable/Traversable in Prelude proposal) otherwise known as (part of) the BBP (Burning Bridges Proposal), slated for inclusion in the core libraries of GHC 7.10. While elements of this proposal may still be under discussion, this page is intended to summarize the proposal as it now stands as of 28 January, 2015. It is a work in progress, done as best as possible, but should not be taken as necessarily a full statement by the libraries committee on every aspect of this proposal.<br />
<br />
== Where did the FTP come from? ==<br />
<br />
The FTP was proposed in the context of a very lengthy [http://osdir.com/ml/libraries@haskell.org/2013-05/msg00280.html "Burning Bridges"] thread on the haskell libraries list in the summer of 2013.<br />
<br />
Over the course of this thread and subsequent and related discussions it was revealed there was a large appetite in the community to "modernize" the Prelude and bring it into line with the current widespread usage of classes such as Applicative, Foldable, and Traversable. Out of these discussions, a "Core Libraries Committee" was formed to manage and steward such large changes in a way to vet them thoroughly and ensure minimal breakage in carrying them out.<br />
<br />
== What does the FTP do? ==<br />
<br />
The FTP does what it says. It brings Foldable and Traversable into the Prelude. Along with this, it replaces Prelude functions that clash with Foldable and Traversable with their more polymorphic versions as drawn from those two classes and their associated methods. One goal here is that people should be able to use methods from these modules without the need of a qualified import -- i.e. to prevent clash in the namespace, by resolving such in favor of the more generalized versions. Additionally, there are some new methods added to the Foldable class because it seems to be the "right" thing. This proposal is semi-independent from the rest of FTP, but the changes tend to have been discussed under the same general umbrella.<br />
<br />
== Does the FTP change any behaviour? ==<br />
<br />
No (almost). By design, nearly any code that compiles under these changes should operate exactly as prior to these changes. If you believe you have found an area where these changes cause a semantic difference, it is a bug and should be reported.<br />
<br />
There are, however, changes to the behaviour of Data.Foldable.sum, Data.Foldable.product, Data.Foldable.maximum, and Data.Foldable.minimum on lists and only on lists, in order to bring them into accord with the prelude.<br />
<br />
== So does the FTP break any code? ==<br />
<br />
As little as possible. Many of the seemingly "odd" aspects of FTP come from engineering choices made specifically so as to minimize code breakage. In particular, a few packages may be broken by new exports from the prelude such as mconcat and foldMap. A few more may be broken by the export of new additions to the Foldable class. And finally, there are a few packages that may be broken by the new generalized signature in the prelude not being sufficient to pin down some otherwise already polymorphic code (particularly in the case of using -XOverloadedStrings).<br />
<br />
On the other hand, 569 packages in Stackage, including the core of it, build without problems. According to Edward Kmett, "of the 50-100 that remain, most are awaiting author feedback on already-filed issues / fixes or are broken by a small change downstream." [TODO: Please clarify if the failures of the remaining packages seem to be caused by FTP or not, in general.]<br />
<br />
== What are the concrete changes in the FTP? ==<br />
Here is a diff of the relevant changes. Note that there are other changes, not listed here, notably those introduced by the "AMP", which makes Applicative a superclass of Monad.<br />
<br />
<nowiki><br />
Control.Monad<br />
- foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a<br />
+ foldM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b<br />
- foldM_ :: Monad m => (a -> b -> m a) -> a -> [b] -> m ()<br />
+ foldM_ :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m ()<br />
- forM :: Monad m => [a] -> (a -> m b) -> m [b]<br />
+ forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)<br />
- forM_ :: Monad m => [a] -> (a -> m b) -> m ()<br />
+ forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()<br />
- mapM :: Monad m => (a -> m b) -> [a] -> m [b]<br />
+ mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)<br />
- mapM_ :: Monad m => (a -> m b) -> [a] -> m ()<br />
+ mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()<br />
- msum :: MonadPlus m => [m a] -> m a<br />
+ msum :: (Foldable t, MonadPlus m) => t (m a) -> m a<br />
- sequence :: Monad m => [m a] -> m [a]<br />
+ sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)<br />
- sequence_ :: Monad m => [m a] -> m ()<br />
+ sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()<br />
<br />
Data.List<br />
- all :: (a -> Bool) -> [a] -> Bool<br />
+ all :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- and :: [Bool] -> Bool<br />
+ and :: Foldable t => t Bool -> Bool<br />
- any :: (a -> Bool) -> [a] -> Bool<br />
+ any :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- concat :: [[a]] -> [a]<br />
+ concat :: Foldable t => t [a] -> [a]<br />
- concatMap :: (a -> [b]) -> [a] -> [b]<br />
+ concatMap :: Foldable t => (a -> [b]) -> t a -> [b]<br />
- elem :: Eq a => a -> [a] -> Bool<br />
+ elem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- find :: (a -> Bool) -> [a] -> Maybe a<br />
+ find :: Foldable t => (a -> Bool) -> t a -> Maybe a<br />
- foldl :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl' :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl' :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl1 :: (a -> a -> a) -> [a] -> a<br />
+ foldl1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- foldr :: (a -> b -> b) -> b -> [a] -> b<br />
+ foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b<br />
- foldr1 :: (a -> a -> a) -> [a] -> a<br />
+ foldr1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
+ isSubsequenceOf :: (Eq a) => [a] -> [a] -> Bool<br />
- length :: [a] -> Int<br />
+ length :: Foldable t => t a -> Int<br />
- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])<br />
+ mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
- mapAccumR :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])<br />
+ mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
- maximum :: Ord a => [a] -> a<br />
+ maximum :: (Foldable t, Ord a) => t a -> a<br />
- maximumBy :: (a -> a -> Ordering) -> [a] -> a<br />
+ maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a<br />
- minimum :: Ord a => [a] -> a<br />
+ minimum :: (Foldable t, Ord a) => t a -> a<br />
- minimumBy :: (a -> a -> Ordering) -> [a] -> a<br />
+ minimumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a<br />
- notElem :: Eq a => a -> [a] -> Bool<br />
+ notElem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- null :: [a] -> Bool<br />
+ null :: Foldable t => t a -> Bool<br />
- or :: [Bool] -> Bool<br />
+ or :: Foldable t => t Bool -> Bool<br />
- product :: Num a => [a] -> a<br />
+ product :: (Foldable t, Num a) => t a -> a<br />
+ scanl' :: (b -> a -> b) -> b -> [a] -> [b]<br />
+ sortOn :: Ord b => (a -> b) -> [a] -> [a]<br />
- sum :: Num a => [a] -> a<br />
+ sum :: (Foldable t, Num a) => t a -> a<br />
+ uncons :: [a] -> Maybe (a, [a])<br />
<br />
Prelude<br />
- all :: (a -> Bool) -> [a] -> Bool<br />
+ all :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- and :: [Bool] -> Bool<br />
+ and :: Foldable t => t Bool -> Bool<br />
- any :: (a -> Bool) -> [a] -> Bool<br />
+ any :: Foldable t => (a -> Bool) -> t a -> Bool<br />
+ class Monoid a<br />
+ class Foldable t<br />
+ class (Functor t, Foldable t) => Traversable t<br />
- concat :: [[a]] -> [a]<br />
+ concat :: Foldable t => t [a] -> [a]<br />
- concatMap :: (a -> [b]) -> [a] -> [b]<br />
+ concatMap :: Foldable t => (a -> [b]) -> t a -> [b]<br />
- elem :: Eq a => a -> [a] -> Bool<br />
+ elem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
+ foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m<br />
- foldl :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl1 :: (a -> a -> a) -> [a] -> a<br />
+ foldl1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- foldr :: (a -> b -> b) -> b -> [a] -> b<br />
+ foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b<br />
- foldr1 :: (a -> a -> a) -> [a] -> a<br />
+ foldr1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- length :: [a] -> Int<br />
+ length :: Foldable t => t a -> Int<br />
- mapM :: Monad m => (a -> m b) -> [a] -> m [b]<br />
+ mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)<br />
- mapM_ :: Monad m => (a -> m b) -> [a] -> m ()<br />
+ mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()<br />
+ mappend :: Monoid a => a -> a -> a<br />
- maximum :: Ord a => [a] -> a<br />
+ maximum :: (Foldable t, Ord a) => t a -> a<br />
+ mconcat :: Monoid a => [a] -> a<br />
+ mempty :: Monoid a => a<br />
- minimum :: Ord a => [a] -> a<br />
+ minimum :: (Foldable t, Ord a) => t a -> a<br />
- notElem :: Eq a => a -> [a] -> Bool<br />
+ notElem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- null :: [a] -> Bool<br />
+ null :: Foldable t => t a -> Bool<br />
- or :: [Bool] -> Bool<br />
+ or :: Foldable t => t Bool -> Bool<br />
- product :: Num a => [a] -> a<br />
+ product :: (Foldable t, Num a) => t a -> a<br />
- sequence :: Monad m => [m a] -> m [a]<br />
+ sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)<br />
+ sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)<br />
- sequence_ :: Monad m => [m a] -> m ()<br />
+ sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()<br />
- sum :: Num a => [a] -> a<br />
+ sum :: (Foldable t, Num a) => t a -> a<br />
+ traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)<br />
<br />
Data.Foldable<br />
+ length :: Foldable t => t a -> Int<br />
+ null :: Foldable t => t a -> Bool<br />
</nowiki><br />
<br />
Additionally, <code>toList</code>, <code>elem</code>, <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code>, before given as methods on <code>Foldable</code> items are now optional methods in the <code>Foldable</code> class.<br />
<br />
Finally, note that the addition of <code>length</code>, <code>null</code>, <code>toList</code>, and <code>elem</code> to <code>Foldable</code> are technically [https://ghc.haskell.org/trac/ghc/ticket/9621 a separate proposal] but are often discussed in conjunction with the FTP. Meanwhile the addition of <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code> are considered part of the FTP, as will be discussed below.<br />
<br />
== Wow, that's a lot of changes! ==<br />
<br />
Well, yes and no. As you can see, these changes are all essentially strict generalizations of existing functions, which was indeed the goal.<br />
<br />
== But, why does Control.Monad also generalize its functions? ==<br />
<br />
Many people import <code>Control.Monad</code> unqualified. If we continued to export the monomorphic functions from <code>Control.Monad</code>, this would lead to many clashes, and much code would break. Now, all that remaining code still works!<br />
<br />
We could instead drop those functions from <code>Control.Monad</code> instead of reexporting their more polymorphic versions. But this would cause breakages for those who imported them explicitly or qualified. Now that code still works too!<br />
<br />
== But, why does Data.List also generalize its functions? ==<br />
<br />
Many people import <code>Data.List</code> unqualified. If we continued to export the monomorphic functions from <code>Data.List</code>, this would lead to many clashes, and much code would break. Now, all that remaining code still works!<br />
<br />
We could instead drop those functions from <code>Data.List</code> instead of reexporting their more polymorphic versions. But this would cause breakages for those who imported them explicitly or qualified. Now that code still works too!<br />
<br />
== OK, but why does the Foldable class have so many methods in it? ==<br />
<br />
Well, <code>Foldable</code> cannot just be given by <code>toList</code>, much as we might think of it as such. <code>foldMap</code> lets us fold over not only potentially right-infinite structures as with <code>foldr</code>, but potentially left-infinite ones (as with <code>foldl</code>) and even "both-infinite" ones such as rooted but infinitely branching trees!<br />
<br />
Other methods in the <code>Foldable</code> class, such as <code>foldl</code> and <code>foldr</code> exist for historical reasons, and to allow the possibility of more efficient implementations. <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code> were added because their prelude versions were performed with a <code>foldl</code>, while their general versions with a <code>foldMap</code>. Moving them into the class allowed Prelude behaviour to be preserved in the case of lists without altering behaviour otherwise in the case of other structures. This has led to the one semantic change in the FTP -- now that these Foldable methods on lists are in accord with the Prelude specification, this means that (unavoidably) their Foldable methods on lists have now changed behaviour.<br />
<br />
Finally, <code>toList</code> and <code>elem</code> were pulled into the class and <code>length</code> and <code>null</code> were added to both the module and the class because they permit potentially more efficient implementations on many structures (with null and length being sometimes, for example ''O(1)''), and it seemed desirable to allow users to take advantage of this asymptotically more efficient behaviour.<br />
<br />
== Now I'm getting unused import warnings. Help? ==<br />
<br />
Suppose your code had <code>import Foldable</code> in it, but you only used things that are now available from the prelude. After the FTP you'll be getting unused import warnings.<br />
<br />
You can go delete the import, but now your code doesn't work for pre-FTP versions! There is a trick to avoid these warnings while remaining compatible across versions. <br />
<br />
Stick <code>import Prelude</code> at the '''bottom''' of your imports list.<br />
<br />
This works because GHC checks that the imports provide something "new" that is used by the module in a top-down fashion, and you are almost certainly using something from Prelude that didn't come from one of the modules above.<br />
<br />
[[Category:FAQ]]<br />
[[Category:How to]]</div>Hvrhttps://wiki.haskell.org/index.php?title=Foldable_Traversable_In_Prelude&diff=59279Foldable Traversable In Prelude2015-02-04T09:45:46Z<p>Hvr: more semantic markup and add a reference to GHC #9621</p>
<hr />
<div>This page is a FAQ for the FTP (Foldable/Traversable in Prelude proposal) otherwise known as (part of) the BBP (Burning Bridges Proposal), slated for inclusion in the core libraries of GHC 7.10. While elements of this proposal may still be under discussion, this page is intended to summarize the proposal as it now stands as of 28 January, 2015. It is a work in progress, done as best as possible, but should not be taken as necessarily a full statement by the libraries committee on every aspect of this proposal.<br />
<br />
== Where did the FTP come from? ==<br />
<br />
The FTP was proposed in the context of a very lengthy [http://osdir.com/ml/libraries@haskell.org/2013-05/msg00280.html "Burning Bridges"] thread on the haskell libraries list in the summer of 2013.<br />
<br />
Over the course of this thread and subsequent and related discussions it was revealed there was a large appetite in the community to "modernize" the Prelude and bring it into line with the current widespread usage of classes such as Applicative, Foldable, and Traversable. Out of these discussions, a "Core Libraries Committee" was formed to manage and steward such large changes in a way to vet them thoroughly and ensure minimal breakage in carrying them out.<br />
<br />
== What does the FTP do? ==<br />
<br />
The FTP does what it says. It brings Foldable and Traversable into the Prelude. Along with this, it replaces Prelude functions that clash with Foldable and Traversable with their more polymorphic versions as drawn from those two classes and their associated methods. One goal here is that people should be able to use methods from these modules without the need of a qualified import -- i.e. to prevent clash in the namespace, by resolving such in favor of the more generalized versions. Additionally, there are some new methods added to the Foldable class because it seems to be the "right" thing. This proposal is semi-independent from the rest of FTP, but the changes tend to have been discussed under the same general umbrella.<br />
<br />
== Does the FTP change any behaviour? ==<br />
<br />
No (almost). By design, nearly any code that compiles under these changes should operate exactly as prior to these changes. If you believe you have found an area where these changes cause a semantic difference, it is a bug and should be reported.<br />
<br />
There are, however, changes to the behaviour of Data.Foldable.sum, Data.Foldable.product, Data.Foldable.maximum, and Data.Foldable.minimum on lists and only on lists, in order to bring them into accord with the prelude.<br />
<br />
== So does the FTP break any code? ==<br />
<br />
As little as possible. Many of the seemingly "odd" aspects of FTP come from engineering choices made specifically so as to minimize code breakage. In particular, a few packages may be broken by new exports from the prelude such as mconcat and foldMap. A few more may be broken by the export of new additions to the Foldable class. And finally, there are a few packages that may be broken by the new generalized signature in the prelude not being sufficient to pin down some otherwise already polymorphic code (particularly in the case of using -XOverloadedStrings).<br />
<br />
On the other hand, 569 packages in Stackage, including the core of it, build without problems. According to Edward Kmett, "of the 50-100 that remain, most are awaiting author feedback on already-filed issues / fixes or are broken by a small change downstream." [TODO: Please clarify if the failures of the remaining packages seem to be caused by FTP or not, in general.]<br />
<br />
== What are the concrete changes in the FTP? ==<br />
Here is a diff of the relevant changes. Note that there are other changes, not listed here, notably those introduced by the "AMP", which makes Applicative a superclass of Monad.<br />
<br />
<nowiki><br />
Control.Monad<br />
- foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a<br />
+ foldM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b<br />
- foldM_ :: Monad m => (a -> b -> m a) -> a -> [b] -> m ()<br />
+ foldM_ :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m ()<br />
- forM :: Monad m => [a] -> (a -> m b) -> m [b]<br />
+ forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)<br />
- forM_ :: Monad m => [a] -> (a -> m b) -> m ()<br />
+ forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()<br />
- mapM :: Monad m => (a -> m b) -> [a] -> m [b]<br />
+ mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)<br />
- mapM_ :: Monad m => (a -> m b) -> [a] -> m ()<br />
+ mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()<br />
- msum :: MonadPlus m => [m a] -> m a<br />
+ msum :: (Foldable t, MonadPlus m) => t (m a) -> m a<br />
- sequence :: Monad m => [m a] -> m [a]<br />
+ sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)<br />
- sequence_ :: Monad m => [m a] -> m ()<br />
+ sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()<br />
<br />
Data.List<br />
- all :: (a -> Bool) -> [a] -> Bool<br />
+ all :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- and :: [Bool] -> Bool<br />
+ and :: Foldable t => t Bool -> Bool<br />
- any :: (a -> Bool) -> [a] -> Bool<br />
+ any :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- concat :: [[a]] -> [a]<br />
+ concat :: Foldable t => t [a] -> [a]<br />
- concatMap :: (a -> [b]) -> [a] -> [b]<br />
+ concatMap :: Foldable t => (a -> [b]) -> t a -> [b]<br />
- elem :: Eq a => a -> [a] -> Bool<br />
+ elem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- find :: (a -> Bool) -> [a] -> Maybe a<br />
+ find :: Foldable t => (a -> Bool) -> t a -> Maybe a<br />
- foldl :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl' :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl' :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl1 :: (a -> a -> a) -> [a] -> a<br />
+ foldl1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- foldr :: (a -> b -> b) -> b -> [a] -> b<br />
+ foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b<br />
- foldr1 :: (a -> a -> a) -> [a] -> a<br />
+ foldr1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
+ isSubsequenceOf :: (Eq a) => [a] -> [a] -> Bool<br />
- length :: [a] -> Int<br />
+ length :: Foldable t => t a -> Int<br />
- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])<br />
+ mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
- mapAccumR :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])<br />
+ mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
- maximum :: Ord a => [a] -> a<br />
+ maximum :: (Foldable t, Ord a) => t a -> a<br />
- maximumBy :: (a -> a -> Ordering) -> [a] -> a<br />
+ maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a<br />
- minimum :: Ord a => [a] -> a<br />
+ minimum :: (Foldable t, Ord a) => t a -> a<br />
- minimumBy :: (a -> a -> Ordering) -> [a] -> a<br />
+ minimumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a<br />
- notElem :: Eq a => a -> [a] -> Bool<br />
+ notElem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- null :: [a] -> Bool<br />
+ null :: Foldable t => t a -> Bool<br />
- or :: [Bool] -> Bool<br />
+ or :: Foldable t => t Bool -> Bool<br />
- product :: Num a => [a] -> a<br />
+ product :: (Foldable t, Num a) => t a -> a<br />
+ scanl' :: (b -> a -> b) -> b -> [a] -> [b]<br />
+ sortOn :: Ord b => (a -> b) -> [a] -> [a]<br />
- sum :: Num a => [a] -> a<br />
+ sum :: (Foldable t, Num a) => t a -> a<br />
+ uncons :: [a] -> Maybe (a, [a])<br />
<br />
Prelude<br />
- all :: (a -> Bool) -> [a] -> Bool<br />
+ all :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- and :: [Bool] -> Bool<br />
+ and :: Foldable t => t Bool -> Bool<br />
- any :: (a -> Bool) -> [a] -> Bool<br />
+ any :: Foldable t => (a -> Bool) -> t a -> Bool<br />
+ class Monoid a<br />
+ class Foldable t<br />
+ class (Functor t, Foldable t) => Traversable t<br />
- concat :: [[a]] -> [a]<br />
+ concat :: Foldable t => t [a] -> [a]<br />
- concatMap :: (a -> [b]) -> [a] -> [b]<br />
+ concatMap :: Foldable t => (a -> [b]) -> t a -> [b]<br />
- elem :: Eq a => a -> [a] -> Bool<br />
+ elem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
+ foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m<br />
- foldl :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl1 :: (a -> a -> a) -> [a] -> a<br />
+ foldl1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- foldr :: (a -> b -> b) -> b -> [a] -> b<br />
+ foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b<br />
- foldr1 :: (a -> a -> a) -> [a] -> a<br />
+ foldr1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- length :: [a] -> Int<br />
+ length :: Foldable t => t a -> Int<br />
- mapM :: Monad m => (a -> m b) -> [a] -> m [b]<br />
+ mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)<br />
- mapM_ :: Monad m => (a -> m b) -> [a] -> m ()<br />
+ mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()<br />
+ mappend :: Monoid a => a -> a -> a<br />
- maximum :: Ord a => [a] -> a<br />
+ maximum :: (Foldable t, Ord a) => t a -> a<br />
+ mconcat :: Monoid a => [a] -> a<br />
+ mempty :: Monoid a => a<br />
- minimum :: Ord a => [a] -> a<br />
+ minimum :: (Foldable t, Ord a) => t a -> a<br />
- notElem :: Eq a => a -> [a] -> Bool<br />
+ notElem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- null :: [a] -> Bool<br />
+ null :: Foldable t => t a -> Bool<br />
- or :: [Bool] -> Bool<br />
+ or :: Foldable t => t Bool -> Bool<br />
- product :: Num a => [a] -> a<br />
+ product :: (Foldable t, Num a) => t a -> a<br />
- sequence :: Monad m => [m a] -> m [a]<br />
+ sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)<br />
+ sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)<br />
- sequence_ :: Monad m => [m a] -> m ()<br />
+ sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()<br />
- sum :: Num a => [a] -> a<br />
+ sum :: (Foldable t, Num a) => t a -> a<br />
+ traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)<br />
<br />
Data.Foldable<br />
+ length :: Foldable t => t a -> Int<br />
+ null :: Foldable t => t a -> Bool<br />
</nowiki><br />
<br />
Additionally, <code>toList</code>, <code>elem</code>, <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code>, before given as methods on <code>Foldable</code> items are now optional methods in the <code>Foldable</code> class.<br />
<br />
Finally, note that the addition of <code>length</code>, <code>null</code>, <code>toList</code>, and <code>elem</code> to <code>Foldable</code> are technically a separate proposal<ref>https://ghc.haskell.org/trac/ghc/ticket/9621</ref> but are often discussed in conjunction with the FTP. Meanwhile the addition of <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code> are considered part of the FTP, as will be discussed below.<br />
<br />
== Wow, that's a lot of changes! ==<br />
<br />
Well, yes and no. As you can see, these changes are all essentially strict generalizations of existing functions, which was indeed the goal.<br />
<br />
== But, why does Control.Monad also generalize its functions? ==<br />
<br />
Many people import <code>Control.Monad</code> unqualified. If we continued to export the monomorphic functions from <code>Control.Monad</code>, this would lead to many clashes, and much code would break. Now, all that remaining code still works!<br />
<br />
We could instead drop those functions from <code>Control.Monad</code> instead of reexporting their more polymorphic versions. But this would cause breakages for those who imported them explicitly or qualified. Now that code still works too!<br />
<br />
== But, why does Data.List also generalize its functions? ==<br />
<br />
Many people import <code>Data.List</code> unqualified. If we continued to export the monomorphic functions from <code>Data.List</code>, this would lead to many clashes, and much code would break. Now, all that remaining code still works!<br />
<br />
We could instead drop those functions from <code>Data.List</code> instead of reexporting their more polymorphic versions. But this would cause breakages for those who imported them explicitly or qualified. Now that code still works too!<br />
<br />
== OK, but why does the Foldable class have so many methods in it? ==<br />
<br />
Well, <code>Foldable</code> cannot just be given by <code>toList</code>, much as we might think of it as such. <code>foldMap</code> lets us fold over not only potentially right-infinite structures as with <code>foldr</code>, but potentially left-infinite ones (as with <code>foldl</code>) and even "both-infinite" ones such as rooted but infinitely branching trees!<br />
<br />
Other methods in the <code>Foldable</code> class, such as <code>foldl</code> and <code>foldr</code> exist for historical reasons, and to allow the possibility of more efficient implementations. <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code> were added because their prelude versions were performed with a <code>foldl</code>, while their general versions with a <code>foldMap</code>. Moving them into the class allowed Prelude behaviour to be preserved in the case of lists without altering behaviour otherwise in the case of other structures. This has led to the one semantic change in the FTP -- now that these Foldable methods on lists are in accord with the Prelude specification, this means that (unavoidably) their Foldable methods on lists have now changed behaviour.<br />
<br />
Finally, <code>toList</code> and <code>elem</code> were pulled into the class and <code>length</code> and <code>null</code> were added to both the module and the class because they permit potentially more efficient implementations on many structures (with null and length being sometimes, for example ''O(1)''), and it seemed desirable to allow users to take advantage of this asymptotically more efficient behaviour.<br />
<br />
== Now I'm getting unused import warnings. Help? ==<br />
<br />
Suppose your code had <code>import Foldable</code> in it, but you only used things that are now available from the prelude. After the FTP you'll be getting unused import warnings.<br />
<br />
You can go delete the import, but now your code doesn't work for pre-FTP versions! There is a trick to avoid these warnings while remaining compatible across versions. <br />
<br />
Stick <code>import Prelude</code> at the '''bottom''' of your imports list.<br />
<br />
This works because GHC checks that the imports provide something "new" that is used by the module in a top-down fashion, and you are almost certainly using something from Prelude that didn't come from one of the modules above.<br />
<br />
[[Category:FAQ]]<br />
[[Category:How to]]</div>Hvrhttps://wiki.haskell.org/index.php?title=Foldable_Traversable_In_Prelude&diff=59278Foldable Traversable In Prelude2015-02-04T09:40:16Z<p>Hvr: minor clarification and semantic-markup</p>
<hr />
<div>This page is a FAQ for the FTP (Foldable/Traversable in Prelude proposal) otherwise known as (part of) the BBP (Burning Bridges Proposal), slated for inclusion in the core libraries of GHC 7.10. While elements of this proposal may still be under discussion, this page is intended to summarize the proposal as it now stands as of 28 January, 2015. It is a work in progress, done as best as possible, but should not be taken as necessarily a full statement by the libraries committee on every aspect of this proposal.<br />
<br />
== Where did the FTP come from? ==<br />
<br />
The FTP was proposed in the context of a very lengthy [http://osdir.com/ml/libraries@haskell.org/2013-05/msg00280.html "Burning Bridges"] thread on the haskell libraries list in the summer of 2013.<br />
<br />
Over the course of this thread and subsequent and related discussions it was revealed there was a large appetite in the community to "modernize" the Prelude and bring it into line with the current widespread usage of classes such as Applicative, Foldable, and Traversable. Out of these discussions, a "Core Libraries Committee" was formed to manage and steward such large changes in a way to vet them thoroughly and ensure minimal breakage in carrying them out.<br />
<br />
== What does the FTP do? ==<br />
<br />
The FTP does what it says. It brings Foldable and Traversable into the Prelude. Along with this, it replaces Prelude functions that clash with Foldable and Traversable with their more polymorphic versions as drawn from those two classes and their associated methods. One goal here is that people should be able to use methods from these modules without the need of a qualified import -- i.e. to prevent clash in the namespace, by resolving such in favor of the more generalized versions. Additionally, there are some new methods added to the Foldable class because it seems to be the "right" thing. This proposal is semi-independent from the rest of FTP, but the changes tend to have been discussed under the same general umbrella.<br />
<br />
== Does the FTP change any behaviour? ==<br />
<br />
No (almost). By design, nearly any code that compiles under these changes should operate exactly as prior to these changes. If you believe you have found an area where these changes cause a semantic difference, it is a bug and should be reported.<br />
<br />
There are, however, changes to the behaviour of Data.Foldable.sum, Data.Foldable.product, Data.Foldable.maximum, and Data.Foldable.minimum on lists and only on lists, in order to bring them into accord with the prelude.<br />
<br />
== So does the FTP break any code? ==<br />
<br />
As little as possible. Many of the seemingly "odd" aspects of FTP come from engineering choices made specifically so as to minimize code breakage. In particular, a few packages may be broken by new exports from the prelude such as mconcat and foldMap. A few more may be broken by the export of new additions to the Foldable class. And finally, there are a few packages that may be broken by the new generalized signature in the prelude not being sufficient to pin down some otherwise already polymorphic code (particularly in the case of using -XOverloadedStrings).<br />
<br />
On the other hand, 569 packages in Stackage, including the core of it, build without problems. According to Edward Kmett, "of the 50-100 that remain, most are awaiting author feedback on already-filed issues / fixes or are broken by a small change downstream." [TODO: Please clarify if the failures of the remaining packages seem to be caused by FTP or not, in general.]<br />
<br />
== What are the concrete changes in the FTP? ==<br />
Here is a diff of the relevant changes. Note that there are other changes, not listed here, notably those introduced by the "AMP", which makes Applicative a superclass of Monad.<br />
<br />
<nowiki><br />
Control.Monad<br />
- foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a<br />
+ foldM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b<br />
- foldM_ :: Monad m => (a -> b -> m a) -> a -> [b] -> m ()<br />
+ foldM_ :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m ()<br />
- forM :: Monad m => [a] -> (a -> m b) -> m [b]<br />
+ forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)<br />
- forM_ :: Monad m => [a] -> (a -> m b) -> m ()<br />
+ forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()<br />
- mapM :: Monad m => (a -> m b) -> [a] -> m [b]<br />
+ mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)<br />
- mapM_ :: Monad m => (a -> m b) -> [a] -> m ()<br />
+ mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()<br />
- msum :: MonadPlus m => [m a] -> m a<br />
+ msum :: (Foldable t, MonadPlus m) => t (m a) -> m a<br />
- sequence :: Monad m => [m a] -> m [a]<br />
+ sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)<br />
- sequence_ :: Monad m => [m a] -> m ()<br />
+ sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()<br />
<br />
Data.List<br />
- all :: (a -> Bool) -> [a] -> Bool<br />
+ all :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- and :: [Bool] -> Bool<br />
+ and :: Foldable t => t Bool -> Bool<br />
- any :: (a -> Bool) -> [a] -> Bool<br />
+ any :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- concat :: [[a]] -> [a]<br />
+ concat :: Foldable t => t [a] -> [a]<br />
- concatMap :: (a -> [b]) -> [a] -> [b]<br />
+ concatMap :: Foldable t => (a -> [b]) -> t a -> [b]<br />
- elem :: Eq a => a -> [a] -> Bool<br />
+ elem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- find :: (a -> Bool) -> [a] -> Maybe a<br />
+ find :: Foldable t => (a -> Bool) -> t a -> Maybe a<br />
- foldl :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl' :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl' :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl1 :: (a -> a -> a) -> [a] -> a<br />
+ foldl1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- foldr :: (a -> b -> b) -> b -> [a] -> b<br />
+ foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b<br />
- foldr1 :: (a -> a -> a) -> [a] -> a<br />
+ foldr1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
+ isSubsequenceOf :: (Eq a) => [a] -> [a] -> Bool<br />
- length :: [a] -> Int<br />
+ length :: Foldable t => t a -> Int<br />
- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])<br />
+ mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
- mapAccumR :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])<br />
+ mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
- maximum :: Ord a => [a] -> a<br />
+ maximum :: (Foldable t, Ord a) => t a -> a<br />
- maximumBy :: (a -> a -> Ordering) -> [a] -> a<br />
+ maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a<br />
- minimum :: Ord a => [a] -> a<br />
+ minimum :: (Foldable t, Ord a) => t a -> a<br />
- minimumBy :: (a -> a -> Ordering) -> [a] -> a<br />
+ minimumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a<br />
- notElem :: Eq a => a -> [a] -> Bool<br />
+ notElem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- null :: [a] -> Bool<br />
+ null :: Foldable t => t a -> Bool<br />
- or :: [Bool] -> Bool<br />
+ or :: Foldable t => t Bool -> Bool<br />
- product :: Num a => [a] -> a<br />
+ product :: (Foldable t, Num a) => t a -> a<br />
+ scanl' :: (b -> a -> b) -> b -> [a] -> [b]<br />
+ sortOn :: Ord b => (a -> b) -> [a] -> [a]<br />
- sum :: Num a => [a] -> a<br />
+ sum :: (Foldable t, Num a) => t a -> a<br />
+ uncons :: [a] -> Maybe (a, [a])<br />
<br />
Prelude<br />
- all :: (a -> Bool) -> [a] -> Bool<br />
+ all :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- and :: [Bool] -> Bool<br />
+ and :: Foldable t => t Bool -> Bool<br />
- any :: (a -> Bool) -> [a] -> Bool<br />
+ any :: Foldable t => (a -> Bool) -> t a -> Bool<br />
+ class Monoid a<br />
+ class Foldable t<br />
+ class (Functor t, Foldable t) => Traversable t<br />
- concat :: [[a]] -> [a]<br />
+ concat :: Foldable t => t [a] -> [a]<br />
- concatMap :: (a -> [b]) -> [a] -> [b]<br />
+ concatMap :: Foldable t => (a -> [b]) -> t a -> [b]<br />
- elem :: Eq a => a -> [a] -> Bool<br />
+ elem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
+ foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m<br />
- foldl :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl1 :: (a -> a -> a) -> [a] -> a<br />
+ foldl1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- foldr :: (a -> b -> b) -> b -> [a] -> b<br />
+ foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b<br />
- foldr1 :: (a -> a -> a) -> [a] -> a<br />
+ foldr1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- length :: [a] -> Int<br />
+ length :: Foldable t => t a -> Int<br />
- mapM :: Monad m => (a -> m b) -> [a] -> m [b]<br />
+ mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)<br />
- mapM_ :: Monad m => (a -> m b) -> [a] -> m ()<br />
+ mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()<br />
+ mappend :: Monoid a => a -> a -> a<br />
- maximum :: Ord a => [a] -> a<br />
+ maximum :: (Foldable t, Ord a) => t a -> a<br />
+ mconcat :: Monoid a => [a] -> a<br />
+ mempty :: Monoid a => a<br />
- minimum :: Ord a => [a] -> a<br />
+ minimum :: (Foldable t, Ord a) => t a -> a<br />
- notElem :: Eq a => a -> [a] -> Bool<br />
+ notElem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- null :: [a] -> Bool<br />
+ null :: Foldable t => t a -> Bool<br />
- or :: [Bool] -> Bool<br />
+ or :: Foldable t => t Bool -> Bool<br />
- product :: Num a => [a] -> a<br />
+ product :: (Foldable t, Num a) => t a -> a<br />
- sequence :: Monad m => [m a] -> m [a]<br />
+ sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)<br />
+ sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)<br />
- sequence_ :: Monad m => [m a] -> m ()<br />
+ sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()<br />
- sum :: Num a => [a] -> a<br />
+ sum :: (Foldable t, Num a) => t a -> a<br />
+ traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)<br />
<br />
Data.Foldable<br />
+ length :: Foldable t => t a -> Int<br />
+ null :: Foldable t => t a -> Bool<br />
</nowiki><br />
<br />
Additionally, <code>toList</code>, <code>elem</code>, <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code>, before given as methods on <code>Foldable</code> items are now optional methods in the <code>Foldable</code> class.<br />
<br />
Finally, note that the addition of <code>length</code>, <code>null</code>, <code>toList</code>, and <code>elem</code> to <code>Foldable</code> are technically a separate proposal but are often discussed in conjunction with the FTP. Meanwhile the addition of <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code> are considered part of the FTP, as will be discussed below.<br />
<br />
== Wow, that's a lot of changes! ==<br />
<br />
Well, yes and no. As you can see, these changes are all essentially strict generalizations of existing functions, which was indeed the goal.<br />
<br />
== But, why does Control.Monad also generalize its functions? ==<br />
<br />
Many people import Control.Monad unqualified. If we continued to export the monomorphic functions from Control.Monad, this would lead to many clashes, and much code would break. Now, all that remaining code still works!<br />
<br />
We could instead drop those functions from Control.Monad instead of reexporting their more polymorphic versions. But this would cause breakages for those who imported them explicitly or qualified. Now that code still works too!<br />
<br />
== But, why does Data.List also generalize its functions? ==<br />
<br />
Many people import Data.List unqualified. If we continued to export the monomorphic functions from Data.List, this would lead to many clashes, and much code would break. Now, all that remaining code still works!<br />
<br />
We could instead drop those functions from Data.List instead of reexporting their more polymorphic versions. But this would cause breakages for those who imported them explicitly or qualified. Now that code still works too!<br />
<br />
== OK, but why does the Foldable class have so many methods in it? ==<br />
<br />
Well, <code>Foldable</code> cannot just be given by <code>toList</code>, much as we might think of it as such. <code>foldMap</code> lets us fold over not only potentially right-infinite structures as with <code>foldr</code>, but potentially left-infinite ones (as with <code>foldl</code>) and even "both-infinite" ones such as rooted but infinitely branching trees!<br />
<br />
Other methods in the <code>Foldable</code> class, such as <code>foldl</code> and <code>foldr</code> exist for historical reasons, and to allow the possibility of more efficient implementations. <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code> were added because their prelude versions were performed with a <code>foldl</code>, while their general versions with a <code>foldMap</code>. Moving them into the class allowed Prelude behaviour to be preserved in the case of lists without altering behaviour otherwise in the case of other structures. This has led to the one semantic change in the FTP -- now that these Foldable methods on lists are in accord with the Prelude specification, this means that (unavoidably) their Foldable methods on lists have now changed behaviour.<br />
<br />
Finally, <code>toList</code> and <code>elem</code> were pulled into the class and <code>length</code> and <code>null</code> were added to both the module and the class because they permit potentially more efficient implementations on many structures (with null and length being sometimes, for example ''O(1)''), and it seemed desirable to allow users to take advantage of this asymptotically more efficient behaviour.<br />
<br />
== Now I'm getting unused import warnings. Help? ==<br />
<br />
Suppose your code had <code>import Foldable</code> in it, but you only used things that are now available from the prelude. After the FTP you'll be getting unused import warnings.<br />
<br />
You can go delete the import, but now your code doesn't work for pre-FTP versions! There is a trick to avoid these warnings while remaining compatible across versions. <br />
<br />
Stick <code>import Prelude</code> at the '''bottom''' of your imports list.<br />
<br />
This works because GHC checks that the imports provide something "new" that is used by the module in a top-down fashion, and you are almost certainly using something from Prelude that didn't come from one of the modules above.<br />
<br />
[[Category:FAQ]]<br />
[[Category:How to]]</div>Hvrhttps://wiki.haskell.org/index.php?title=Foldable_Traversable_In_Prelude&diff=59263Foldable Traversable In Prelude2015-02-01T21:53:41Z<p>Hvr: Undo revision 59262 by Hvr (talk)</p>
<hr />
<div>This page is a FAQ for the FTP (Foldable/Traversable in Prelude proposal) otherwise known as the BBP (Burning Bridges Proposal), slated for inclusion in the core libraries of GHC 7.10. While elements of this proposal may still be under discussion, this page is intended to summarize the proposal as it now stands as of 28 January, 2015. It is a work in progress, done as best as possible, but should not be taken as necessarily a full statement by the libraries committee on every aspect of this proposal.<br />
<br />
== Where did the FTP come from? ==<br />
<br />
The FTP was proposed in the context of a very lengthy [http://osdir.com/ml/libraries@haskell.org/2013-05/msg00280.html "Burning Bridges"] thread on the haskell libraries list in the summer of 2013.<br />
<br />
Over the course of this thread and subsequent and related discussions it was revealed there was a large appetite in the community to "modernize" the Prelude and bring it into line with the current widespread usage of classes such as Applicative, Foldable, and Traversable. Out of these discussions, a "Core Libraries Committee" was formed to manage and steward such large changes in a way to vet them thoroughly and ensure minimal breakage in carrying them out.<br />
<br />
== What does the FTP do? ==<br />
<br />
The FTP does what it says. It brings Foldable and Traversable into the Prelude. Along with this, it replaces Prelude functions that clash with Foldable and Traversable with their more polymorphic versions as drawn from those two classes and their associated methods. One goal here is that people should be able to use methods from these modules without the need of a qualified import -- i.e. to prevent clash in the namespace, by resolving such in favor of the more generalized versions. Additionally, there are some new methods added to the Foldable class because it seems to be the "right" thing. This proposal is semi-independent from the rest of FTP, but the changes tend to have been discussed under the same general umbrella.<br />
<br />
== Does the FTP change any behaviour? ==<br />
<br />
No (almost). By design, nearly any code that compiles under these changes should operate exactly as prior to these changes. If you believe you have found an area where these changes cause a semantic difference, it is a bug and should be reported.<br />
<br />
There are, however, changes to the behaviour of Data.Foldable.sum, Data.Foldable.product, Data.Foldable.maximum, and Data.Foldable.minimum on lists and only on lists, in order to bring them into accord with the prelude.<br />
<br />
== So does the FTP break any code? ==<br />
<br />
As little as possible. Many of the seemingly "odd" aspects of FTP come from engineering choices made specifically so as to minimize code breakage. In particular, a few packages may be broken by new exports from the prelude such as mconcat and foldMap. A few more may be broken by the export of new additions to the Foldable class. And finally, there are a few packages that may be broken by the new generalized signature in the prelude not being sufficient to pin down some otherwise already polymorphic code (particularly in the case of using -XOverloadedStrings).<br />
<br />
On the other hand, 569 packages in Stackage, including the core of it, build without problems. According to Edward Kmett, "of the 50-100 that remain, most are awaiting author feedback on already-filed issues / fixes or are broken by a small change downstream."<br />
<br />
== What are the concrete changes in the FTP? ==<br />
Here is a diff of the relevant changes. Note that there are other changes, not listed here, notably those introduced by the "AMP", which makes Applicative a superclass of Monad.<br />
<br />
<nowiki><br />
Control.Monad<br />
- foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a<br />
+ foldM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b<br />
- foldM_ :: Monad m => (a -> b -> m a) -> a -> [b] -> m ()<br />
+ foldM_ :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m ()<br />
- forM :: Monad m => [a] -> (a -> m b) -> m [b]<br />
+ forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)<br />
- forM_ :: Monad m => [a] -> (a -> m b) -> m ()<br />
+ forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()<br />
- mapM :: Monad m => (a -> m b) -> [a] -> m [b]<br />
+ mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)<br />
- mapM_ :: Monad m => (a -> m b) -> [a] -> m ()<br />
+ mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()<br />
- msum :: MonadPlus m => [m a] -> m a<br />
+ msum :: (Foldable t, MonadPlus m) => t (m a) -> m a<br />
- sequence :: Monad m => [m a] -> m [a]<br />
+ sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)<br />
- sequence_ :: Monad m => [m a] -> m ()<br />
+ sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()<br />
<br />
Data.List<br />
- all :: (a -> Bool) -> [a] -> Bool<br />
+ all :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- and :: [Bool] -> Bool<br />
+ and :: Foldable t => t Bool -> Bool<br />
- any :: (a -> Bool) -> [a] -> Bool<br />
+ any :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- concat :: [[a]] -> [a]<br />
+ concat :: Foldable t => t [a] -> [a]<br />
- concatMap :: (a -> [b]) -> [a] -> [b]<br />
+ concatMap :: Foldable t => (a -> [b]) -> t a -> [b]<br />
- elem :: Eq a => a -> [a] -> Bool<br />
+ elem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- find :: (a -> Bool) -> [a] -> Maybe a<br />
+ find :: Foldable t => (a -> Bool) -> t a -> Maybe a<br />
- foldl :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl' :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl' :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl1 :: (a -> a -> a) -> [a] -> a<br />
+ foldl1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- foldr :: (a -> b -> b) -> b -> [a] -> b<br />
+ foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b<br />
- foldr1 :: (a -> a -> a) -> [a] -> a<br />
+ foldr1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
+ isSubsequenceOf :: (Eq a) => [a] -> [a] -> Bool<br />
- length :: [a] -> Int<br />
+ length :: Foldable t => t a -> Int<br />
- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])<br />
+ mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
- mapAccumR :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])<br />
+ mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
- maximum :: Ord a => [a] -> a<br />
+ maximum :: (Foldable t, Ord a) => t a -> a<br />
- maximumBy :: (a -> a -> Ordering) -> [a] -> a<br />
+ maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a<br />
- minimum :: Ord a => [a] -> a<br />
+ minimum :: (Foldable t, Ord a) => t a -> a<br />
- minimumBy :: (a -> a -> Ordering) -> [a] -> a<br />
+ minimumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a<br />
- notElem :: Eq a => a -> [a] -> Bool<br />
+ notElem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- null :: [a] -> Bool<br />
+ null :: Foldable t => t a -> Bool<br />
- or :: [Bool] -> Bool<br />
+ or :: Foldable t => t Bool -> Bool<br />
- product :: Num a => [a] -> a<br />
+ product :: (Foldable t, Num a) => t a -> a<br />
+ scanl' :: (b -> a -> b) -> b -> [a] -> [b]<br />
+ sortOn :: Ord b => (a -> b) -> [a] -> [a]<br />
- sum :: Num a => [a] -> a<br />
+ sum :: (Foldable t, Num a) => t a -> a<br />
+ uncons :: [a] -> Maybe (a, [a])<br />
<br />
Prelude<br />
- all :: (a -> Bool) -> [a] -> Bool<br />
+ all :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- and :: [Bool] -> Bool<br />
+ and :: Foldable t => t Bool -> Bool<br />
- any :: (a -> Bool) -> [a] -> Bool<br />
+ any :: Foldable t => (a -> Bool) -> t a -> Bool<br />
+ class Monoid a<br />
+ class Foldable t<br />
+ class (Functor t, Foldable t) => Traversable t<br />
- concat :: [[a]] -> [a]<br />
+ concat :: Foldable t => t [a] -> [a]<br />
- concatMap :: (a -> [b]) -> [a] -> [b]<br />
+ concatMap :: Foldable t => (a -> [b]) -> t a -> [b]<br />
- elem :: Eq a => a -> [a] -> Bool<br />
+ elem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
+ foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m<br />
- foldl :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl1 :: (a -> a -> a) -> [a] -> a<br />
+ foldl1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- foldr :: (a -> b -> b) -> b -> [a] -> b<br />
+ foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b<br />
- foldr1 :: (a -> a -> a) -> [a] -> a<br />
+ foldr1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- length :: [a] -> Int<br />
+ length :: Foldable t => t a -> Int<br />
- mapM :: Monad m => (a -> m b) -> [a] -> m [b]<br />
+ mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)<br />
- mapM_ :: Monad m => (a -> m b) -> [a] -> m ()<br />
+ mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()<br />
+ mappend :: Monoid a => a -> a -> a<br />
- maximum :: Ord a => [a] -> a<br />
+ maximum :: (Foldable t, Ord a) => t a -> a<br />
+ mconcat :: Monoid a => [a] -> a<br />
+ mempty :: Monoid a => a<br />
- minimum :: Ord a => [a] -> a<br />
+ minimum :: (Foldable t, Ord a) => t a -> a<br />
- notElem :: Eq a => a -> [a] -> Bool<br />
+ notElem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- null :: [a] -> Bool<br />
+ null :: Foldable t => t a -> Bool<br />
- or :: [Bool] -> Bool<br />
+ or :: Foldable t => t Bool -> Bool<br />
- product :: Num a => [a] -> a<br />
+ product :: (Foldable t, Num a) => t a -> a<br />
- sequence :: Monad m => [m a] -> m [a]<br />
+ sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)<br />
+ sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)<br />
- sequence_ :: Monad m => [m a] -> m ()<br />
+ sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()<br />
- sum :: Num a => [a] -> a<br />
+ sum :: (Foldable t, Num a) => t a -> a<br />
+ traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)<br />
<br />
Data.Foldable<br />
+ length :: Foldable t => t a -> Int<br />
+ null :: Foldable t => t a -> Bool<br />
</nowiki><br />
<br />
Additionally, <code>toList</code>, <code>elem</code>, <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code>, before given as methods on <code>Foldable</code> items are now optional methods in the <code>Foldable</code> class.<br />
<br />
Finally, note that the addition of <code>length</code>, <code>null</code>, <code>toList</code>, and <code>elem</code> to <code>Foldable</code> are technically a separate proposal but are often discussed in conjunction with the FTP. Meanwhile the addition of <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code> are considered part of the FTP, as will be discussed below.<br />
<br />
== Wow, that's a lot of changes! ==<br />
<br />
Well, yes and no. As you can see, these changes are all essentially strict generalizations of existing functions, which was indeed the goal.<br />
<br />
== But, why does Control.Monad also generalize its functions? ==<br />
<br />
Many people import Control.Monad unqualified. If we continued to export the monomorphic functions from Control.Monad, this would lead to many clashes, and much code would break. Now, all that remaining code still works!<br />
<br />
We could instead drop those functions from Control.Monad instead of reexporting their more polymorphic versions. But this would cause breakages for those who imported them explicitly or qualified. Now that code still works too!<br />
<br />
== But, why does Data.List also generalize its functions? ==<br />
<br />
Many people import Data.List unqualified. If we continued to export the monomorphic functions from Data.List, this would lead to many clashes, and much code would break. Now, all that remaining code still works!<br />
<br />
We could instead drop those functions from Data.List instead of reexporting their more polymorphic versions. But this would cause breakages for those who imported them explicitly or qualified. Now that code still works too!<br />
<br />
== OK, but why does the Foldable class have so many methods in it? ==<br />
<br />
Well, Foldable cannot just be given by toList, much as we might think of it as such. foldMap lets us fold over not only potentially right-infinite structures as with foldr, but potentially left-infinite ones (as with foldl) and even "both-infinite" ones such as rooted but infinitely branching trees!<br />
<br />
Other methods in the Foldable class, such as foldl and foldr exist for historical reasons, and to allow the possibility of more efficient implementations. Sum, product, maximum, and minimum were added because their prelude versions were performed with a foldl, while their general versions with a foldMap. Moving them into the class allowed Prelude behaviour to be preserved in the case of lists without altering behaviour otherwise in the case of other structures. This has led to the one semantic change in the FTP -- now that these Foldable methods on lists are in accord with the Prelude specification, this means that (unavoidably) their Foldable methods on lists have now changed behaviour.<br />
<br />
Finally, toList and elem were pulled into the class and length and null were added to both the module and the class because they permit potentially more efficient implementations on many structures (with null and length being sometimes, for example O(1)), and it seemed desirable to allow users to take advantage of this asymptotically more efficient behaviour.<br />
<br />
== Now I'm getting unused import warnings. Help? ==<br />
<br />
Suppose your code had <code>import Foldable</code> in it, but you only used things that are now available from the prelude. After the FTP you'll be getting unused import warnings.<br />
<br />
You can go delete the import, but now your code doesn't work for pre-FTP versions! There is a trick to avoid these warnings while remaining compatible across versions. <br />
<br />
Stick <code>import Prelude</code> at the '''bottom''' of your imports list.<br />
<br />
This works because GHC checks that the imports provide something "new" that is used by the module in a top-down fashion, and you are almost certainly using something from Prelude that didn't come from one of the modules above.<br />
<br />
[[Category:FAQ]]<br />
[[Category:How to]]</div>Hvrhttps://wiki.haskell.org/index.php?title=Foldable_Traversable_In_Prelude&diff=59262Foldable Traversable In Prelude2015-02-01T20:49:17Z<p>Hvr: Monoid(..) was not added to Prelude by FTP, but rather due to AMP</p>
<hr />
<div>This page is a FAQ for the FTP (Foldable/Traversable in Prelude proposal) otherwise known as the BBP (Burning Bridges Proposal), slated for inclusion in the core libraries of GHC 7.10. While elements of this proposal may still be under discussion, this page is intended to summarize the proposal as it now stands as of 28 January, 2015. It is a work in progress, done as best as possible, but should not be taken as necessarily a full statement by the libraries committee on every aspect of this proposal.<br />
<br />
== Where did the FTP come from? ==<br />
<br />
The FTP was proposed in the context of a very lengthy [http://osdir.com/ml/libraries@haskell.org/2013-05/msg00280.html "Burning Bridges"] thread on the haskell libraries list in the summer of 2013.<br />
<br />
Over the course of this thread and subsequent and related discussions it was revealed there was a large appetite in the community to "modernize" the Prelude and bring it into line with the current widespread usage of classes such as Applicative, Foldable, and Traversable. Out of these discussions, a "Core Libraries Committee" was formed to manage and steward such large changes in a way to vet them thoroughly and ensure minimal breakage in carrying them out.<br />
<br />
== What does the FTP do? ==<br />
<br />
The FTP does what it says. It brings Foldable and Traversable into the Prelude. Along with this, it replaces Prelude functions that clash with Foldable and Traversable with their more polymorphic versions as drawn from those two classes and their associated methods. One goal here is that people should be able to use methods from these modules without the need of a qualified import -- i.e. to prevent clash in the namespace, by resolving such in favor of the more generalized versions. Additionally, there are some new methods added to the Foldable class because it seems to be the "right" thing. This proposal is semi-independent from the rest of FTP, but the changes tend to have been discussed under the same general umbrella.<br />
<br />
== Does the FTP change any behaviour? ==<br />
<br />
No (almost). By design, nearly any code that compiles under these changes should operate exactly as prior to these changes. If you believe you have found an area where these changes cause a semantic difference, it is a bug and should be reported.<br />
<br />
There are, however, changes to the behaviour of Data.Foldable.sum, Data.Foldable.product, Data.Foldable.maximum, and Data.Foldable.minimum on lists and only on lists, in order to bring them into accord with the prelude.<br />
<br />
== So does the FTP break any code? ==<br />
<br />
As little as possible. Many of the seemingly "odd" aspects of FTP come from engineering choices made specifically so as to minimize code breakage. In particular, a few packages may be broken by new exports from the prelude such as mconcat and foldMap. A few more may be broken by the export of new additions to the Foldable class. And finally, there are a few packages that may be broken by the new generalized signature in the prelude not being sufficient to pin down some otherwise already polymorphic code (particularly in the case of using -XOverloadedStrings).<br />
<br />
On the other hand, 569 packages in Stackage, including the core of it, build without problems. According to Edward Kmett, "of the 50-100 that remain, most are awaiting author feedback on already-filed issues / fixes or are broken by a small change downstream."<br />
<br />
== What are the concrete changes in the FTP? ==<br />
Here is a diff of the relevant changes. Note that there are other changes, not listed here, notably those introduced by the "AMP", which makes Applicative a superclass of Monad.<br />
<br />
<nowiki><br />
Control.Monad<br />
- foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a<br />
+ foldM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b<br />
- foldM_ :: Monad m => (a -> b -> m a) -> a -> [b] -> m ()<br />
+ foldM_ :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m ()<br />
- forM :: Monad m => [a] -> (a -> m b) -> m [b]<br />
+ forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)<br />
- forM_ :: Monad m => [a] -> (a -> m b) -> m ()<br />
+ forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()<br />
- mapM :: Monad m => (a -> m b) -> [a] -> m [b]<br />
+ mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)<br />
- mapM_ :: Monad m => (a -> m b) -> [a] -> m ()<br />
+ mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()<br />
- msum :: MonadPlus m => [m a] -> m a<br />
+ msum :: (Foldable t, MonadPlus m) => t (m a) -> m a<br />
- sequence :: Monad m => [m a] -> m [a]<br />
+ sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)<br />
- sequence_ :: Monad m => [m a] -> m ()<br />
+ sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()<br />
<br />
Data.List<br />
- all :: (a -> Bool) -> [a] -> Bool<br />
+ all :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- and :: [Bool] -> Bool<br />
+ and :: Foldable t => t Bool -> Bool<br />
- any :: (a -> Bool) -> [a] -> Bool<br />
+ any :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- concat :: [[a]] -> [a]<br />
+ concat :: Foldable t => t [a] -> [a]<br />
- concatMap :: (a -> [b]) -> [a] -> [b]<br />
+ concatMap :: Foldable t => (a -> [b]) -> t a -> [b]<br />
- elem :: Eq a => a -> [a] -> Bool<br />
+ elem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- find :: (a -> Bool) -> [a] -> Maybe a<br />
+ find :: Foldable t => (a -> Bool) -> t a -> Maybe a<br />
- foldl :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl' :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl' :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl1 :: (a -> a -> a) -> [a] -> a<br />
+ foldl1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- foldr :: (a -> b -> b) -> b -> [a] -> b<br />
+ foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b<br />
- foldr1 :: (a -> a -> a) -> [a] -> a<br />
+ foldr1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
+ isSubsequenceOf :: (Eq a) => [a] -> [a] -> Bool<br />
- length :: [a] -> Int<br />
+ length :: Foldable t => t a -> Int<br />
- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])<br />
+ mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
- mapAccumR :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])<br />
+ mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
- maximum :: Ord a => [a] -> a<br />
+ maximum :: (Foldable t, Ord a) => t a -> a<br />
- maximumBy :: (a -> a -> Ordering) -> [a] -> a<br />
+ maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a<br />
- minimum :: Ord a => [a] -> a<br />
+ minimum :: (Foldable t, Ord a) => t a -> a<br />
- minimumBy :: (a -> a -> Ordering) -> [a] -> a<br />
+ minimumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a<br />
- notElem :: Eq a => a -> [a] -> Bool<br />
+ notElem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- null :: [a] -> Bool<br />
+ null :: Foldable t => t a -> Bool<br />
- or :: [Bool] -> Bool<br />
+ or :: Foldable t => t Bool -> Bool<br />
- product :: Num a => [a] -> a<br />
+ product :: (Foldable t, Num a) => t a -> a<br />
+ scanl' :: (b -> a -> b) -> b -> [a] -> [b]<br />
+ sortOn :: Ord b => (a -> b) -> [a] -> [a]<br />
- sum :: Num a => [a] -> a<br />
+ sum :: (Foldable t, Num a) => t a -> a<br />
+ uncons :: [a] -> Maybe (a, [a])<br />
<br />
Prelude<br />
- all :: (a -> Bool) -> [a] -> Bool<br />
+ all :: Foldable t => (a -> Bool) -> t a -> Bool<br />
- and :: [Bool] -> Bool<br />
+ and :: Foldable t => t Bool -> Bool<br />
- any :: (a -> Bool) -> [a] -> Bool<br />
+ any :: Foldable t => (a -> Bool) -> t a -> Bool<br />
+ class Foldable t<br />
+ class (Functor t, Foldable t) => Traversable t<br />
- concat :: [[a]] -> [a]<br />
+ concat :: Foldable t => t [a] -> [a]<br />
- concatMap :: (a -> [b]) -> [a] -> [b]<br />
+ concatMap :: Foldable t => (a -> [b]) -> t a -> [b]<br />
- elem :: Eq a => a -> [a] -> Bool<br />
+ elem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
+ foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m<br />
- foldl :: (b -> a -> b) -> b -> [a] -> b<br />
+ foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b<br />
- foldl1 :: (a -> a -> a) -> [a] -> a<br />
+ foldl1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- foldr :: (a -> b -> b) -> b -> [a] -> b<br />
+ foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b<br />
- foldr1 :: (a -> a -> a) -> [a] -> a<br />
+ foldr1 :: Foldable t => (a -> a -> a) -> t a -> a<br />
- length :: [a] -> Int<br />
+ length :: Foldable t => t a -> Int<br />
- mapM :: Monad m => (a -> m b) -> [a] -> m [b]<br />
+ mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)<br />
- mapM_ :: Monad m => (a -> m b) -> [a] -> m ()<br />
+ mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()<br />
- maximum :: Ord a => [a] -> a<br />
+ maximum :: (Foldable t, Ord a) => t a -> a<br />
- minimum :: Ord a => [a] -> a<br />
+ minimum :: (Foldable t, Ord a) => t a -> a<br />
- notElem :: Eq a => a -> [a] -> Bool<br />
+ notElem :: (Foldable t, Eq a) => a -> t a -> Bool<br />
- null :: [a] -> Bool<br />
+ null :: Foldable t => t a -> Bool<br />
- or :: [Bool] -> Bool<br />
+ or :: Foldable t => t Bool -> Bool<br />
- product :: Num a => [a] -> a<br />
+ product :: (Foldable t, Num a) => t a -> a<br />
- sequence :: Monad m => [m a] -> m [a]<br />
+ sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)<br />
+ sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)<br />
- sequence_ :: Monad m => [m a] -> m ()<br />
+ sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()<br />
- sum :: Num a => [a] -> a<br />
+ sum :: (Foldable t, Num a) => t a -> a<br />
+ traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)<br />
<br />
Data.Foldable<br />
+ length :: Foldable t => t a -> Int<br />
+ null :: Foldable t => t a -> Bool<br />
</nowiki><br />
<br />
Additionally, <code>toList</code>, <code>elem</code>, <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code>, before given as methods on <code>Foldable</code> items are now optional methods in the <code>Foldable</code> class.<br />
<br />
Finally, note that the addition of <code>length</code>, <code>null</code>, <code>toList</code>, and <code>elem</code> to <code>Foldable</code> are technically a separate proposal but are often discussed in conjunction with the FTP. Meanwhile the addition of <code>sum</code>, <code>product</code>, <code>maximum</code>, and <code>minimum</code> are considered part of the FTP, as will be discussed below.<br />
<br />
== Wow, that's a lot of changes! ==<br />
<br />
Well, yes and no. As you can see, these changes are all essentially strict generalizations of existing functions, which was indeed the goal.<br />
<br />
== But, why does Control.Monad also generalize its functions? ==<br />
<br />
Many people import Control.Monad unqualified. If we continued to export the monomorphic functions from Control.Monad, this would lead to many clashes, and much code would break. Now, all that remaining code still works!<br />
<br />
We could instead drop those functions from Control.Monad instead of reexporting their more polymorphic versions. But this would cause breakages for those who imported them explicitly or qualified. Now that code still works too!<br />
<br />
== But, why does Data.List also generalize its functions? ==<br />
<br />
Many people import Data.List unqualified. If we continued to export the monomorphic functions from Data.List, this would lead to many clashes, and much code would break. Now, all that remaining code still works!<br />
<br />
We could instead drop those functions from Data.List instead of reexporting their more polymorphic versions. But this would cause breakages for those who imported them explicitly or qualified. Now that code still works too!<br />
<br />
== OK, but why does the Foldable class have so many methods in it? ==<br />
<br />
Well, Foldable cannot just be given by toList, much as we might think of it as such. foldMap lets us fold over not only potentially right-infinite structures as with foldr, but potentially left-infinite ones (as with foldl) and even "both-infinite" ones such as rooted but infinitely branching trees!<br />
<br />
Other methods in the Foldable class, such as foldl and foldr exist for historical reasons, and to allow the possibility of more efficient implementations. Sum, product, maximum, and minimum were added because their prelude versions were performed with a foldl, while their general versions with a foldMap. Moving them into the class allowed Prelude behaviour to be preserved in the case of lists without altering behaviour otherwise in the case of other structures. This has led to the one semantic change in the FTP -- now that these Foldable methods on lists are in accord with the Prelude specification, this means that (unavoidably) their Foldable methods on lists have now changed behaviour.<br />
<br />
Finally, toList and elem were pulled into the class and length and null were added to both the module and the class because they permit potentially more efficient implementations on many structures (with null and length being sometimes, for example O(1)), and it seemed desirable to allow users to take advantage of this asymptotically more efficient behaviour.<br />
<br />
== Now I'm getting unused import warnings. Help? ==<br />
<br />
Suppose your code had <code>import Foldable</code> in it, but you only used things that are now available from the prelude. After the FTP you'll be getting unused import warnings.<br />
<br />
You can go delete the import, but now your code doesn't work for pre-FTP versions! There is a trick to avoid these warnings while remaining compatible across versions. <br />
<br />
Stick <code>import Prelude</code> at the '''bottom''' of your imports list.<br />
<br />
This works because GHC checks that the imports provide something "new" that is used by the module in a top-down fashion, and you are almost certainly using something from Prelude that didn't come from one of the modules above.<br />
<br />
[[Category:FAQ]]<br />
[[Category:How to]]</div>Hvrhttps://wiki.haskell.org/index.php?title=Core_Libraries_Committee&diff=57982Core Libraries Committee2014-04-29T10:08:54Z<p>Hvr: /* Current members */ Add note about GitHub Team</p>
<hr />
<div>To contact the Haskell Core Libraries Committee, send email to '''core-libraries-committee [AT] haskell.org'''. <br />
<br />
== Responsibilities ==<br />
<br />
The [[Core Libraries Committee]] acts as the ''Maintainer'' per the [[Library submissions]] guidelines for many of the core libraries that make up the Haskell Platform.<br />
<br />
== Current members ==<br />
<br />
* Edward Kmett (chair)<br />
* Brent Yorgey<br />
* Dan Doel<br />
* Michael Snoyman<br />
* Doug Beardsley<br />
* Joachim Breitner<br />
* Mark Lentczner (ex-officio as the Haskell Platform Maintainer)<br />
<br />
e-mail: core-libraries-committee [AT] haskell.org<br />
<br />
GitHub: The [https://github.com/orgs/haskell/teams/core-libraries-committee Core Libraries Committee Team] can be mentioned/notified in GitHub conversations by using the syntax <code>@haskell/core-libraries-committee</code>.<br />
<br />
== Operation ==<br />
<br />
The committee consists of 7 members. Members are expected to serve a 3 year term, and terms are staggered so that 2 members step down each year, at the end of June.<br />
<br />
The members will elect one of their number to be chair each year. The chair is responsible for making sure that things keep moving, and to ensure that a conclusion is reached on any issues raised.<br />
<br />
When a member steps down, either because they have reached the end of their term or because other circumstances require them to step down early, open self-nominations will be sought from the community via the libraries@ mailing list. Previous committee members, including those who have just stepped down, will also be eligible for nomination.<br />
<br />
The committee will then select a replacement from amongst those nominated. For the purposes of considering nominations, the committee will include any outgoing members who are not seeking re-appointment.<br />
<br />
The committee replacement process is intentionally currently very light. As we get more experience, we may wish to change it, e.g. by having a larger subset of "the community" vote on nominations.<br />
<br />
If any member of the community wishes to raise any issue with the committee, they may contact it by e-mailing core-libraries-committee [AT] haskell.org.<br />
<br />
It is expected the committee will discuss any matters brought to it amongst themselves, and if they think appropriate, with the wider community, to try to reach consensus. Ultimately, the committee will make decisions by more than half of the membership voting for a particular outcome. These rules of operation may also be changed in the same way.<br />
<br />
[[Category:Community]]</div>Hvrhttps://wiki.haskell.org/index.php?title=GHC&diff=55617GHC2013-03-30T10:52:45Z<p>Hvr: add link to memory-footprint wiki page</p>
<hr />
<div>The '''Glasgow Haskell Compiler''' is a state-of-the-art, open source compiler and interactive environment for the functional language Haskell.<br />
<br />
* [http://www.haskell.org/ghc/ The GHC Home Page]<br />
<br />
== Documentation ==<br />
<br />
The documentation below relates to ''using'' GHC. For documentation about GHC's internals and building GHC, head over to the [http://hackage.haskell.org/trac/ghc GHC Developer Wiki].<br />
<br />
These documents relate to the ''latest released'' version of GHC.<br />
For ''earlier released'' versions click the relevant version on the<br />
[http://www.haskell.org/ghc/download.html downloads page]. <br />
For the the ''current HEAD snapshot'' look at <br />
[http://www.haskell.org/ghc/download.html#snapshots development snapshots].<br />
<br />
<br />
; [http://www.haskell.org/ghc/docs/latest/html/users_guide/index.html The User's Guide]: The User's Guide has all you need to know about using GHC: command line options, language extensions, GHCi, etc.<br />
: Download: | [http://www.haskell.org/ghc/docs/latest/users_guide.html.tar.bz2 HTML.tar.bz2] | [http://www.haskell.org/ghc/docs/latest/users_guide.pdf PDF] | [http://www.haskell.org/ghc/docs/latest/users_guide.ps PS] |<br />
<br />
; [http://www.haskell.org/ghc/docs/latest/html/libraries/index.html Standard Libraries]: Documentation for the libraries that come with GHC.<br />
: Download: | [http://www.haskell.org/ghc/docs/latest/libraries.html.tar.bz2 HTML.tar.bz2]<br />
<br />
; [http://www.haskell.org/cabal/users-guide/ Cabal]: An infrastructure for building and distributing Haskell software.<br />
<br />
== Collaborative documentation ==<br />
<br />
GHC is a big system. We try to document the core functionality (above), but<br />
you can help by writing documentation yourself. This section collects<br />
documentation written in a collaborative way, by users and developers together.<br />
Please help by adding new sections, and by clarifying and improving existing ones.<br />
<br />
* Using GHC<br />
** [[How_to_write_a_Haskell_program|How to write a Haskell program]]<br />
** [[/FAQ|GHC FAQ]]<br />
** [[/Error messages|Error messages]]<br />
** [[Upgrading_packages|Guidelines for upgrading your GHC]]<br />
** [[/GHCi|Using GHCi]]<br />
** [[/GHCi debugger| The GHCi debugger]]<br />
** [[Cabal|Using Cabal]] (including with DLLs)<br />
** The [[Performance|Haskell Performance Resource]], for advice on improving the performance of your code<br />
** [[Mutually recursive modules]]<br />
** [[/Memory_Management| Memory management and garbage collection]]<br />
** [[/Memory Footprint|Memory footprint on the heap of common data-structures]]<br />
<br />
* Platform related matters<br />
** [[GHC under WINE|Running GHC under Wine]]<br />
** [[Mac OS X]]<br />
** [[Windows]]<br />
*** [http://haskell.forkio.com/dotnet Using GHC with .NET]<br />
*** [http://haskell.forkio.com/gmpwindows Dynamically linking GMP on Windows]<br />
<br />
* GHC extensions<br />
** [[/Type system|Type system extensions in GHC]]<br />
** [[/As a library|Using GHC as a library]]<br />
** [[/Concurrency|Concurrent programming in GHC]]<br />
** [[Template Haskell]] is a (GHC) extension to Haskell that adds compile-time metaprogramming facilities.<br />
** [[Quasiquotation]] allows the ability for user-definable parsers to provide new concrete syntax for any datatype.<br />
** [http://www.cse.unsw.edu.au/~dons/hs-plugins Dynamically loaded Haskell modules]: Don Stewart's <tt>hs-plugins</tt> library<br />
** [[/Using the FFI|Using the Foreign Function Interface]]<br />
** [[/GUI programming|GUI programming in GHC]]<br />
** [[/Using rules|Using RULES in GHC]]<br />
** [[GHC/Data Parallel Haskell|Data Parallel Haskell: using nested data parallelism in GHC]]<br />
<br />
* [[Correctness of short cut fusion]]<br />
<br />
== Development of GHC ==<br />
<br />
See the [http://hackage.haskell.org/trac/ghc GHC Developer Wiki]. The latest snapshot of the documentation for the next version can be found [http://haskell.org/ghc/dist/current/docs/ here].<br />
<br />
* [[/SIMD|SIMD CPU operations]]<br />
<br />
[[Category:Implementations]]<br />
[[Category:GHC]]</div>Hvrhttps://wiki.haskell.org/index.php?title=GHC/Memory_Footprint&diff=42032GHC/Memory Footprint2011-09-10T12:25:37Z<p>Hvr: /* Basic Types */</p>
<hr />
<div>This page is concerned with the memory footprint of Haskell data structures stored in the heap.<br />
<br />
The heap is the garbage collected area of memory in which the running program introduces heap nodes.<br />
<br />
An in-depth explaination of the GHC internals can be found in the[http://hackage.haskell.org/trac/ghc/wiki/Commentary/Rts/Storage/HeapObjects GHC Commentary: The Layout of Heap Objects].<br />
<br />
A good introduction on how to compute the size of Haskell datastructures can be found in Johan Tibell's [http://blog.johantibell.com/2011/06/computing-size-of-hashmap.html Computing the size of a HashMap].<br />
<br />
== Memory Footprints of common data types ==<br />
<br />
See also [http://blog.johantibell.com/2011/06/memory-footprints-of-some-common-data.html Memory footprints of some common data types] which is the origin of the table below.<br />
<br />
The following tables assumes fully evaluated data structures (i.e. no thunks)<br />
<br />
A "word" is 4 bytes on 32bit archs, and 8 bytes on 64bit archs. Sizes are usually rounded up to word-boundaries.<br />
<br />
Constructors with no fields are instantiated only once on the heap. This is expressed in the sizeof()-formulas below with italic numbers which can be ignored for practical considerations.<br />
<br />
=== Basic Types ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! Data type<br />
! sizeof(T)<br />
! Notes<br />
|-<br />
| ()<br />
| ''1'' word<br />
| single shared ()<br />
|-<br />
| Bool<br />
| ''1'' word<br />
| single shared True/False<br />
|-<br />
| Char<br />
| 2 words<br />
| Char-sharing pool<br />
|-<br />
| Int<br />
| 2 words<br />
|-<br />
| Int64 (on 64bit arch) <br />
| 2 words<br />
|-<br />
| Int64 (on 32bit arch) <br />
| 3 words<br />
|-<br />
| Double (on 64bit arch) <br />
| 2 words<br />
|-<br />
| Double (on 32bit arch) <br />
| 3 words<br />
|-<br />
| Integer (small)<br />
| 2 words<br />
|-<br />
| Integer (bignum rep.)<br />
| 3 words + sizeof(bignum-repr)<br />
| FIXME<br />
|}<br />
<br />
=== Container Types ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! Data type<br />
! sizeof(T)<br />
! Notes<br />
|-<br />
| (va,vb)<br />
| 3 words + sizeof(va) + sizeof(vb)<br />
|-<br />
| [v]<br />
| (''1'' + 3N) words + sizeof(N v)<br />
| [] is singleton<br />
|-<br />
| Data.ByteString<br />
| 9 words + N bytes <br />
|-<br />
| Data.Text<br />
| 6 words + 2N bytes<br />
|- <br />
| Data.Map k v<br />
| 6N words + sizeof(N k + N v)<br />
|-<br />
| Data.Set v<br />
| 5N words + sizeof(N v)<br />
|-<br />
| Data.IntMap v<br />
| (3N + 5(N-1) words) + sizeof(v)<br />
|-<br />
| Data.IntSet<br />
| (2N + 5(N-1)) words<br />
|-<br />
| Data.HashMap k v<br />
| (5N + 4(N-1)) words + sizeof(N k + N v)<br />
| non-HAMT impl.<br />
|-<br />
| Data.HashSet<br />
| (5N + 4(N-1)) words + sizeof(N v)<br />
|-<br />
| Data.Vector v<br />
| (4 + (2+N)) words + sizeof(N v)<br />
| ''O(1)'' slicing shares Array#<br />
|}</div>Hvrhttps://wiki.haskell.org/index.php?title=GHC/Memory_Footprint&diff=42031GHC/Memory Footprint2011-09-10T12:24:26Z<p>Hvr: New page: This page is concerned with the memory footprint of Haskell data structures stored in the heap. The heap is the garbage collected area of memory in which the running program introduces he...</p>
<hr />
<div>This page is concerned with the memory footprint of Haskell data structures stored in the heap.<br />
<br />
The heap is the garbage collected area of memory in which the running program introduces heap nodes.<br />
<br />
An in-depth explaination of the GHC internals can be found in the[http://hackage.haskell.org/trac/ghc/wiki/Commentary/Rts/Storage/HeapObjects GHC Commentary: The Layout of Heap Objects].<br />
<br />
A good introduction on how to compute the size of Haskell datastructures can be found in Johan Tibell's [http://blog.johantibell.com/2011/06/computing-size-of-hashmap.html Computing the size of a HashMap].<br />
<br />
== Memory Footprints of common data types ==<br />
<br />
See also [http://blog.johantibell.com/2011/06/memory-footprints-of-some-common-data.html Memory footprints of some common data types] which is the origin of the table below.<br />
<br />
The following tables assumes fully evaluated data structures (i.e. no thunks)<br />
<br />
A "word" is 4 bytes on 32bit archs, and 8 bytes on 64bit archs. Sizes are usually rounded up to word-boundaries.<br />
<br />
Constructors with no fields are instantiated only once on the heap. This is expressed in the sizeof()-formulas below with italic numbers which can be ignored for practical considerations.<br />
<br />
=== Basic Types ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! Data type<br />
! sizeof(T)<br />
! Notes<br />
|-<br />
| ()<br />
| ''1'' word<br />
| single shared ()<br />
|-<br />
| Bool<br />
| ''1'' word<br />
| single shared True/False<br />
|-<br />
| Char<br />
| 2 words<br />
| Char-sharing pool<br />
|-<br />
| Int<br />
| 2 words<br />
|-<br />
| Int64 (on 64bit arch) <br />
| 2 words<br />
|-<br />
| Int64 (on 32bit arch) <br />
| 3 words<br />
|-<br />
| Integer (small)<br />
| 2 words<br />
|-<br />
| Integer (bignum rep.)<br />
| 3 words + sizeof(bignum-repr)<br />
| FIXME<br />
|}<br />
<br />
=== Container Types ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! Data type<br />
! sizeof(T)<br />
! Notes<br />
|-<br />
| (va,vb)<br />
| 3 words + sizeof(va) + sizeof(vb)<br />
|-<br />
| [v]<br />
| (''1'' + 3N) words + sizeof(N v)<br />
| [] is singleton<br />
|-<br />
| Data.ByteString<br />
| 9 words + N bytes <br />
|-<br />
| Data.Text<br />
| 6 words + 2N bytes<br />
|- <br />
| Data.Map k v<br />
| 6N words + sizeof(N k + N v)<br />
|-<br />
| Data.Set v<br />
| 5N words + sizeof(N v)<br />
|-<br />
| Data.IntMap v<br />
| (3N + 5(N-1) words) + sizeof(v)<br />
|-<br />
| Data.IntSet<br />
| (2N + 5(N-1)) words<br />
|-<br />
| Data.HashMap k v<br />
| (5N + 4(N-1)) words + sizeof(N k + N v)<br />
| non-HAMT impl.<br />
|-<br />
| Data.HashSet<br />
| (5N + 4(N-1)) words + sizeof(N v)<br />
|-<br />
| Data.Vector v<br />
| (4 + (2+N)) words + sizeof(N v)<br />
| ''O(1)'' slicing shares Array#<br />
|}</div>Hvrhttps://wiki.haskell.org/index.php?title=Haskell_mode_for_Emacs&diff=39507Haskell mode for Emacs2011-04-19T12:57:48Z<p>Hvr: Add hint about using Scion with Emacs</p>
<hr />
<div>haskell-mode is a major mode for Emacs and XEmacs specifically for writing Haskell code. You can get haskell-mode from the web page: http://projects.haskell.org/haskellmode-emacs/ or on Debian you can type <code>apt-get install haskell-mode</code> (although this currently doesn't have the latest version). It is currently maintained by Svein Ove Aas[http://www.mail-archive.com/haskell-cafe@haskell.org/msg66300.html].<br />
<br />
<br />
<br />
<br />
==Development Version==<br />
<br />
<code><br />
$ darcs get http://code.haskell.org/haskellmode-emacs/<br />
</code><br />
<br />
See also [http://trac.haskell.org/haskellmode-emacs/report/1 Active Tickets] in bug tracker.<br />
<br />
==Setup==<br />
<br />
Download and unpack the basic mode and modules into a suitable directory, e.g. <code>~/lib/emacs/haskell-mode/</code> where <code>~</code> stands for your home directory.<br />
<br />
Assuming you have placed the basic mode haskell-mode.el and the modules you want to use in the directory <code>~/lib/emacs/haskell-mode/</code>, add the following command to your init file (<code>~/.emacs</code>):<br />
<br />
<code><br />
(load "~/lib/emacs/haskell-mode/haskell-site-file")<br />
</code><br />
<br />
adding the following lines according to which modules you want to use:<br />
<br />
<code><br />
(add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)<br />
(add-hook 'haskell-mode-hook 'turn-on-haskell-indentation)<br />
;;(add-hook 'haskell-mode-hook 'turn-on-haskell-indent)<br />
;;(add-hook 'haskell-mode-hook 'turn-on-haskell-simple-indent)<br />
</code><br />
<br />
Note that the three indentation modules are mutually exclusive - add at most one. Note that the line of code for simple indentation is commented out (using a preceding ;) in preference for the more advanced indentation module. Installation is now complete!<br />
<br />
==== Inferior Mode ====<br />
<br />
Normally, inf-haskell automatically finds ghci or hugs in your <code>PATH</code>, but if that's not the case (common under Windows), or if you need to specify your preference, just tell Emacs which executable to use with:<br />
<br />
<code><br />
(setq haskell-program-name "/some/where/ghci.exe")<br />
</code><br />
<br />
If you want to use different settings when you use Cygwin Emacs and NTEmacs,<br />
you can test the value of `system-type':<br />
<br />
<code><br />
(setq haskell-program-name<br />
(if (eq system-type 'cygwin)<br />
"/cygdrive/c/ghc/ghc-6.8.1/bin/ghcii.sh"<br />
"c:/ghc/ghc-6.8.1/bin/ghci.exe"))<br />
</code><br />
<br />
Note that Cygwin binaries tend to interact poorly with NTEmacs, especially<br />
w.r.t signal-handling.<br />
<br />
==Tips and use==<br />
Handy keybindings in haskell-mode. See the documentation <code>C-h m</code> for more information:<br />
*<code>C-c C-=</code> inserts an = sign and lines up type signatures and other pattern matches nicely.<br />
*<code>C-c C-|</code> inserts a guard<br />
*<code>C-c C-o</code> inserts a guard <hask>| otherwise =</hask> and lines up existing guards<br />
*<code>C-c C-w</code> inserts a where keyword<br />
*<code>C-c C-.</code> aligns code over a region in a "sensible" fashion.<br />
<br />
Now in version 2.2:<br />
*<code>C-c C-t</code> gets :type for symbol at point, and remembers it<br />
*<code>C-u C-c C-t</code> inserts a type annotation, for symbol at point, on the line above<br />
*<code>C-c C-i</code> gets :info for symbol at point<br />
*<code>C-c M-.</code> find definition of (interpreted) symbol at point<br />
<br />
(See the section below on [[#inf-haskell.el:_the_best_thing_since_the_breadknife|inf-haskell]].)<br />
<br />
Here's an example for <code>C-c C-=</code>. Put your cursor after myInt and hit <code>C-c C-=</code><br />
<haskell><br />
blah :: Int -> Int<br />
blah myInt<br />
</haskell><br />
note how the function signature is reindented to match the column of the = sign.<br />
<haskell><br />
blah :: Int -> Int<br />
blah myInt =<br />
</haskell><br />
<br />
You could also achieve the same effect by selecting the region and typing <code>C-c C-.</code><br />
<br />
You can also use Haskell-Mode to load Emacs buffers with Haskell code in either Hugs or GHC. To load something in Hugs or ghci, type <code>C-c C-l</code> to load the file. Then, you can go on to type <code>C-c C-r</code> (or simply <code>C-c C-l</code> again) to reload the current module when you have made a change.<br />
<br />
=== Indentation ===<br />
Indentation is one thing that nearly all programming modes provide. However, indenting Haskell code is very hard: for a given line, there are nearly always more than column for which indentation makes sense. For example, imagine the following is open in a haskell-mode buffer, where <code>!</code> represents the point:<br />
<br />
<haskell><br />
foo :: Int -> String<br />
foo 0 = f 4 ++ s<br />
where f 4 = "hello" ++ <br />
!<br />
</haskell><br />
<br />
If you ask haskell-mode to indent for you, where should it indent to? There are four basic options:<br />
<br />
<ol><br />
<li><br />
You want to finish off the expression you were writing in the last line. Haskell-mode indents to be underneath the <code>"</code> character at the beginning of <code>"hello"</code>:<br />
<br />
<haskell><br />
where f 4 = "hello" ++<br />
!<br />
</haskell><br />
<br />
This is debatably a bad choice as you'd probably want to indent a bit further in to make it clear that you were carrying on an expression, but the layout rule would accept something like the following:<br />
<br />
<haskell><br />
where f 4 = "hello" ++<br />
"world"<br />
</haskell><br />
<br />
</li><br />
<li><br />
You want to add a second equation for <code>f</code>. Haskell-mode will indent to line up with the first argument, and fill in the <code>f</code> in the equation:<br />
<br />
<haskell><br />
where f 4 = "hello" ++<br />
f !<br />
</haskell><br />
<br />
This is an unlikely choice as the expression in the previous line isn't complete, but haskell-mode isn't smart enough to know that. (If <code>f</code> had been something without arguments, like <hask>where f = "hello"</hask>, then it's impossible to have more than one equation and haskell-mode won't offer this indentation level.)<br />
</li><br />
<li><br />
You want to add a second binding to the <code>where</code>-block. Haskell-mode indents to line up with the <code>f</code>:<br />
<br />
<haskell><br />
where f 4 = "hello" ++<br />
!<br />
</haskell><br />
<br />
</li><br />
<li>You want to start an entirely new top-level binding. Haskell-mode indents to the first column:<br />
<br />
<haskell><br />
foo :: Int -> String<br />
foo 0 = f 4 ++ s<br />
where f 4 = "hello" ++<br />
!<br />
</haskell><br />
<br />
</li><br />
</ol><br />
<br />
These four locations can be reached by repeatedly pressing <code>TAB</code>. This is what's known as the tab-cycle. The innermost location is offered first, then cycling progresses outwards. Although this may seem like an inefficient system (and it is indeed a shame that Haskell's design didn't result in an unambiguous indentation system), you do quickly get used to the tab-cycle and indenting Haskell code.<br />
<br />
==== indent-region ====<br />
Using indent-region is generally a bad idea on Haskell code, because it would need to know which of the tab-cycle stops you wish to choose for each line. The innermost one is chosen in each case, which often results in unusable code. Moral: just don't use indent-region with haskell-mode.<br />
<br />
==== Unicodifying symbols (Pretty Lambda for Haskell-mode) ====<br />
In Haskell code, you can end up using a lot of mathematical symbols. It is possible to hack the fontifying features of Emacs to change the ASCII textual representations of arrows and operators into the nice-looking real symbols, much like you could with TeX. The following code is a compilation of Emacs lisp code found on the Emacs wiki on the [http://www.emacswiki.org/cgi-bin/wiki/PrettyLambda#toc4 Pretty Lambda] page (that page also has examples of how to apply the general Unicode defuns to other languages):<br />
<br />
HOWEVER: due to the symbols taking up less space, this has the unfortunate side effect of changing the indentation stops that the indent key offers. This will mean that your code may not look properly aligned to those who do not have this feature in their editor, or could even mean that your code means something different to how it looks. (It is possible to contrive an example that looks correct in emacs, but actually fails to compile). The following is left for interest, but probably should NOT be used.<br />
<br />
Haskell-mode has included this feature for a long time now, so you probably just need to <code>(setq haskell-font-lock-symbols t)</code> in your .emacs to use this feature.<br />
<br />
<code><br />
(defun unicode-symbol (name)<br />
"Translate a symbolic name for a Unicode character -- e.g., LEFT-ARROW <br />
or GREATER-THAN into an actual Unicode character code. "<br />
(decode-char 'ucs (case name <br />
(left-arrow 8592)<br />
(up-arrow 8593)<br />
(right-arrow 8594)<br />
(down-arrow 8595) <br />
(double-vertical-bar #X2551) <br />
(equal #X003d)<br />
(not-equal #X2260)<br />
(identical #X2261)<br />
(not-identical #X2262)<br />
(less-than #X003c)<br />
(greater-than #X003e)<br />
(less-than-or-equal-to #X2264)<br />
(greater-than-or-equal-to #X2265) <br />
(logical-and #X2227)<br />
(logical-or #X2228)<br />
(logical-neg #X00AC) <br />
('nil #X2205)<br />
(horizontal-ellipsis #X2026)<br />
(double-exclamation #X203C)<br />
(prime #X2032)<br />
(double-prime #X2033)<br />
(for-all #X2200)<br />
(there-exists #X2203)<br />
(element-of #X2208) <br />
(square-root #X221A)<br />
(squared #X00B2)<br />
(cubed #X00B3) <br />
(lambda #X03BB)<br />
(alpha #X03B1)<br />
(beta #X03B2)<br />
(gamma #X03B3)<br />
(delta #X03B4))))<br />
<br />
(defun substitute-pattern-with-unicode (pattern symbol)<br />
"Add a font lock hook to replace the matched part of PATTERN with the <br />
Unicode symbol SYMBOL looked up with UNICODE-SYMBOL."<br />
(font-lock-add-keywords<br />
nil `((,pattern <br />
(0 (progn (compose-region (match-beginning 1) (match-end 1)<br />
,(unicode-symbol symbol)<br />
'decompose-region)<br />
nil))))))<br />
<br />
(defun substitute-patterns-with-unicode (patterns)<br />
"Call SUBSTITUTE-PATTERN-WITH-UNICODE repeatedly."<br />
(mapcar #'(lambda (x)<br />
(substitute-pattern-with-unicode (car x)<br />
(cdr x)))<br />
patterns))<br />
<br />
(defun haskell-unicode ()<br />
(substitute-patterns-with-unicode<br />
(list (cons "\\(<-\\)" 'left-arrow)<br />
(cons "\\(->\\)" 'right-arrow)<br />
(cons "\\(==\\)" 'identical)<br />
(cons "\\(/=\\)" 'not-identical)<br />
(cons "\\(()\\)" 'nil)<br />
(cons "\\<\\(sqrt\\)\\>" 'square-root)<br />
(cons "\\(&&\\)" 'logical-and)<br />
(cons "\\(||\\)" 'logical-or)<br />
(cons "\\<\\(not\\)\\>" 'logical-neg)<br />
(cons "\\(>\\)\\[^=\\]" 'greater-than)<br />
(cons "\\(<\\)\\[^=\\]" 'less-than)<br />
(cons "\\(>=\\)" 'greater-than-or-equal-to)<br />
(cons "\\(<=\\)" 'less-than-or-equal-to)<br />
(cons "\\<\\(alpha\\)\\>" 'alpha)<br />
(cons "\\<\\(beta\\)\\>" 'beta)<br />
(cons "\\<\\(gamma\\)\\>" 'gamma)<br />
(cons "\\<\\(delta\\)\\>" 'delta)<br />
(cons "\\(<nowiki>''</nowiki>\\)" 'double-prime)<br />
(cons "\\('\\)" 'prime)<br />
(cons "\\(!!\\)" 'double-exclamation)<br />
(cons "\\(\\.\\.\\)" 'horizontal-ellipsis))))<br />
<br />
(add-hook 'haskell-mode-hook 'haskell-unicode)</code><br />
<br />
== Bugs ==<br />
Bugs and feature requests should be sent to the maintainer [mailto:svein.ove@aas.no Svein Ove Aas].<br />
For people using the Debian package, Debian maintains a [http://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=haskell-mode list of bugs] for haskell-mode, they should be reported there.<br />
<br />
===XEmacs===<br />
On some the GNU/Linux systems with XEmacs, admittedly, only verified on Ubuntu and Debian and with haskell-mode 2.2, there is a system function missing that interferes with automatic indenting. Secondly, there seems to be an issue with setting the <code-lisp>haskell-default-face</code-lisp> to <code-lisp>nil</code-lisp>.<br />
<br />
====line-end-position====<br />
<br />
To fix this, find where the haskell mode package is installed on your system. (Usually <code>/usr/share/emacs/site-lisp/haskell-mode</code>). Edit the file <code>haskell-indent.el</code> and add the lines:<br />
<pre-lisp><br />
(eval-and-compile<br />
<br />
;; If `line-end-position' isn't available provide one.<br />
(unless (fboundp 'line-end-position)<br />
(defun line-end-position (&optional n)<br />
"Return the `point' of the end of the current line."<br />
(save-excursion<br />
(end-of-line n)<br />
(point)))))<br />
</pre-lisp><br />
right after the comments at the top. That should fix the issue.<br />
<br />
====haskell-default-face====<br />
<br />
This one shows up when typing in code (at various spots - most often when typing a qualified function, such as <hask>List.map</hask>.)<br />
<br />
To fix this one, edit the file <code>haskell-font-lock.el</code>. Look for the line that says:<br />
<pre-lisp><br />
(defvar haskell-default-face nil)<br />
</pre-lisp><br />
and change this to <br />
<pre-lisp><br />
(defvar haskell-default-face 'default)<br />
</pre-lisp><br />
In my version, this is line 168.<br />
<br />
Then, look for the line that says:<br />
<pre-lisp><br />
(,qvarid 0 haskell-default-face)<br />
</pre-lisp><br />
and change it to<br />
<pre-lisp><br />
(,qvarid 0 (symbol-value 'haskell-default-face))<br />
</pre-lisp><br />
<br />
For me, this is line 326 of the file.<br />
YMMV - hope this helps.<br />
<br />
<!--<br />
=== GNU Emacs ===<br />
<br />
==== ghci buffer infested with "^J"s, C-c C-t doesn't work ====<br />
<br />
(only happens after loading a haskell file into ghci)<br />
<br />
--><br />
<br />
<br />
== inf-haskell.el: the best thing since the breadknife ==<br />
inf-haskell.el is _awesome_. At one point I decided to sit down and write a list of functions I'd love to have in haskell-mode, intending to write them myself. I thought I'd check to see whether the key shortcuts I'd chosen were free but I was surprised to find that ''every one'' of these functions is already provided by inf-haskell.el! Here's a selection of the highlights:<br />
<br />
=== Getting set up ===<br />
inf-haskell.el is usually already setup as part of the haskell-mode package, so there is nothing special to do for it. On some systems, you may need this in your .emacs:<br />
<br />
<pre-lisp><br />
(require 'inf-haskell)<br />
</pre-lisp><br />
<br />
To use the following functions, first find a .hs file, then hit C-c C-l (inferior-haskell-load-file). This fires up Hugs or Ghci (you can change this by customising haskell-program-name) on your file. Don't worry if it's not an isolated module, GHCi will load all the modules it imports as normal. You can even load entire programs this way by using C-c C-l on the Main.hs file. If everything loads without errors, you'll be able to use the functions below.<br />
<br />
=== inferior-haskell-type (C-c C-t) ===<br />
Say you have the following code:<br />
<br />
foo = foldr (+) 0 [1..20]<br />
<br />
Perhaps you've forgotten the order of arguments to foldr. It's easily done; I can never remember whether the operation or final value comes first. That's easy to check: just put your point between the 'f' and 'r' of 'foldr' and hit C-c C-t RET. The type of foldr will be revealed in the echo area. This isn't particularly impressive; haskell-doc.el already did this. However, this will work for ''any'' function in the module in question ''or'' in those modules imported by the current module (including the standard libs)!<br />
<br />
If you find that the type shown in the echo area is overwritten after a short amount of time (or any other such problem, of course), please report it as a bug. We know of no such bug, but someone apparently bumped into some such problem which he says he worked around by disabling doc-mode and decl-scan:<br />
<br />
To turn off haskell-doc-mode, add the following to your .emacs:<br />
<pre-lisp><br />
(remove-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)<br />
</pre-lisp><br />
To turn off haskell-decl-scan, just refrain from turning it on (it's not enabled by default).<br />
<br />
(P.S. I re-use haskell-doc-mode to save queried type info, and re-display it in the minibuffer. Disabling doc mode would disable that. -- mrd)<br />
<br />
Another nice feature of this function is the ability to automatically insert type signatures for the function at point on the line above. For example, suppose you have the below open in Emacs, with the point represented by -!-:<br />
<br />
-!-map _ [] = []<br />
map f (x:xs) = f x : map f xs<br />
<br />
And press C-u C-c C-t (note the prefix argument), it will result in the following:<br />
<br />
map :: (a -> b) -> [a] -> [b]<br />
-!-map _ [] = []<br />
map f (x:xs) = f x : map f xs<br />
<br />
=== inferior-haskell-info (C-c C-i) ===<br />
The :info command in GHCi/Hugs is extremely useful; it'll tell you:<br />
<br />
* The definition of an algebraic datatype given its name. E.g. try <code>:info Bool</code>. The output will contain something like <code>data Bool = True | False</code>.<br />
* The classes a type instantiates given the type's name. <code>:info Bool</code> will also give you the classes Bool instantiates. If you can't see an instance you think should be there, make sure the module where that instance is declared is loaded.<br />
* The type of a function, given its name.<br />
* The types of the methods of a class, and the number of arguments of that class, given the class name.<br />
* The expansion of a type synonym given that synonym's name.<br />
<br />
And for all of the above, :info will also tell you the filename and line where that thing is defined. inferior-haskell-info lets you hook into this power. Use it with C-c C-i on anything within a Haskell file.<br />
<br />
=== inferior-haskell-find-definition (C-c M-.) ===<br />
This one needs little explanation. Sometimes you just need to find the source of a function, or datatype, or class, or type synonym etc. to see how it works, and this function lets you do just that. Unfortunately, it won't work on the standard lib modules or anything that isn't 'local' to your project. This is one of the most useful functions inf-haskell.el provides.<br />
<br />
(Basically, it only works on interpreted code, for which ghci has location information. If you want a more general find-definition, use hasktags to create a TAGS file and then use the normal emacs <code>M-.</code> with that. -- mrd)<br />
: Note that you can also create a TAGS file using GHCi's :etags command. [[User:DavidHouse|DavidHouse]] 14:38, 29 April 2007 (UTC)<br />
<br />
: Again, :etags/:ctags only works for interpreted code.<br />
<br />
: <code>inferior-haskell-mode</code> is missing TAB completion, which in GHCi works basically for everything (GHCi commands, modules, functions, language extensions, file names etc.). -- Oleksandr Manzyuk<br />
<br />
== Tricks and tweaks ==<br />
<br />
=== Automatic unit testing ===<br />
Here's a cute trick I've evolved:<br />
<br />
I'm a great fan of [[unit test first]], as described by eXtremeProgramming on TheOriginalWiki.<br />
<br />
With the code below, I can press F12 and immediately run all of my unit tests, and immediately see whether they all passed or not.<br />
I've put all of my unit tests into their own file with a main function that runs the tests and gives an exitcode according to the test results. I've specified that the compile-command for that file compiles and runs the file.<br />
<br />
This elisp code will run the <code>compile</code> command from the F12 key in emacs. The output will popup a new window twelve lines tall. If the compilation is successful (exitcode zero) the window goes away. If the exitcode is 1 or greater, the window stays so you can see the output.<br />
<pre-lisp><br />
(require 'compile)<br />
<br />
;; this means hitting the compile button always saves the buffer<br />
;; having to separately hit C-x C-s is a waste of time<br />
(setq mode-compile-always-save-buffer-p t)<br />
;; make the compile window stick at 12 lines tall<br />
(setq compilation-window-height 12)<br />
<br />
;; from enberg on #emacs<br />
;; if the compilation has a zero exit code, <br />
;; the windows disappears after two seconds<br />
;; otherwise it stays<br />
(setq compilation-finish-function<br />
(lambda (buf str)<br />
(unless (string-match "exited abnormally" str)<br />
;;no errors, make the compilation window go away in a few seconds<br />
(run-at-time<br />
"2 sec" nil 'delete-windows-on<br />
(get-buffer-create "*compilation*"))<br />
(message "No Compilation Errors!"))))<br />
<br />
<br />
;; one-button testing, tada!<br />
(global-set-key [f12] 'compile)<br />
</pre-lisp><br />
<br />
<br />
This Haskell code has some Emacs local variable settings at the bottom specifying what the compile-command should be for this buffer.<br />
<haskell><br />
import HUnit<br />
import System<br />
<br />
myTestList = <br />
TestList [<br />
"add numbers" ~: 5 ~=? (3 + 2)<br />
,"add numbers" ~: 5 ~=? (3 + 3)<br />
]<br />
<br />
h = runTestTT myTestList<br />
<br />
main = do c <- h<br />
putStr $ show c<br />
let errs = errors c<br />
fails = failures c<br />
System.exitWith (codeGet errs fails)<br />
<br />
codeGet errs fails<br />
| fails > 0 = ExitFailure 2<br />
| errs > 0 = ExitFailure 1<br />
| otherwise = ExitSuccess<br />
<br />
-- Local Variables:<br />
-- compile-command: "ghc --make -o Test_Demo -i/home/shae/src/haskell/libraries/ HUnitDemo.hs && ./Test_Demo"<br />
-- End:<br />
</haskell><br />
<br />
<br />
If you have any questions, ideas, or suggestions for this code, the maintainer would love to hear them.<br />
<br />
=== Hoogle integration ===<br />
From haskell-mode version 2.4 onwards, the built-in function haskell-hoogle will hoogle the identifier at point.<br />
<br />
=== Using rectangular region commands ===<br />
<br />
Emacs has a set of commands which operate on the region as if it were rectangular. This turns out to be extremely useful when dealing with whitespace sensitive languages.<br />
<br />
<code>C-x r o</code> is "Open Rectangle". It will shift any text within the rectangle to the right side. Also see:<br />
<br />
<code>C-x r t</code> is "String Rectangle". It will shift any text within the rectangle over to the right, and insert a given string prefixing all the lines in the region. If comment-region didn't already exist, you could use this instead, for example.<br />
<br />
<code>C-x r d</code> is "Delete Rectangle". It will delete the contents of the rectangle and move anything on the right over.<br />
<br />
<code>C-x r r</code> is "Copy Rectangle to Register". It will prompt you for a register number so it can save it for later.<br />
<br />
<code>C-x r g</code> is "Insert register". This will insert the contents of the given register, overwriting whatever happens to be within the target rectangle. (So make room)<br />
<br />
<code>C-x r k</code> is "Kill rectangle". Delete rectangle and save contents for:<br />
<br />
<code>C-x r y</code> is "Yank rectangle". This will insert the contents of<br />
the last killed rectangle.<br />
<br />
As with all Emacs modifier combos, you can type <code>C-x r C-h</code> to find out what keys are bound beginning with the <code>C-x r</code> prefix.<br />
<br />
=== Aligning code ===<br />
<br />
Emacs22 has a neat tool called: align-regexp. Select a region you want to align text within, M-x align-regexp, and type a regexp representing the alignment delimiter.<br />
<br />
For example, I often line up my Haddock comments:<br />
<br />
<haskell><br />
f :: a -- ^ does a<br />
-> Foo b -- ^ and b<br />
-> c -- ^ to c<br />
</haskell><br />
<br />
Select the region, and let the regexp be: <code>--</code><br />
<br />
<haskell><br />
f :: a -- ^ does a<br />
-> Foo b -- ^ and b<br />
-> c -- ^ to c<br />
</haskell><br />
<br />
Of course, this works for just about anything. Personally, I've globally bound it to <code>C-x a r</code>:<br />
<br />
<code>(global-set-key (kbd "C-x a r") 'align-regexp)</code>.<br />
<br />
=== Automatically building ===<br />
Emacs 21 has a package that can be installed (included by default in 22 and up) called 'FlyMake'; the idea is that as you are editing away, it occasionally calls the interpreter/compiler automatically and keeps track of whether the code works or not. You can fairly easily get it to work for Haskell as well; see [http://www.emacswiki.org/cgi-bin/wiki/FlymakeHaskell FlymakeHaskell] on the Emacs wiki.<br />
<br />
=== Emacs Integration with Hayoo ===<br />
<br />
My newly installed system would not allow me to hoogle what I wanted (no xmonad or xmonadcontrib in hoogle) so someone suggested Hayoo.<br />
<br />
<code><br />
(define-key haskell-mode-map (kbd "<f3>")<br />
(lambda ()<br />
(interactive)<br />
(browse-url (format "http://holumbus.fh-wedel.de/hayoo/hayoo.html?query=%s&start"<br />
(region-or-word-at-point)))))<br />
</code><br />
<br />
region-or-word-at-point is available in the thing-at-pt+.el library.<br />
<br />
Added 22-12-2008 - Promt for hayoo word<br />
<br />
<code><br />
(defun rgr/hayoo()<br />
(interactive)<br />
(let* ((default (region-or-word-at-point))<br />
(term (read-string (format "Hayoo for the following phrase (%s): "<br />
default))))<br />
(let ((term (if (zerop (length term)) default term)))<br />
(browse-url (format "http://holumbus.fh-wedel.de/hayoo/hayoo.html?query=%s&start" term)))))<br />
<br />
<br />
(define-key haskell-mode-map (kbd "<f3>") 'rgr/hayoo)<br />
</code><br />
<br />
Alternatively use the excellent browse-apropos-url stuff:<br />
<br />
http://www.emacswiki.org/emacs/BrowseAproposURL#toc6<br />
<br />
[http://richardriley.net Richard]<br />
<br />
Note: Using and URL like this should work too and will give better results (not yet tested as I'm not an emacs user):<br />
<br />
<code><br />
http://holumbus.fh-wedel.de/hayoo/hayoo.html?query=%s<br />
</code><br />
<br />
[[User:Tbh|Tbh]] 00:56, 25 January 2009 (UTC)<br />
<br />
=== Integration with HLint ===<br />
<br />
[http://www-users.cs.york.ac.uk/~ndm/hlint/ HLint] could be used directly from Emacs buffer. There is [http://www.cs.york.ac.uk/fp/darcs/hlint/data/hs-lint.el hs-lint.el] package (in HLint distribution, in the data subdirectory), that allows user to run HLint and navigate through errors, or apply suggestions to the source code.<br />
<br />
This package implements `hs-lint` command, that behaves differently depending on settings. If the `hs-lint-replace-with-suggestions` variable is set to `t`, then it will ask user and apply concrete suggested change to source code, otherwise you'll be able to navigate through list of suggestions with `next-error` command. If the `hs-lint-replace-without-ask` variable is also set to `t`, then all suggestions will applied automatically. <br />
<br />
You can also bind `hs-lint` command to some key (in this example this is `C-c l`) with following code:<br />
<br />
<code><br />
(defun my-haskell-mode-hook ()<br />
(local-set-key "\C-cl" 'hs-lint))<br />
(add-hook 'haskell-mode-hook 'my-haskell-mode-hook)<br />
</code><br />
<br />
All settings, described above are available for customization via `hs-lint` customization group.<br />
<br />
[[Category:Development tools]]<br />
<br />
=== Folding ===<br />
For folding parts of code you can use<br />
*'''hide-show.el'''<br />
*and '''hs-outline-level''' (based on py-outline-level created by Gb)<br />
<br />
<code><br />
;; this gets called by outline to determine the level. Just use the length of the whitespace<br />
(defun hsk-outline-level ()<br />
(let (buffer-invisibility-spec)<br />
(save-excursion<br />
(skip-chars-forward "\t ")<br />
(current-column))))<br />
<br />
;; this get called after haskell mode is enabled <br />
(add-hook<br />
'haskell-mode-hook<br />
(lambda ()<br />
;; outline uses this regexp to find headers. I match lines with no indent and indented<br />
;; some lines, such as "--" ... "class"<br />
(setq outline-regexp "^[^\t ].*\\|^.*[\t ]+\\(where\\|of\\|do\\|in\\|if\\|then\\|else\\|let\\|module\\|import\\|deriving\\|instance\\|class\\)[\t\n ]")<br />
;; enable our level computation<br />
(setq outline-level 'hsk-outline-level)<br />
;; do not use their \C-c@ prefix, too hard to type. Note this overides some python mode bindings<br />
;;(setq outline-minor-mode-prefix "C-c")<br />
;; turn on outline mode<br />
(outline-minor-mode t)<br />
;; initially hide all but the headers<br />
;;(hide-body)<br />
))<br />
</code><br />
<br />
*Also, you can use '''toggle-selective-display''' for global folding<br />
<br />
<code><br />
;; folding for all rows, starting on the current column<br />
(defun toggle-selective-display (column)<br />
(interactive "P")<br />
(set-selective-display<br />
(or column<br />
(unless selective-display<br />
(1+ (current-column))))))<br />
<br />
(global-set-key (kbd "C-x $") 'toggle-selective-display)<br />
<br />
(defun toggle-hiding (column)<br />
(interactive "P")<br />
(if hs-minor-mode<br />
(if (condition-case nil<br />
(hs-toggle-hiding)<br />
(error t))<br />
(hs-show-all))<br />
(toggle-selective-display column)))<br />
<br />
(global-set-key (kbd "C-@") 'toggle-hiding)<br />
</code><br />
<br />
*and '''narrowing capabilities''' for folding the rest of code<br />
<code><br />
(put 'narrow-to-defun 'disabled nil)<br />
(put 'narrow-to-page 'disabled nil)<br />
(put 'narrow-to-region 'disabled nil)<br />
</code><br />
<br />
*or '''folding-mode''', if you do not mind add markers such as '''{-{{{-}''' and '''{-}}}-}''' in code.<br />
<br />
=== Speedbar ===<br />
<br />
Emacs has a [http://www.emacswiki.org/emacs/SpeedBar SpeedBar] which works quite nice together with haskell-mode and also detects syntactic elements such as variables, imports, instances, classes.<br />
<br />
Just add<br />
<code><br />
(require 'speedbar)<br />
(speedbar-add-supported-extension ".hs")<br />
</code><br />
to your .emacs file and fire up speedbar with <code>M-x speedbar</code>.<br />
<br />
=== Literate Haskell ===<br />
<br />
Literate Haskell is supported directly by haskell-mode without having to use MMM or other tricks that may be found in old mailing list postings, so ignore that out of date information. If you load an .lhs file, then literate haskell should automatically work. If it doesn't then you should make sure that you are using a current version of haskell-mode and that the correct literate type is selected. You can switch between bird (the default) and tex by typing:<br />
<br />
<code><br />
M-x customize-variable RET haskell-literate-default<br />
</code><br />
<br />
=== Keeping Imports sorted and aligned ===<br />
<br />
See this [http://www.youtube.com/watch?v=UXHSiUPKLvg&fmt=35 screencast about making imports automatically alphabetically ordered and indented].<br />
<br />
The extension modules for that can be found at https://github.com/chrisdone/haskell-mode-exts#readme<br />
<br />
=== Scion Integration ===<br />
<br />
The [http://code.google.com/p/scion-lib/ Scion IDE library] can be used to complement the haskell-mode with additional features, such as (quoting the documentation):<br />
<br />
* Highlights error messages directly in the source, together with a tool-tip<br />
* Optional on-the-fly typechecking (idle-time based, or whenever file is saved)<br />
* Completion on `LANGUAGE` names, pragmas, external module names and `OPTIONS`-flags<br />
* Go to definition sites of symbols at point<br />
<br />
Documentation on how to use `scion.el` can be found in the `README.markdown` file.<br />
<br />
The primary repository is at [https://github.com/nominolo/scion nominolo/scion]. An experimental fork featuring GHC7 support can be found at [https://github.com/hvr/scion hvr/scion]. The hackage version is probably outdated, so better use the upstream version.</div>Hvrhttps://wiki.haskell.org/index.php?title=Haskell_mode_for_Emacs&diff=39467Haskell mode for Emacs2011-04-17T06:08:06Z<p>Hvr: add link to haskell-mode-exts for sorting/indenting imports</p>
<hr />
<div>haskell-mode is a major mode for Emacs and XEmacs specifically for writing Haskell code. You can get haskell-mode from the web page: http://projects.haskell.org/haskellmode-emacs/ or on Debian you can type <code>apt-get install haskell-mode</code> (although this currently doesn't have the latest version). It is currently maintained by Svein Ove Aas[http://www.mail-archive.com/haskell-cafe@haskell.org/msg66300.html].<br />
<br />
<br />
<br />
<br />
==Development Version==<br />
<br />
<code><br />
$ darcs get http://code.haskell.org/haskellmode-emacs/<br />
</code><br />
<br />
See also [http://trac.haskell.org/haskellmode-emacs/report/1 Active Tickets] in bug tracker.<br />
<br />
==Setup==<br />
<br />
Download and unpack the basic mode and modules into a suitable directory, e.g. <code>~/lib/emacs/haskell-mode/</code> where <code>~</code> stands for your home directory.<br />
<br />
Assuming you have placed the basic mode haskell-mode.el and the modules you want to use in the directory <code>~/lib/emacs/haskell-mode/</code>, add the following command to your init file (<code>~/.emacs</code>):<br />
<br />
<code><br />
(load "~/lib/emacs/haskell-mode/haskell-site-file")<br />
</code><br />
<br />
adding the following lines according to which modules you want to use:<br />
<br />
<code><br />
(add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)<br />
(add-hook 'haskell-mode-hook 'turn-on-haskell-indentation)<br />
;;(add-hook 'haskell-mode-hook 'turn-on-haskell-indent)<br />
;;(add-hook 'haskell-mode-hook 'turn-on-haskell-simple-indent)<br />
</code><br />
<br />
Note that the three indentation modules are mutually exclusive - add at most one. Note that the line of code for simple indentation is commented out (using a preceding ;) in preference for the more advanced indentation module. Installation is now complete!<br />
<br />
==== Inferior Mode ====<br />
<br />
Normally, inf-haskell automatically finds ghci or hugs in your <code>PATH</code>, but if that's not the case (common under Windows), or if you need to specify your preference, just tell Emacs which executable to use with:<br />
<br />
<code><br />
(setq haskell-program-name "/some/where/ghci.exe")<br />
</code><br />
<br />
If you want to use different settings when you use Cygwin Emacs and NTEmacs,<br />
you can test the value of `system-type':<br />
<br />
<code><br />
(setq haskell-program-name<br />
(if (eq system-type 'cygwin)<br />
"/cygdrive/c/ghc/ghc-6.8.1/bin/ghcii.sh"<br />
"c:/ghc/ghc-6.8.1/bin/ghci.exe"))<br />
</code><br />
<br />
Note that Cygwin binaries tend to interact poorly with NTEmacs, especially<br />
w.r.t signal-handling.<br />
<br />
==Tips and use==<br />
Handy keybindings in haskell-mode. See the documentation <code>C-h m</code> for more information:<br />
*<code>C-c C-=</code> inserts an = sign and lines up type signatures and other pattern matches nicely.<br />
*<code>C-c C-|</code> inserts a guard<br />
*<code>C-c C-o</code> inserts a guard <hask>| otherwise =</hask> and lines up existing guards<br />
*<code>C-c C-w</code> inserts a where keyword<br />
*<code>C-c C-.</code> aligns code over a region in a "sensible" fashion.<br />
<br />
Now in version 2.2:<br />
*<code>C-c C-t</code> gets :type for symbol at point, and remembers it<br />
*<code>C-u C-c C-t</code> inserts a type annotation, for symbol at point, on the line above<br />
*<code>C-c C-i</code> gets :info for symbol at point<br />
*<code>C-c M-.</code> find definition of (interpreted) symbol at point<br />
<br />
(See the section below on [[#inf-haskell.el:_the_best_thing_since_the_breadknife|inf-haskell]].)<br />
<br />
Here's an example for <code>C-c C-=</code>. Put your cursor after myInt and hit <code>C-c C-=</code><br />
<haskell><br />
blah :: Int -> Int<br />
blah myInt<br />
</haskell><br />
note how the function signature is reindented to match the column of the = sign.<br />
<haskell><br />
blah :: Int -> Int<br />
blah myInt =<br />
</haskell><br />
<br />
You could also achieve the same effect by selecting the region and typing <code>C-c C-.</code><br />
<br />
You can also use Haskell-Mode to load Emacs buffers with Haskell code in either Hugs or GHC. To load something in Hugs or ghci, type <code>C-c C-l</code> to load the file. Then, you can go on to type <code>C-c C-r</code> (or simply <code>C-c C-l</code> again) to reload the current module when you have made a change.<br />
<br />
=== Indentation ===<br />
Indentation is one thing that nearly all programming modes provide. However, indenting Haskell code is very hard: for a given line, there are nearly always more than column for which indentation makes sense. For example, imagine the following is open in a haskell-mode buffer, where <code>!</code> represents the point:<br />
<br />
<haskell><br />
foo :: Int -> String<br />
foo 0 = f 4 ++ s<br />
where f 4 = "hello" ++ <br />
!<br />
</haskell><br />
<br />
If you ask haskell-mode to indent for you, where should it indent to? There are four basic options:<br />
<br />
<ol><br />
<li><br />
You want to finish off the expression you were writing in the last line. Haskell-mode indents to be underneath the <code>"</code> character at the beginning of <code>"hello"</code>:<br />
<br />
<haskell><br />
where f 4 = "hello" ++<br />
!<br />
</haskell><br />
<br />
This is debatably a bad choice as you'd probably want to indent a bit further in to make it clear that you were carrying on an expression, but the layout rule would accept something like the following:<br />
<br />
<haskell><br />
where f 4 = "hello" ++<br />
"world"<br />
</haskell><br />
<br />
</li><br />
<li><br />
You want to add a second equation for <code>f</code>. Haskell-mode will indent to line up with the first argument, and fill in the <code>f</code> in the equation:<br />
<br />
<haskell><br />
where f 4 = "hello" ++<br />
f !<br />
</haskell><br />
<br />
This is an unlikely choice as the expression in the previous line isn't complete, but haskell-mode isn't smart enough to know that. (If <code>f</code> had been something without arguments, like <hask>where f = "hello"</hask>, then it's impossible to have more than one equation and haskell-mode won't offer this indentation level.)<br />
</li><br />
<li><br />
You want to add a second binding to the <code>where</code>-block. Haskell-mode indents to line up with the <code>f</code>:<br />
<br />
<haskell><br />
where f 4 = "hello" ++<br />
!<br />
</haskell><br />
<br />
</li><br />
<li>You want to start an entirely new top-level binding. Haskell-mode indents to the first column:<br />
<br />
<haskell><br />
foo :: Int -> String<br />
foo 0 = f 4 ++ s<br />
where f 4 = "hello" ++<br />
!<br />
</haskell><br />
<br />
</li><br />
</ol><br />
<br />
These four locations can be reached by repeatedly pressing <code>TAB</code>. This is what's known as the tab-cycle. The innermost location is offered first, then cycling progresses outwards. Although this may seem like an inefficient system (and it is indeed a shame that Haskell's design didn't result in an unambiguous indentation system), you do quickly get used to the tab-cycle and indenting Haskell code.<br />
<br />
==== indent-region ====<br />
Using indent-region is generally a bad idea on Haskell code, because it would need to know which of the tab-cycle stops you wish to choose for each line. The innermost one is chosen in each case, which often results in unusable code. Moral: just don't use indent-region with haskell-mode.<br />
<br />
==== Unicodifying symbols (Pretty Lambda for Haskell-mode) ====<br />
In Haskell code, you can end up using a lot of mathematical symbols. It is possible to hack the fontifying features of Emacs to change the ASCII textual representations of arrows and operators into the nice-looking real symbols, much like you could with TeX. The following code is a compilation of Emacs lisp code found on the Emacs wiki on the [http://www.emacswiki.org/cgi-bin/wiki/PrettyLambda#toc4 Pretty Lambda] page (that page also has examples of how to apply the general Unicode defuns to other languages):<br />
<br />
HOWEVER: due to the symbols taking up less space, this has the unfortunate side effect of changing the indentation stops that the indent key offers. This will mean that your code may not look properly aligned to those who do not have this feature in their editor, or could even mean that your code means something different to how it looks. (It is possible to contrive an example that looks correct in emacs, but actually fails to compile). The following is left for interest, but probably should NOT be used.<br />
<br />
Haskell-mode has included this feature for a long time now, so you probably just need to <code>(setq haskell-font-lock-symbols t)</code> in your .emacs to use this feature.<br />
<br />
<code><br />
(defun unicode-symbol (name)<br />
"Translate a symbolic name for a Unicode character -- e.g., LEFT-ARROW <br />
or GREATER-THAN into an actual Unicode character code. "<br />
(decode-char 'ucs (case name <br />
(left-arrow 8592)<br />
(up-arrow 8593)<br />
(right-arrow 8594)<br />
(down-arrow 8595) <br />
(double-vertical-bar #X2551) <br />
(equal #X003d)<br />
(not-equal #X2260)<br />
(identical #X2261)<br />
(not-identical #X2262)<br />
(less-than #X003c)<br />
(greater-than #X003e)<br />
(less-than-or-equal-to #X2264)<br />
(greater-than-or-equal-to #X2265) <br />
(logical-and #X2227)<br />
(logical-or #X2228)<br />
(logical-neg #X00AC) <br />
('nil #X2205)<br />
(horizontal-ellipsis #X2026)<br />
(double-exclamation #X203C)<br />
(prime #X2032)<br />
(double-prime #X2033)<br />
(for-all #X2200)<br />
(there-exists #X2203)<br />
(element-of #X2208) <br />
(square-root #X221A)<br />
(squared #X00B2)<br />
(cubed #X00B3) <br />
(lambda #X03BB)<br />
(alpha #X03B1)<br />
(beta #X03B2)<br />
(gamma #X03B3)<br />
(delta #X03B4))))<br />
<br />
(defun substitute-pattern-with-unicode (pattern symbol)<br />
"Add a font lock hook to replace the matched part of PATTERN with the <br />
Unicode symbol SYMBOL looked up with UNICODE-SYMBOL."<br />
(font-lock-add-keywords<br />
nil `((,pattern <br />
(0 (progn (compose-region (match-beginning 1) (match-end 1)<br />
,(unicode-symbol symbol)<br />
'decompose-region)<br />
nil))))))<br />
<br />
(defun substitute-patterns-with-unicode (patterns)<br />
"Call SUBSTITUTE-PATTERN-WITH-UNICODE repeatedly."<br />
(mapcar #'(lambda (x)<br />
(substitute-pattern-with-unicode (car x)<br />
(cdr x)))<br />
patterns))<br />
<br />
(defun haskell-unicode ()<br />
(substitute-patterns-with-unicode<br />
(list (cons "\\(<-\\)" 'left-arrow)<br />
(cons "\\(->\\)" 'right-arrow)<br />
(cons "\\(==\\)" 'identical)<br />
(cons "\\(/=\\)" 'not-identical)<br />
(cons "\\(()\\)" 'nil)<br />
(cons "\\<\\(sqrt\\)\\>" 'square-root)<br />
(cons "\\(&&\\)" 'logical-and)<br />
(cons "\\(||\\)" 'logical-or)<br />
(cons "\\<\\(not\\)\\>" 'logical-neg)<br />
(cons "\\(>\\)\\[^=\\]" 'greater-than)<br />
(cons "\\(<\\)\\[^=\\]" 'less-than)<br />
(cons "\\(>=\\)" 'greater-than-or-equal-to)<br />
(cons "\\(<=\\)" 'less-than-or-equal-to)<br />
(cons "\\<\\(alpha\\)\\>" 'alpha)<br />
(cons "\\<\\(beta\\)\\>" 'beta)<br />
(cons "\\<\\(gamma\\)\\>" 'gamma)<br />
(cons "\\<\\(delta\\)\\>" 'delta)<br />
(cons "\\(<nowiki>''</nowiki>\\)" 'double-prime)<br />
(cons "\\('\\)" 'prime)<br />
(cons "\\(!!\\)" 'double-exclamation)<br />
(cons "\\(\\.\\.\\)" 'horizontal-ellipsis))))<br />
<br />
(add-hook 'haskell-mode-hook 'haskell-unicode)</code><br />
<br />
== Bugs ==<br />
Bugs and feature requests should be sent to the maintainer [mailto:svein.ove@aas.no Svein Ove Aas].<br />
For people using the Debian package, Debian maintains a [http://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=haskell-mode list of bugs] for haskell-mode, they should be reported there.<br />
<br />
===XEmacs===<br />
On some the GNU/Linux systems with XEmacs, admittedly, only verified on Ubuntu and Debian and with haskell-mode 2.2, there is a system function missing that interferes with automatic indenting. Secondly, there seems to be an issue with setting the <code-lisp>haskell-default-face</code-lisp> to <code-lisp>nil</code-lisp>.<br />
<br />
====line-end-position====<br />
<br />
To fix this, find where the haskell mode package is installed on your system. (Usually <code>/usr/share/emacs/site-lisp/haskell-mode</code>). Edit the file <code>haskell-indent.el</code> and add the lines:<br />
<pre-lisp><br />
(eval-and-compile<br />
<br />
;; If `line-end-position' isn't available provide one.<br />
(unless (fboundp 'line-end-position)<br />
(defun line-end-position (&optional n)<br />
"Return the `point' of the end of the current line."<br />
(save-excursion<br />
(end-of-line n)<br />
(point)))))<br />
</pre-lisp><br />
right after the comments at the top. That should fix the issue.<br />
<br />
====haskell-default-face====<br />
<br />
This one shows up when typing in code (at various spots - most often when typing a qualified function, such as <hask>List.map</hask>.)<br />
<br />
To fix this one, edit the file <code>haskell-font-lock.el</code>. Look for the line that says:<br />
<pre-lisp><br />
(defvar haskell-default-face nil)<br />
</pre-lisp><br />
and change this to <br />
<pre-lisp><br />
(defvar haskell-default-face 'default)<br />
</pre-lisp><br />
In my version, this is line 168.<br />
<br />
Then, look for the line that says:<br />
<pre-lisp><br />
(,qvarid 0 haskell-default-face)<br />
</pre-lisp><br />
and change it to<br />
<pre-lisp><br />
(,qvarid 0 (symbol-value 'haskell-default-face))<br />
</pre-lisp><br />
<br />
For me, this is line 326 of the file.<br />
YMMV - hope this helps.<br />
<br />
<!--<br />
=== GNU Emacs ===<br />
<br />
==== ghci buffer infested with "^J"s, C-c C-t doesn't work ====<br />
<br />
(only happens after loading a haskell file into ghci)<br />
<br />
--><br />
<br />
<br />
== inf-haskell.el: the best thing since the breadknife ==<br />
inf-haskell.el is _awesome_. At one point I decided to sit down and write a list of functions I'd love to have in haskell-mode, intending to write them myself. I thought I'd check to see whether the key shortcuts I'd chosen were free but I was surprised to find that ''every one'' of these functions is already provided by inf-haskell.el! Here's a selection of the highlights:<br />
<br />
=== Getting set up ===<br />
inf-haskell.el is usually already setup as part of the haskell-mode package, so there is nothing special to do for it. On some systems, you may need this in your .emacs:<br />
<br />
<pre-lisp><br />
(require 'inf-haskell)<br />
</pre-lisp><br />
<br />
To use the following functions, first find a .hs file, then hit C-c C-l (inferior-haskell-load-file). This fires up Hugs or Ghci (you can change this by customising haskell-program-name) on your file. Don't worry if it's not an isolated module, GHCi will load all the modules it imports as normal. You can even load entire programs this way by using C-c C-l on the Main.hs file. If everything loads without errors, you'll be able to use the functions below.<br />
<br />
=== inferior-haskell-type (C-c C-t) ===<br />
Say you have the following code:<br />
<br />
foo = foldr (+) 0 [1..20]<br />
<br />
Perhaps you've forgotten the order of arguments to foldr. It's easily done; I can never remember whether the operation or final value comes first. That's easy to check: just put your point between the 'f' and 'r' of 'foldr' and hit C-c C-t RET. The type of foldr will be revealed in the echo area. This isn't particularly impressive; haskell-doc.el already did this. However, this will work for ''any'' function in the module in question ''or'' in those modules imported by the current module (including the standard libs)!<br />
<br />
If you find that the type shown in the echo area is overwritten after a short amount of time (or any other such problem, of course), please report it as a bug. We know of no such bug, but someone apparently bumped into some such problem which he says he worked around by disabling doc-mode and decl-scan:<br />
<br />
To turn off haskell-doc-mode, add the following to your .emacs:<br />
<pre-lisp><br />
(remove-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)<br />
</pre-lisp><br />
To turn off haskell-decl-scan, just refrain from turning it on (it's not enabled by default).<br />
<br />
(P.S. I re-use haskell-doc-mode to save queried type info, and re-display it in the minibuffer. Disabling doc mode would disable that. -- mrd)<br />
<br />
Another nice feature of this function is the ability to automatically insert type signatures for the function at point on the line above. For example, suppose you have the below open in Emacs, with the point represented by -!-:<br />
<br />
-!-map _ [] = []<br />
map f (x:xs) = f x : map f xs<br />
<br />
And press C-u C-c C-t (note the prefix argument), it will result in the following:<br />
<br />
map :: (a -> b) -> [a] -> [b]<br />
-!-map _ [] = []<br />
map f (x:xs) = f x : map f xs<br />
<br />
=== inferior-haskell-info (C-c C-i) ===<br />
The :info command in GHCi/Hugs is extremely useful; it'll tell you:<br />
<br />
* The definition of an algebraic datatype given its name. E.g. try <code>:info Bool</code>. The output will contain something like <code>data Bool = True | False</code>.<br />
* The classes a type instantiates given the type's name. <code>:info Bool</code> will also give you the classes Bool instantiates. If you can't see an instance you think should be there, make sure the module where that instance is declared is loaded.<br />
* The type of a function, given its name.<br />
* The types of the methods of a class, and the number of arguments of that class, given the class name.<br />
* The expansion of a type synonym given that synonym's name.<br />
<br />
And for all of the above, :info will also tell you the filename and line where that thing is defined. inferior-haskell-info lets you hook into this power. Use it with C-c C-i on anything within a Haskell file.<br />
<br />
=== inferior-haskell-find-definition (C-c M-.) ===<br />
This one needs little explanation. Sometimes you just need to find the source of a function, or datatype, or class, or type synonym etc. to see how it works, and this function lets you do just that. Unfortunately, it won't work on the standard lib modules or anything that isn't 'local' to your project. This is one of the most useful functions inf-haskell.el provides.<br />
<br />
(Basically, it only works on interpreted code, for which ghci has location information. If you want a more general find-definition, use hasktags to create a TAGS file and then use the normal emacs <code>M-.</code> with that. -- mrd)<br />
: Note that you can also create a TAGS file using GHCi's :etags command. [[User:DavidHouse|DavidHouse]] 14:38, 29 April 2007 (UTC)<br />
<br />
: Again, :etags/:ctags only works for interpreted code.<br />
<br />
: <code>inferior-haskell-mode</code> is missing TAB completion, which in GHCi works basically for everything (GHCi commands, modules, functions, language extensions, file names etc.). -- Oleksandr Manzyuk<br />
<br />
== Tricks and tweaks ==<br />
<br />
=== Automatic unit testing ===<br />
Here's a cute trick I've evolved:<br />
<br />
I'm a great fan of [[unit test first]], as described by eXtremeProgramming on TheOriginalWiki.<br />
<br />
With the code below, I can press F12 and immediately run all of my unit tests, and immediately see whether they all passed or not.<br />
I've put all of my unit tests into their own file with a main function that runs the tests and gives an exitcode according to the test results. I've specified that the compile-command for that file compiles and runs the file.<br />
<br />
This elisp code will run the <code>compile</code> command from the F12 key in emacs. The output will popup a new window twelve lines tall. If the compilation is successful (exitcode zero) the window goes away. If the exitcode is 1 or greater, the window stays so you can see the output.<br />
<pre-lisp><br />
(require 'compile)<br />
<br />
;; this means hitting the compile button always saves the buffer<br />
;; having to separately hit C-x C-s is a waste of time<br />
(setq mode-compile-always-save-buffer-p t)<br />
;; make the compile window stick at 12 lines tall<br />
(setq compilation-window-height 12)<br />
<br />
;; from enberg on #emacs<br />
;; if the compilation has a zero exit code, <br />
;; the windows disappears after two seconds<br />
;; otherwise it stays<br />
(setq compilation-finish-function<br />
(lambda (buf str)<br />
(unless (string-match "exited abnormally" str)<br />
;;no errors, make the compilation window go away in a few seconds<br />
(run-at-time<br />
"2 sec" nil 'delete-windows-on<br />
(get-buffer-create "*compilation*"))<br />
(message "No Compilation Errors!"))))<br />
<br />
<br />
;; one-button testing, tada!<br />
(global-set-key [f12] 'compile)<br />
</pre-lisp><br />
<br />
<br />
This Haskell code has some Emacs local variable settings at the bottom specifying what the compile-command should be for this buffer.<br />
<haskell><br />
import HUnit<br />
import System<br />
<br />
myTestList = <br />
TestList [<br />
"add numbers" ~: 5 ~=? (3 + 2)<br />
,"add numbers" ~: 5 ~=? (3 + 3)<br />
]<br />
<br />
h = runTestTT myTestList<br />
<br />
main = do c <- h<br />
putStr $ show c<br />
let errs = errors c<br />
fails = failures c<br />
System.exitWith (codeGet errs fails)<br />
<br />
codeGet errs fails<br />
| fails > 0 = ExitFailure 2<br />
| errs > 0 = ExitFailure 1<br />
| otherwise = ExitSuccess<br />
<br />
-- Local Variables:<br />
-- compile-command: "ghc --make -o Test_Demo -i/home/shae/src/haskell/libraries/ HUnitDemo.hs && ./Test_Demo"<br />
-- End:<br />
</haskell><br />
<br />
<br />
If you have any questions, ideas, or suggestions for this code, the maintainer would love to hear them.<br />
<br />
=== Hoogle integration ===<br />
From haskell-mode version 2.4 onwards, the built-in function haskell-hoogle will hoogle the identifier at point.<br />
<br />
=== Using rectangular region commands ===<br />
<br />
Emacs has a set of commands which operate on the region as if it were rectangular. This turns out to be extremely useful when dealing with whitespace sensitive languages.<br />
<br />
<code>C-x r o</code> is "Open Rectangle". It will shift any text within the rectangle to the right side. Also see:<br />
<br />
<code>C-x r t</code> is "String Rectangle". It will shift any text within the rectangle over to the right, and insert a given string prefixing all the lines in the region. If comment-region didn't already exist, you could use this instead, for example.<br />
<br />
<code>C-x r d</code> is "Delete Rectangle". It will delete the contents of the rectangle and move anything on the right over.<br />
<br />
<code>C-x r r</code> is "Copy Rectangle to Register". It will prompt you for a register number so it can save it for later.<br />
<br />
<code>C-x r g</code> is "Insert register". This will insert the contents of the given register, overwriting whatever happens to be within the target rectangle. (So make room)<br />
<br />
<code>C-x r k</code> is "Kill rectangle". Delete rectangle and save contents for:<br />
<br />
<code>C-x r y</code> is "Yank rectangle". This will insert the contents of<br />
the last killed rectangle.<br />
<br />
As with all Emacs modifier combos, you can type <code>C-x r C-h</code> to find out what keys are bound beginning with the <code>C-x r</code> prefix.<br />
<br />
=== Aligning code ===<br />
<br />
Emacs22 has a neat tool called: align-regexp. Select a region you want to align text within, M-x align-regexp, and type a regexp representing the alignment delimiter.<br />
<br />
For example, I often line up my Haddock comments:<br />
<br />
<haskell><br />
f :: a -- ^ does a<br />
-> Foo b -- ^ and b<br />
-> c -- ^ to c<br />
</haskell><br />
<br />
Select the region, and let the regexp be: <code>--</code><br />
<br />
<haskell><br />
f :: a -- ^ does a<br />
-> Foo b -- ^ and b<br />
-> c -- ^ to c<br />
</haskell><br />
<br />
Of course, this works for just about anything. Personally, I've globally bound it to <code>C-x a r</code>:<br />
<br />
<code>(global-set-key (kbd "C-x a r") 'align-regexp)</code>.<br />
<br />
=== Automatically building ===<br />
Emacs 21 has a package that can be installed (included by default in 22 and up) called 'FlyMake'; the idea is that as you are editing away, it occasionally calls the interpreter/compiler automatically and keeps track of whether the code works or not. You can fairly easily get it to work for Haskell as well; see [http://www.emacswiki.org/cgi-bin/wiki/FlymakeHaskell FlymakeHaskell] on the Emacs wiki.<br />
<br />
=== Emacs Integration with Hayoo ===<br />
<br />
My newly installed system would not allow me to hoogle what I wanted (no xmonad or xmonadcontrib in hoogle) so someone suggested Hayoo.<br />
<br />
<code><br />
(define-key haskell-mode-map (kbd "<f3>")<br />
(lambda ()<br />
(interactive)<br />
(browse-url (format "http://holumbus.fh-wedel.de/hayoo/hayoo.html?query=%s&start"<br />
(region-or-word-at-point)))))<br />
</code><br />
<br />
region-or-word-at-point is available in the thing-at-pt+.el library.<br />
<br />
Added 22-12-2008 - Promt for hayoo word<br />
<br />
<code><br />
(defun rgr/hayoo()<br />
(interactive)<br />
(let* ((default (region-or-word-at-point))<br />
(term (read-string (format "Hayoo for the following phrase (%s): "<br />
default))))<br />
(let ((term (if (zerop (length term)) default term)))<br />
(browse-url (format "http://holumbus.fh-wedel.de/hayoo/hayoo.html?query=%s&start" term)))))<br />
<br />
<br />
(define-key haskell-mode-map (kbd "<f3>") 'rgr/hayoo)<br />
</code><br />
<br />
Alternatively use the excellent browse-apropos-url stuff:<br />
<br />
http://www.emacswiki.org/emacs/BrowseAproposURL#toc6<br />
<br />
[http://richardriley.net Richard]<br />
<br />
Note: Using and URL like this should work too and will give better results (not yet tested as I'm not an emacs user):<br />
<br />
<code><br />
http://holumbus.fh-wedel.de/hayoo/hayoo.html?query=%s<br />
</code><br />
<br />
[[User:Tbh|Tbh]] 00:56, 25 January 2009 (UTC)<br />
<br />
=== Integration with HLint ===<br />
<br />
[http://www-users.cs.york.ac.uk/~ndm/hlint/ HLint] could be used directly from Emacs buffer. There is [http://www.cs.york.ac.uk/fp/darcs/hlint/data/hs-lint.el hs-lint.el] package (in HLint distribution, in the data subdirectory), that allows user to run HLint and navigate through errors, or apply suggestions to the source code.<br />
<br />
This package implements `hs-lint` command, that behaves differently depending on settings. If the `hs-lint-replace-with-suggestions` variable is set to `t`, then it will ask user and apply concrete suggested change to source code, otherwise you'll be able to navigate through list of suggestions with `next-error` command. If the `hs-lint-replace-without-ask` variable is also set to `t`, then all suggestions will applied automatically. <br />
<br />
You can also bind `hs-lint` command to some key (in this example this is `C-c l`) with following code:<br />
<br />
<code><br />
(defun my-haskell-mode-hook ()<br />
(local-set-key "\C-cl" 'hs-lint))<br />
(add-hook 'haskell-mode-hook 'my-haskell-mode-hook)<br />
</code><br />
<br />
All settings, described above are available for customization via `hs-lint` customization group.<br />
<br />
[[Category:Development tools]]<br />
<br />
=== Folding ===<br />
For folding parts of code you can use<br />
*'''hide-show.el'''<br />
*and '''hs-outline-level''' (based on py-outline-level created by Gb)<br />
<br />
<code><br />
;; this gets called by outline to determine the level. Just use the length of the whitespace<br />
(defun hsk-outline-level ()<br />
(let (buffer-invisibility-spec)<br />
(save-excursion<br />
(skip-chars-forward "\t ")<br />
(current-column))))<br />
<br />
;; this get called after haskell mode is enabled <br />
(add-hook<br />
'haskell-mode-hook<br />
(lambda ()<br />
;; outline uses this regexp to find headers. I match lines with no indent and indented<br />
;; some lines, such as "--" ... "class"<br />
(setq outline-regexp "^[^\t ].*\\|^.*[\t ]+\\(where\\|of\\|do\\|in\\|if\\|then\\|else\\|let\\|module\\|import\\|deriving\\|instance\\|class\\)[\t\n ]")<br />
;; enable our level computation<br />
(setq outline-level 'hsk-outline-level)<br />
;; do not use their \C-c@ prefix, too hard to type. Note this overides some python mode bindings<br />
;;(setq outline-minor-mode-prefix "C-c")<br />
;; turn on outline mode<br />
(outline-minor-mode t)<br />
;; initially hide all but the headers<br />
;;(hide-body)<br />
))<br />
</code><br />
<br />
*Also, you can use '''toggle-selective-display''' for global folding<br />
<br />
<code><br />
;; folding for all rows, starting on the current column<br />
(defun toggle-selective-display (column)<br />
(interactive "P")<br />
(set-selective-display<br />
(or column<br />
(unless selective-display<br />
(1+ (current-column))))))<br />
<br />
(global-set-key (kbd "C-x $") 'toggle-selective-display)<br />
<br />
(defun toggle-hiding (column)<br />
(interactive "P")<br />
(if hs-minor-mode<br />
(if (condition-case nil<br />
(hs-toggle-hiding)<br />
(error t))<br />
(hs-show-all))<br />
(toggle-selective-display column)))<br />
<br />
(global-set-key (kbd "C-@") 'toggle-hiding)<br />
</code><br />
<br />
*and '''narrowing capabilities''' for folding the rest of code<br />
<code><br />
(put 'narrow-to-defun 'disabled nil)<br />
(put 'narrow-to-page 'disabled nil)<br />
(put 'narrow-to-region 'disabled nil)<br />
</code><br />
<br />
*or '''folding-mode''', if you do not mind add markers such as '''{-{{{-}''' and '''{-}}}-}''' in code.<br />
<br />
=== Speedbar ===<br />
<br />
Emacs has a [http://www.emacswiki.org/emacs/SpeedBar SpeedBar] which works quite nice together with haskell-mode and also detects syntactic elements such as variables, imports, instances, classes.<br />
<br />
Just add<br />
<code><br />
(require 'speedbar)<br />
(speedbar-add-supported-extension ".hs")<br />
</code><br />
to your .emacs file and fire up speedbar with <code>M-x speedbar</code>.<br />
<br />
=== Literate Haskell ===<br />
<br />
Literate Haskell is supported directly by haskell-mode without having to use MMM or other tricks that may be found in old mailing list postings, so ignore that out of date information. If you load an .lhs file, then literate haskell should automatically work. If it doesn't then you should make sure that you are using a current version of haskell-mode and that the correct literate type is selected. You can switch between bird (the default) and tex by typing:<br />
<br />
<code><br />
M-x customize-variable RET haskell-literate-default<br />
</code><br />
<br />
=== Keeping Imports sorted and aligned ===<br />
<br />
See this [http://www.youtube.com/watch?v=UXHSiUPKLvg&fmt=35 screencast about making imports automatically alphabetically ordered and indented].<br />
<br />
The extension modules for that can be found at https://github.com/chrisdone/haskell-mode-exts#readme</div>Hvrhttps://wiki.haskell.org/index.php?title=Haskell_mode_for_Emacs&diff=36854Haskell mode for Emacs2010-09-26T07:39:05Z<p>Hvr: add direct link to bug tracker</p>
<hr />
<div>haskell-mode is a major mode for Emacs and XEmacs specifically for writing Haskell code. You can get haskell-mode from the web page: http://projects.haskell.org/haskellmode-emacs/ or on Debian you can type <code>apt-get install haskell-mode</code> (although this currently doesn't have the latest version). It is currently maintained by Svein Ove Aas[http://www.mail-archive.com/haskell-cafe@haskell.org/msg66300.html].<br />
<br />
<br />
<br />
<br />
==Development Version==<br />
<br />
<code><br />
$ darcs get http://code.haskell.org/haskellmode-emacs/<br />
</code><br />
<br />
See also [http://trac.haskell.org/haskellmode-emacs/report/1 Active Tickets] in bug tracker.<br />
<br />
==Setup==<br />
<br />
Download and unpack the basic mode and modules into a suitable directory, e.g. <code>~/lib/emacs/haskell-mode/</code> where <code>~</code> stands for your home directory.<br />
<br />
Assuming you have placed the basic mode haskell-mode.el and the modules you want to use in the directory <code>~/lib/emacs/haskell-mode/</code>, add the following command to your init file (<code>~/.emacs</code>):<br />
<br />
<code><br />
(load "~/lib/emacs/haskell-mode/haskell-site-file")<br />
</code><br />
<br />
adding the following lines according to which modules you want to use:<br />
<br />
<code><br />
(add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)<br />
(add-hook 'haskell-mode-hook 'turn-on-haskell-indentation)<br />
;;(add-hook 'haskell-mode-hook 'turn-on-haskell-indent)<br />
;;(add-hook 'haskell-mode-hook 'turn-on-haskell-simple-indent)<br />
</code><br />
<br />
Note that the three indentation modules are mutually exclusive - add at most one. Note that the line of code for simple indentation is commented out (using a preceding ;) in preference for the more advanced indentation module. Installation is now complete!<br />
<br />
==== Inferior Mode ====<br />
<br />
Normally, inf-haskell automatically finds ghci or hugs in your <code>PATH</code>, but if that's not the case (common under Windows), or if you need to specify your preference, just tell Emacs which executable to use with:<br />
<br />
<code><br />
(setq haskell-program-name "/some/where/ghci.exe")<br />
</code><br />
<br />
If you want to use different settings when you use Cygwin Emacs and NTEmacs,<br />
you can test the value of `system-type':<br />
<br />
<code><br />
(setq haskell-program-name<br />
(if (eq system-type 'cygwin)<br />
"/cygdrive/c/ghc/ghc-6.8.1/bin/ghcii.sh"<br />
"c:/ghc/ghc-6.8.1/bin/ghci.exe"))<br />
</code><br />
<br />
Note that Cygwin binaries tend to interact poorly with NTEmacs, especially<br />
w.r.t signal-handling.<br />
<br />
==Tips and use==<br />
Handy keybindings in haskell-mode. See the documentation <code>C-h m</code> for more information:<br />
*<code>C-c C-=</code> inserts an = sign and lines up type signatures and other pattern matches nicely.<br />
*<code>C-c C-|</code> inserts a guard<br />
*<code>C-c C-o</code> inserts a guard <hask>| otherwise =</hask> and lines up existing guards<br />
*<code>C-c C-w</code> inserts a where keyword<br />
*<code>C-c C-.</code> aligns code over a region in a "sensible" fashion.<br />
<br />
Now in version 2.2:<br />
*<code>C-c C-t</code> gets :type for symbol at point, and remembers it<br />
*<code>C-u C-c C-t</code> inserts a type annotation, for symbol at point, on the line above<br />
*<code>C-c C-i</code> gets :info for symbol at point<br />
*<code>C-c M-.</code> find definition of (interpreted) symbol at point<br />
<br />
(See the section below on [[#inf-haskell.el:_the_best_thing_since_the_breadknife|inf-haskell]].)<br />
<br />
Here's an example for <code>C-c C-=</code>. Put your cursor after myInt and hit <code>C-c C-=</code><br />
<haskell><br />
blah :: Int -> Int<br />
blah myInt<br />
</haskell><br />
note how the function signature is reindented to match the column of the = sign.<br />
<haskell><br />
blah :: Int -> Int<br />
blah myInt =<br />
</haskell><br />
<br />
You could also achieve the same effect by selecting the region and typing <code>C-c C-.</code><br />
<br />
You can also use Haskell-Mode to load Emacs buffers with Haskell code in either Hugs or GHC. To load something in Hugs or ghci, type <code>C-c C-l</code> to load the file. Then, you can go on to type <code>C-c C-r</code> (or simply <code>C-c C-l</code> again) to reload the current module when you have made a change.<br />
<br />
=== Indentation ===<br />
Indentation is one thing that nearly all programming modes provide. However, indenting Haskell code is very hard: for a given line, there are nearly always more than column for which indentation makes sense. For example, imagine the following is open in a haskell-mode buffer, where <code>!</code> represents the point:<br />
<br />
<haskell><br />
foo :: Int -> String<br />
foo 0 = f 4 ++ s<br />
where f 4 = "hello" ++ <br />
!<br />
</haskell><br />
<br />
If you ask haskell-mode to indent for you, where should it indent to? There are four basic options:<br />
<br />
<ol><br />
<li><br />
You want to finish off the expression you were writing in the last line. Haskell-mode indents to be underneath the <code>"</code> character at the beginning of <code>"hello"</code>:<br />
<br />
<haskell><br />
where f 4 = "hello" ++<br />
!<br />
</haskell><br />
<br />
This is debatably a bad choice as you'd probably want to indent a bit further in to make it clear that you were carrying on an expression, but the layout rule would accept something like the following:<br />
<br />
<haskell><br />
where f 4 = "hello" ++<br />
"world"<br />
</haskell><br />
<br />
</li><br />
<li><br />
You want to add a second equation for <code>f</code>. Haskell-mode will indent to line up with the first argument, and fill in the <code>f</code> in the equation:<br />
<br />
<haskell><br />
where f 4 = "hello" ++<br />
f !<br />
</haskell><br />
<br />
This is an unlikely choice as the expression in the previous line isn't complete, but haskell-mode isn't smart enough to know that. (If <code>f</code> had been something without arguments, like <hask>where f = "hello"</hask>, then it's impossible to have more than one equation and haskell-mode won't offer this indentation level.)<br />
</li><br />
<li><br />
You want to add a second binding to the <code>where</code>-block. Haskell-mode indents to line up with the <code>f</code>:<br />
<br />
<haskell><br />
where f 4 = "hello" ++<br />
!<br />
</haskell><br />
<br />
</li><br />
<li>You want to start an entirely new top-level binding. Haskell-mode indents to the first column:<br />
<br />
<haskell><br />
foo :: Int -> String<br />
foo 0 = f 4 ++ s<br />
where f 4 = "hello" ++<br />
!<br />
</haskell><br />
<br />
</li><br />
</ol><br />
<br />
These four locations can be reached by repeatedly pressing <code>TAB</code>. This is what's known as the tab-cycle. The innermost location is offered first, then cycling progresses outwards. Although this may seem like an inefficient system (and it is indeed a shame that Haskell's design didn't result in an unambiguous indentation system), you do quickly get used to the tab-cycle and indenting Haskell code.<br />
<br />
==== indent-region ====<br />
Using indent-region is generally a bad idea on Haskell code, because it would need to know which of the tab-cycle stops you wish to choose for each line. The innermost one is chosen in each case, which often results in unusable code. Moral: just don't use indent-region with haskell-mode.<br />
<br />
==== Unicodifying symbols (Pretty Lambda for Haskell-mode) ====<br />
In Haskell code, you can end up using a lot of mathematical symbols. It is possible to hack the fontifying features of Emacs to change the ASCII textual representations of arrows and operators into the nice-looking real symbols, much like you could with TeX. The following code is a compilation of Emacs lisp code found on the Emacs wiki on the [http://www.emacswiki.org/cgi-bin/wiki/PrettyLambda#toc4 Pretty Lambda] page (that page also has examples of how to apply the general Unicode defuns to other languages):<br />
<br />
HOWEVER: due to the symbols taking up less space, this has the unfortunate side effect of changing the indentation stops that the indent key offers. This will mean that your code may not look properly aligned to those who do not have this feature in their editor, or could even mean that your code means something different to how it looks. (It is possible to contrive an example that looks correct in emacs, but actually fails to compile). The following is left for interest, but probably should NOT be used.<br />
<br />
Haskell-mode has included this feature for a long time now, so you probably just need to <code>(setq haskell-font-lock-symbols t)</code> in your .emacs to use this feature.<br />
<br />
<code><br />
(defun unicode-symbol (name)<br />
"Translate a symbolic name for a Unicode character -- e.g., LEFT-ARROW <br />
or GREATER-THAN into an actual Unicode character code. "<br />
(decode-char 'ucs (case name <br />
('left-arrow 8592)<br />
('up-arrow 8593)<br />
('right-arrow 8594)<br />
('down-arrow 8595) <br />
('double-vertical-bar #X2551) <br />
('equal #X003d)<br />
('not-equal #X2260)<br />
('identical #X2261)<br />
('not-identical #X2262)<br />
('less-than #X003c)<br />
('greater-than #X003e)<br />
('less-than-or-equal-to #X2264)<br />
('greater-than-or-equal-to #X2265) <br />
('logical-and #X2227)<br />
('logical-or #X2228)<br />
('logical-neg #X00AC) <br />
('nil #X2205)<br />
('horizontal-ellipsis #X2026)<br />
('double-exclamation #X203C)<br />
('prime #X2032)<br />
('double-prime #X2033)<br />
('for-all #X2200)<br />
('there-exists #X2203)<br />
('element-of #X2208) <br />
('square-root #X221A)<br />
('squared #X00B2)<br />
('cubed #X00B3) <br />
('lambda #X03BB)<br />
('alpha #X03B1)<br />
('beta #X03B2)<br />
('gamma #X03B3)<br />
('delta #X03B4))))<br />
<br />
(defun substitute-pattern-with-unicode (pattern symbol)<br />
"Add a font lock hook to replace the matched part of PATTERN with the <br />
Unicode symbol SYMBOL looked up with UNICODE-SYMBOL."<br />
(interactive)<br />
(font-lock-add-keywords<br />
nil `((,pattern <br />
(0 (progn (compose-region (match-beginning 1) (match-end 1)<br />
,(unicode-symbol symbol)<br />
'decompose-region)<br />
nil))))))<br />
<br />
(defun substitute-patterns-with-unicode (patterns)<br />
"Call SUBSTITUTE-PATTERN-WITH-UNICODE repeatedly."<br />
(mapcar #'(lambda (x)<br />
(substitute-pattern-with-unicode (car x)<br />
(cdr x)))<br />
patterns))<br />
<br />
(defun haskell-unicode ()<br />
(interactive)<br />
(substitute-patterns-with-unicode<br />
(list (cons "\\(<-\\)" 'left-arrow)<br />
(cons "\\(->\\)" 'right-arrow)<br />
(cons "\\(==\\)" 'identical)<br />
(cons "\\(/=\\)" 'not-identical)<br />
(cons "\\(()\\)" 'nil)<br />
(cons "\\<\\(sqrt\\)\\>" 'square-root)<br />
(cons "\\(&&\\)" 'logical-and)<br />
(cons "\\(||\\)" 'logical-or)<br />
(cons "\\<\\(not\\)\\>" 'logical-neg)<br />
(cons "\\(>\\)\\[^=\\]" 'greater-than)<br />
(cons "\\(<\\)\\[^=\\]" 'less-than)<br />
(cons "\\(>=\\)" 'greater-than-or-equal-to)<br />
(cons "\\(<=\\)" 'less-than-or-equal-to)<br />
(cons "\\<\\(alpha\\)\\>" 'alpha)<br />
(cons "\\<\\(beta\\)\\>" 'beta)<br />
(cons "\\<\\(gamma\\)\\>" 'gamma)<br />
(cons "\\<\\(delta\\)\\>" 'delta)<br />
(cons "\\(<nowiki>''</nowiki>\\)" 'double-prime)<br />
(cons "\\('\\)" 'prime)<br />
(cons "\\(!!\\)" 'double-exclamation)<br />
(cons "\\(\\.\\.\\)" 'horizontal-ellipsis))))<br />
<br />
(add-hook 'haskell-mode-hook 'haskell-unicode)</code><br />
<br />
== Bugs ==<br />
Bugs and feature requests should be sent to the maintainer [mailto:svein.ove@aas.no Svein Ove Aas].<br />
For people using the Debian package, Debian maintains a [http://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=haskell-mode list of bugs] for haskell-mode, they should be reported there.<br />
<br />
===XEmacs===<br />
On some the GNU/Linux systems with XEmacs, admittedly, only verified on Ubuntu and Debian and with haskell-mode 2.2, there is a system function missing that interferes with automatic indenting. Secondly, there seems to be an issue with setting the <code-lisp>haskell-default-face</code-lisp> to <code-lisp>nil</code-lisp>.<br />
<br />
====line-end-position====<br />
<br />
To fix this, find where the haskell mode package is installed on your system. (Usually <code>/usr/share/emacs/site-lisp/haskell-mode</code>). Edit the file <code>haskell-indent.el</code> and add the lines:<br />
<pre-lisp><br />
(eval-and-compile<br />
<br />
;; If `line-end-position' isn't available provide one.<br />
(unless (fboundp 'line-end-position)<br />
(defun line-end-position (&optional n)<br />
"Return the `point' of the end of the current line."<br />
(save-excursion<br />
(end-of-line n)<br />
(point)))))<br />
</pre-lisp><br />
right after the comments at the top. That should fix the issue.<br />
<br />
====haskell-default-face====<br />
<br />
This one shows up when typing in code (at various spots - most often when typing a qualified function, such as <hask>List.map</hask>.)<br />
<br />
To fix this one, edit the file <code>haskell-font-lock.el</code>. Look for the line that says:<br />
<pre-lisp><br />
(defvar haskell-default-face nil)<br />
</pre-lisp><br />
and change this to <br />
<pre-lisp><br />
(defvar haskell-default-face 'default)<br />
</pre-lisp><br />
In my version, this is line 168.<br />
<br />
Then, look for the line that says:<br />
<pre-lisp><br />
(,qvarid 0 haskell-default-face)<br />
</pre-lisp><br />
and change it to<br />
<pre-lisp><br />
(,qvarid 0 (symbol-value 'haskell-default-face))<br />
</pre-lisp><br />
<br />
For me, this is line 326 of the file.<br />
YMMV - hope this helps.<br />
<br />
<!--<br />
=== GNU Emacs ===<br />
<br />
==== ghci buffer infested with "^J"s, C-c C-t doesn't work ====<br />
<br />
(only happens after loading a haskell file into ghci)<br />
<br />
--><br />
<br />
<br />
== inf-haskell.el: the best thing since the breadknife ==<br />
inf-haskell.el is _awesome_. At one point I decided to sit down and write a list of functions I'd love to have in haskell-mode, intending to write them myself. I thought I'd check to see whether the key shortcuts I'd chosen were free but I was surprised to find that ''every one'' of these functions is already provided by inf-haskell.el! Here's a selection of the highlights:<br />
<br />
=== Getting set up ===<br />
inf-haskell.el is usually already setup as part of the haskell-mode package, so there is nothing special to do for it. On some systems, you may need this in your .emacs:<br />
<br />
<pre-lisp><br />
(require 'inf-haskell)<br />
</pre-lisp><br />
<br />
To use the following functions, first find a .hs file, then hit C-c C-l (inferior-haskell-load-file). This fires up Hugs or Ghci (you can change this by customising haskell-program-name) on your file. Don't worry if it's not an isolated module, GHCi will load all the modules it imports as normal. You can even load entire programs this way by using C-c C-l on the Main.hs file. If everything loads without errors, you'll be able to use the functions below.<br />
<br />
=== inferior-haskell-type (C-c C-t) ===<br />
Say you have the following code:<br />
<br />
foo = foldr (+) 0 [1..20]<br />
<br />
Perhaps you've forgotten the order of arguments to foldr. It's easily done; I can never remember whether the operation or final value comes first. That's easy to check: just put your point between the 'f' and 'r' of 'foldr' and hit C-c C-t RET. The type of foldr will be revealed in the echo area. This isn't particularly impressive; haskell-doc.el already did this. However, this will work for ''any'' function in the module in question ''or'' in those modules imported by the current module (including the standard libs)!<br />
<br />
If you find that the type shown in the echo area is overwritten after a short amount of time (or any other such problem, of course), please report it as a bug. We know of no such bug, but someone apparently bumped into some such problem which he says he worked around by disabling doc-mode and decl-scan:<br />
<br />
To turn off haskell-doc-mode, add the following to your .emacs:<br />
<pre-lisp><br />
(remove-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)<br />
</pre-lisp><br />
To turn off haskell-decl-scan, just refrain from turning it on (it's not enabled by default).<br />
<br />
(P.S. I re-use haskell-doc-mode to save queried type info, and re-display it in the minibuffer. Disabling doc mode would disable that. -- mrd)<br />
<br />
Another nice feature of this function is the ability to automatically insert type signatures for the function at point on the line above. For example, suppose you have the below open in Emacs, with the point represented by -!-:<br />
<br />
-!-map _ [] = []<br />
map f (x:xs) = f x : map f xs<br />
<br />
And press C-u C-c C-t (note the prefix argument), it will result in the following:<br />
<br />
map :: (a -> b) -> [a] -> [b]<br />
-!-map _ [] = []<br />
map f (x:xs) = f x : map f xs<br />
<br />
=== inferior-haskell-info (C-c C-i) ===<br />
The :info command in GHCi/Hugs is extremely useful; it'll tell you:<br />
<br />
* The definition of an algebraic datatype given its name. E.g. try <code>:info Bool</code>. The output will contain something like <code>data Bool = True | False</code>.<br />
* The classes a type instantiates given the type's name. <code>:info Bool</code> will also give you the classes Bool instantiates. If you can't see an instance you think should be there, make sure the module where that instance is declared is loaded.<br />
* The type of a function, given its name.<br />
* The types of the methods of a class, and the number of arguments of that class, given the class name.<br />
* The expansion of a type synonym given that synonym's name.<br />
<br />
And for all of the above, :info will also tell you the filename and line where that thing is defined. inferior-haskell-info lets you hook into this power. Use it with C-c C-i on anything within a Haskell file.<br />
<br />
=== inferior-haskell-find-definition (C-c M-.) ===<br />
This one needs little explanation. Sometimes you just need to find the source of a function, or datatype, or class, or type synonym etc. to see how it works, and this function lets you do just that. Unfortunately, it won't work on the standard lib modules or anything that isn't 'local' to your project. This is one of the most useful functions inf-haskell.el provides.<br />
<br />
(Basically, it only works on interpreted code, for which ghci has location information. If you want a more general find-definition, use hasktags to create a TAGS file and then use the normal emacs <code>M-.</code> with that. -- mrd)<br />
: Note that you can also create a TAGS file using GHCi's :etags command. [[User:DavidHouse|DavidHouse]] 14:38, 29 April 2007 (UTC)<br />
<br />
: Again, :etags/:ctags only works for interpreted code.<br />
<br />
: <code>inferior-haskell-mode</code> is missing TAB completion, which in GHCi works basically for everything (GHCi commands, modules, functions, language extensions, file names etc.). -- Oleksandr Manzyuk<br />
<br />
== Tricks and tweaks ==<br />
<br />
=== Automatic unit testing ===<br />
Here's a cute trick I've evolved:<br />
<br />
I'm a great fan of [[unit test first]], as described by eXtremeProgramming on TheOriginalWiki.<br />
<br />
With the code below, I can press F12 and immediately run all of my unit tests, and immediately see whether they all passed or not.<br />
I've put all of my unit tests into their own file with a main function that runs the tests and gives an exitcode according to the test results. I've specified that the compile-command for that file compiles and runs the file.<br />
<br />
This elisp code will run the <code>compile</code> command from the F12 key in emacs. The output will popup a new window twelve lines tall. If the compilation is successful (exitcode zero) the window goes away. If the exitcode is 1 or greater, the window stays so you can see the output.<br />
<pre-lisp><br />
(require 'compile)<br />
<br />
;; this means hitting the compile button always saves the buffer<br />
;; having to separately hit C-x C-s is a waste of time<br />
(setq mode-compile-always-save-buffer-p t)<br />
;; make the compile window stick at 12 lines tall<br />
(setq compilation-window-height 12)<br />
<br />
;; from enberg on #emacs<br />
;; if the compilation has a zero exit code, <br />
;; the windows disappears after two seconds<br />
;; otherwise it stays<br />
(setq compilation-finish-function<br />
(lambda (buf str)<br />
(unless (string-match "exited abnormally" str)<br />
;;no errors, make the compilation window go away in a few seconds<br />
(run-at-time<br />
"2 sec" nil 'delete-windows-on<br />
(get-buffer-create "*compilation*"))<br />
(message "No Compilation Errors!"))))<br />
<br />
<br />
;; one-button testing, tada!<br />
(global-set-key [f12] 'compile)<br />
</pre-lisp><br />
<br />
<br />
This Haskell code has some Emacs local variable settings at the bottom specifying what the compile-command should be for this buffer.<br />
<haskell><br />
import HUnit<br />
import System<br />
<br />
myTestList = <br />
TestList [<br />
"add numbers" ~: 5 ~=? (3 + 2)<br />
,"add numbers" ~: 5 ~=? (3 + 3)<br />
]<br />
<br />
h = runTestTT myTestList<br />
<br />
main = do c <- h<br />
putStr $ show c<br />
let errs = errors c<br />
fails = failures c<br />
System.exitWith (codeGet errs fails)<br />
<br />
codeGet errs fails<br />
| fails > 0 = ExitFailure 2<br />
| errs > 0 = ExitFailure 1<br />
| otherwise = ExitSuccess<br />
<br />
-- Local Variables:<br />
-- compile-command: "ghc --make -o Test_Demo -i/home/shae/src/haskell/libraries/ HUnitDemo.hs && ./Test_Demo"<br />
-- End:<br />
</haskell><br />
<br />
<br />
If you have any questions, ideas, or suggestions for this code, the maintainer would love to hear them.<br />
<br />
=== Hoogle integration ===<br />
From haskell-mode version 2.4 onwards, the built-in function haskell-hoogle will hoogle the identifier at point.<br />
<br />
=== Using rectangular region commands ===<br />
<br />
Emacs has a set of commands which operate on the region as if it were rectangular. This turns out to be extremely useful when dealing with whitespace sensitive languages.<br />
<br />
<code>C-x r o</code> is "Open Rectangle". It will shift any text within the rectangle to the right side. Also see:<br />
<br />
<code>C-x r t</code> is "String Rectangle". It will shift any text within the rectangle over to the right, and insert a given string prefixing all the lines in the region. If comment-region didn't already exist, you could use this instead, for example.<br />
<br />
<code>C-x r d</code> is "Delete Rectangle". It will delete the contents of the rectangle and move anything on the right over.<br />
<br />
<code>C-x r r</code> is "Copy Rectangle to Register". It will prompt you for a register number so it can save it for later.<br />
<br />
<code>C-x r g</code> is "Insert register". This will insert the contents of the given register, overwriting whatever happens to be within the target rectangle. (So make room)<br />
<br />
<code>C-x r k</code> is "Kill rectangle". Delete rectangle and save contents for:<br />
<br />
<code>C-x r y</code> is "Yank rectangle". This will insert the contents of<br />
the last killed rectangle.<br />
<br />
As with all Emacs modifier combos, you can type <code>C-x r C-h</code> to find out what keys are bound beginning with the <code>C-x r</code> prefix.<br />
<br />
=== Aligning code ===<br />
<br />
Emacs22 has a neat tool called: align-regexp. Select a region you want to align text within, M-x align-regexp, and type a regexp representing the alignment delimiter.<br />
<br />
For example, I often line up my Haddock comments:<br />
<br />
<haskell><br />
f :: a -- ^ does a<br />
-> Foo b -- ^ and b<br />
-> c -- ^ to c<br />
</haskell><br />
<br />
Select the region, and let the regexp be: <code>--</code><br />
<br />
<haskell><br />
f :: a -- ^ does a<br />
-> Foo b -- ^ and b<br />
-> c -- ^ to c<br />
</haskell><br />
<br />
Of course, this works for just about anything. Personally, I've globally bound it to <code>C-x a r</code>:<br />
<br />
<code>(global-set-key (kbd "C-x a r") 'align-regexp)</code>.<br />
<br />
=== Automatically building ===<br />
Emacs 21 has a package that can be installed (included by default in 22 and up) called 'FlyMake'; the idea is that as you are editing away, it occasionally calls the interpreter/compiler automatically and keeps track of whether the code works or not. You can fairly easily get it to work for Haskell as well; see [http://www.emacswiki.org/cgi-bin/wiki/FlymakeHaskell FlymakeHaskell] on the Emacs wiki.<br />
<br />
=== Emacs Integration with Hayoo ===<br />
<br />
My newly installed system would not allow me to hoogle what I wanted (no xmonad or xmonadcontrib in hoogle) so someone suggested Hayoo.<br />
<br />
<code><br />
(define-key haskell-mode-map (kbd "<f3>") (lambda()(interactive)(browse-url (format "http://holumbus.fh-wedel.de/hayoo/hayoo.html?query=%s&start" (region-or-word-at-point)))))<br />
</code><br />
<br />
region-or-word-at-point is available in the thing-at-pt+.el library.<br />
<br />
Added 22-12-2008 - Promt for hayoo word<br />
<br />
<code><br />
(defun rgr/hayoo()<br />
(interactive)<br />
(let* ((default (region-or-word-at-point))<br />
(term (read-string (format "Hayoo for the following phrase (%s): "<br />
default))))<br />
(let ((term (if (zerop(length term)) default term)))<br />
(browse-url (format "http://holumbus.fh-wedel.de/hayoo/hayoo.html?query=%s&start" term)))))<br />
<br />
<br />
(define-key haskell-mode-map (kbd "<f3>") (lambda()(interactive)(rgr/hayoo)))<br />
</code><br />
<br />
Alteratively use the excellent browse-apropos-url stuff:<br />
<br />
http://www.emacswiki.org/emacs/BrowseAproposURL#toc6<br />
<br />
[http://richardriley.net Richard]<br />
<br />
Note: Using and URL like this should work too and will give better results (not yet tested as I'm not an emacs user):<br />
<br />
<code><br />
http://holumbus.fh-wedel.de/hayoo/hayoo.html?query=%s<br />
</code><br />
<br />
[[User:Tbh|Tbh]] 00:56, 25 January 2009 (UTC)<br />
<br />
=== Integration with HLint ===<br />
<br />
[http://www-users.cs.york.ac.uk/~ndm/hlint/ HLint] could be used directly from Emacs buffer. There is [http://www.cs.york.ac.uk/fp/darcs/hlint/data/hs-lint.el hs-lint.el] package (in HLint distribution, in the data subdirectory), that allows user to run HLint and navigate through errors, or apply suggestions to the source code.<br />
<br />
This package implements `hs-lint` command, that behaves differently depending on settings. If the `hs-lint-replace-with-suggestions` variable is set to `t`, then it will ask user and apply concrete suggested change to source code, otherwise you'll be able to navigate through list of suggestions with `next-error` command. If the `hs-lint-replace-without-ask` variable is also set to `t`, then all suggestions will applied automatically. <br />
<br />
You can also bind `hs-lint` command to some key (in this example this is `C-c l`) with following code:<br />
<br />
<code><br />
(defun my-haskell-mode-hook ()<br />
(local-set-key "\C-cl" 'hs-lint))<br />
(add-hook 'haskell-mode-hook 'my-haskell-mode-hook)<br />
</code><br />
<br />
All settings, described above are available for customization via `hs-lint` customization group.<br />
<br />
[[Category:Development tools]]<br />
<br />
=== Folding ===<br />
For folding parts of code you can use<br />
*'''hide-show.el'''<br />
*and '''hs-outline-level''' (based on py-outline-level created by Gb)<br />
<br />
<code><br />
;; this gets called by outline to deteremine the level. Just use the length of the whitespace<br />
(defun hsk-outline-level ()<br />
(let (buffer-invisibility-spec)<br />
(save-excursion<br />
(skip-chars-forward "\t ")<br />
(current-column))))<br />
<br />
;; this get called after haskell mode is enabled <br />
(add-hook<br />
'haskell-mode-hook<br />
'(lambda ()<br />
;; outline uses this regexp to find headers. I match lines with no indent and indented<br />
;; some lines, such as "--" ... "class"<br />
(setq outline-regexp "^[^\t ].*\\|^.*[\t ]+\\(where\\|of\\|do\\|in\\|if\\|then\\|else\\|let\\|module\\|import\\|deriving\\|instance\\|class\\)[\t\n ]")<br />
;; enable our level computation<br />
(setq outline-level 'hsk-outline-level)<br />
;; do not use their \C-c@ prefix, too hard to type. Note this overides some python mode bindings<br />
;;(setq outline-minor-mode-prefix "C-c")<br />
;; turn on outline mode<br />
(outline-minor-mode t)<br />
;; initially hide all but the headers<br />
;;(hide-body)<br />
))<br />
</code><br />
<br />
*Also, you can use '''toggle-selective-display''' for global folding<br />
<br />
<code><br />
;; folding for all rows, starting on the current column<br />
(defun toggle-selective-display (column)<br />
(interactive "P")<br />
(set-selective-display<br />
(or column<br />
(unless selective-display<br />
(1+ (current-column))))))<br />
<br />
(global-set-key (kbd "C-x $") 'toggle-selective-display)<br />
<br />
(defun toggle-hiding (column)<br />
(interactive "P")<br />
(if hs-minor-mode<br />
(if (condition-case nil<br />
(hs-toggle-hiding)<br />
(error t))<br />
(hs-show-all))<br />
(toggle-selective-display column)))<br />
<br />
(global-set-key (kbd "C-@") 'toggle-hiding)<br />
</code><br />
<br />
*and '''narrowing capabilities''' for folding the rest of code<br />
<code><br />
(put 'narrow-to-defun 'disabled nil)<br />
(put 'narrow-to-page 'disabled nil)<br />
(put 'narrow-to-region 'disabled nil)<br />
</code><br />
<br />
*or '''folding-mode''', if you do not mind add markers such as '''{-{{{-}''' and '''{-}}}-}''' in code.<br />
<br />
=== Speedbar ===<br />
<br />
Emacs has a [http://www.emacswiki.org/emacs/SpeedBar SpeedBar] which works quite nice together with haskell-mode and also detects syntactic elements such as variables, imports, instances, classes.<br />
<br />
Just add<br />
<code><br />
(require 'speedbar)<br />
(speedbar-add-supported-extension ".hs")<br />
</code><br />
to your .emacs file and fire up speedbar with <code>M-x speedbar</code>.</div>Hvrhttps://wiki.haskell.org/index.php?title=Haskell_mode_for_Emacs&diff=36816Haskell mode for Emacs2010-09-22T06:21:41Z<p>Hvr: add note about speedbar/emacs support for haskell mode</p>
<hr />
<div>haskell-mode is a major mode for Emacs and XEmacs specifically for writing Haskell code. You can get haskell-mode from the web page: http://projects.haskell.org/haskellmode-emacs/ or on Debian you can type <code>apt-get install haskell-mode</code> (although this currently doesn't have the latest version). It is currently maintained by Svein Ove Aas[http://www.mail-archive.com/haskell-cafe@haskell.org/msg66300.html].<br />
<br />
==Development Version==<br />
<br />
<code><br />
$ darcs get http://code.haskell.org/haskellmode-emacs/<br />
</code><br />
<br />
==Setup==<br />
<br />
Download and unpack the basic mode and modules into a suitable directory, e.g. <code>~/lib/emacs/haskell-mode/</code> where <code>~</code> stands for your home directory.<br />
<br />
Assuming you have placed the basic mode haskell-mode.el and the modules you want to use in the directory <code>~/lib/emacs/haskell-mode/</code>, add the following command to your init file (<code>~/.emacs</code>):<br />
<br />
<code><br />
(load "~/lib/emacs/haskell-mode/haskell-site-file")<br />
</code><br />
<br />
adding the following lines according to which modules you want to use:<br />
<br />
<code><br />
(add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)<br />
(add-hook 'haskell-mode-hook 'turn-on-haskell-indentation)<br />
;;(add-hook 'haskell-mode-hook 'turn-on-haskell-indent)<br />
;;(add-hook 'haskell-mode-hook 'turn-on-haskell-simple-indent)<br />
</code><br />
<br />
Note that the three indentation modules are mutually exclusive - add at most one. Note that the line of code for simple indentation is commented out (using a preceding ;) in preference for the more advanced indentation module. Installation is now complete!<br />
<br />
==== Inferior Mode ====<br />
<br />
Normally, inf-haskell automatically finds ghci or hugs in your <code>PATH</code>, but if that's not the case (common under Windows), or if you need to specify your preference, just tell Emacs which executable to use with:<br />
<br />
<code><br />
(setq haskell-program-name "/some/where/ghci.exe")<br />
</code><br />
<br />
If you want to use different settings when you use Cygwin Emacs and NTEmacs,<br />
you can test the value of `system-type':<br />
<br />
<code><br />
(setq haskell-program-name<br />
(if (eq system-type 'cygwin)<br />
"/cygdrive/c/ghc/ghc-6.8.1/bin/ghcii.sh"<br />
"c:/ghc/ghc-6.8.1/bin/ghci.exe"))<br />
</code><br />
<br />
Note that Cygwin binaries tend to interact poorly with NTEmacs, especially<br />
w.r.t signal-handling.<br />
<br />
==Tips and use==<br />
Handy keybindings in haskell-mode. See the documentation <code>C-h m</code> for more information:<br />
*<code>C-c C-=</code> inserts an = sign and lines up type signatures and other pattern matches nicely.<br />
*<code>C-c C-|</code> inserts a guard<br />
*<code>C-c C-o</code> inserts a guard <hask>| otherwise =</hask> and lines up existing guards<br />
*<code>C-c C-w</code> inserts a where keyword<br />
*<code>C-c C-.</code> aligns code over a region in a "sensible" fashion.<br />
<br />
Now in version 2.2:<br />
*<code>C-c C-t</code> gets :type for symbol at point, and remembers it<br />
*<code>C-u C-c C-t</code> inserts a type annotation, for symbol at point, on the line above<br />
*<code>C-c C-i</code> gets :info for symbol at point<br />
*<code>C-c M-.</code> find definition of (interpreted) symbol at point<br />
<br />
(See the section below on [[#inf-haskell.el:_the_best_thing_since_the_breadknife|inf-haskell]].)<br />
<br />
Here's an example for <code>C-c C-=</code>. Put your cursor after myInt and hit <code>C-c C-=</code><br />
<haskell><br />
blah :: Int -> Int<br />
blah myInt<br />
</haskell><br />
note how the function signature is reindented to match the column of the = sign.<br />
<haskell><br />
blah :: Int -> Int<br />
blah myInt =<br />
</haskell><br />
<br />
You could also achieve the same effect by selecting the region and typing <code>C-c C-.</code><br />
<br />
You can also use Haskell-Mode to load Emacs buffers with Haskell code in either Hugs or GHC. To load something in Hugs or ghci, type <code>C-c C-l</code> to load the file. Then, you can go on to type <code>C-c C-r</code> (or simply <code>C-c C-l</code> again) to reload the current module when you have made a change.<br />
<br />
=== Indentation ===<br />
Indentation is one thing that nearly all programming modes provide. However, indenting Haskell code is very hard: for a given line, there are nearly always more than column for which indentation makes sense. For example, imagine the following is open in a haskell-mode buffer, where <code>!</code> represents the point:<br />
<br />
<haskell><br />
foo :: Int -> String<br />
foo 0 = f 4 ++ s<br />
where f 4 = "hello" ++ <br />
!<br />
</haskell><br />
<br />
If you ask haskell-mode to indent for you, where should it indent to? There are four basic options:<br />
<br />
<ol><br />
<li><br />
You want to finish off the expression you were writing in the last line. Haskell-mode indents to be underneath the <code>"</code> character at the beginning of <code>"hello"</code>:<br />
<br />
<haskell><br />
where f 4 = "hello" ++<br />
!<br />
</haskell><br />
<br />
This is debatably a bad choice as you'd probably want to indent a bit further in to make it clear that you were carrying on an expression, but the layout rule would accept something like the following:<br />
<br />
<haskell><br />
where f 4 = "hello" ++<br />
"world"<br />
</haskell><br />
<br />
</li><br />
<li><br />
You want to add a second equation for <code>f</code>. Haskell-mode will indent to line up with the first argument, and fill in the <code>f</code> in the equation:<br />
<br />
<haskell><br />
where f 4 = "hello" ++<br />
f !<br />
</haskell><br />
<br />
This is an unlikely choice as the expression in the previous line isn't complete, but haskell-mode isn't smart enough to know that. (If <code>f</code> had been something without arguments, like <hask>where f = "hello"</hask>, then it's impossible to have more than one equation and haskell-mode won't offer this indentation level.)<br />
</li><br />
<li><br />
You want to add a second binding to the <code>where</code>-block. Haskell-mode indents to line up with the <code>f</code>:<br />
<br />
<haskell><br />
where f 4 = "hello" ++<br />
!<br />
</haskell><br />
<br />
</li><br />
<li>You want to start an entirely new top-level binding. Haskell-mode indents to the first column:<br />
<br />
<haskell><br />
foo :: Int -> String<br />
foo 0 = f 4 ++ s<br />
where f 4 = "hello" ++<br />
!<br />
</haskell><br />
<br />
</li><br />
</ol><br />
<br />
These four locations can be reached by repeatedly pressing <code>TAB</code>. This is what's known as the tab-cycle. The innermost location is offered first, then cycling progresses outwards. Although this may seem like an inefficient system (and it is indeed a shame that Haskell's design didn't result in an unambiguous indentation system), you do quickly get used to the tab-cycle and indenting Haskell code.<br />
<br />
==== indent-region ====<br />
Using indent-region is generally a bad idea on Haskell code, because it would need to know which of the tab-cycle stops you wish to choose for each line. The innermost one is chosen in each case, which often results in unusable code. Moral: just don't use indent-region with haskell-mode.<br />
<br />
==== Unicodifying symbols (Pretty Lambda for Haskell-mode) ====<br />
In Haskell code, you can end up using a lot of mathematical symbols. It is possible to hack the fontifying features of Emacs to change the ASCII textual representations of arrows and operators into the nice-looking real symbols, much like you could with TeX. The following code is a compilation of Emacs lisp code found on the Emacs wiki on the [http://www.emacswiki.org/cgi-bin/wiki/PrettyLambda#toc4 Pretty Lambda] page (that page also has examples of how to apply the general Unicode defuns to other languages):<br />
<br />
HOWEVER: due to the symbols taking up less space, this has the unfortunate side effect of changing the indentation stops that the indent key offers. This will mean that your code may not look properly aligned to those who do not have this feature in their editor, or could even mean that your code means something different to how it looks. (It is possible to contrive an example that looks correct in emacs, but actually fails to compile). The following is left for interest, but probably should NOT be used.<br />
<br />
Haskell-mode has included this feature for a long time now, so you probably just need to <code>(setq haskell-font-lock-symbols t)</code> in your .emacs to use this feature.<br />
<br />
<code><br />
(defun unicode-symbol (name)<br />
"Translate a symbolic name for a Unicode character -- e.g., LEFT-ARROW <br />
or GREATER-THAN into an actual Unicode character code. "<br />
(decode-char 'ucs (case name <br />
('left-arrow 8592)<br />
('up-arrow 8593)<br />
('right-arrow 8594)<br />
('down-arrow 8595) <br />
('double-vertical-bar #X2551) <br />
('equal #X003d)<br />
('not-equal #X2260)<br />
('identical #X2261)<br />
('not-identical #X2262)<br />
('less-than #X003c)<br />
('greater-than #X003e)<br />
('less-than-or-equal-to #X2264)<br />
('greater-than-or-equal-to #X2265) <br />
('logical-and #X2227)<br />
('logical-or #X2228)<br />
('logical-neg #X00AC) <br />
('nil #X2205)<br />
('horizontal-ellipsis #X2026)<br />
('double-exclamation #X203C)<br />
('prime #X2032)<br />
('double-prime #X2033)<br />
('for-all #X2200)<br />
('there-exists #X2203)<br />
('element-of #X2208) <br />
('square-root #X221A)<br />
('squared #X00B2)<br />
('cubed #X00B3) <br />
('lambda #X03BB)<br />
('alpha #X03B1)<br />
('beta #X03B2)<br />
('gamma #X03B3)<br />
('delta #X03B4))))<br />
<br />
(defun substitute-pattern-with-unicode (pattern symbol)<br />
"Add a font lock hook to replace the matched part of PATTERN with the <br />
Unicode symbol SYMBOL looked up with UNICODE-SYMBOL."<br />
(interactive)<br />
(font-lock-add-keywords<br />
nil `((,pattern <br />
(0 (progn (compose-region (match-beginning 1) (match-end 1)<br />
,(unicode-symbol symbol)<br />
'decompose-region)<br />
nil))))))<br />
<br />
(defun substitute-patterns-with-unicode (patterns)<br />
"Call SUBSTITUTE-PATTERN-WITH-UNICODE repeatedly."<br />
(mapcar #'(lambda (x)<br />
(substitute-pattern-with-unicode (car x)<br />
(cdr x)))<br />
patterns))<br />
<br />
(defun haskell-unicode ()<br />
(interactive)<br />
(substitute-patterns-with-unicode<br />
(list (cons "\\(<-\\)" 'left-arrow)<br />
(cons "\\(->\\)" 'right-arrow)<br />
(cons "\\(==\\)" 'identical)<br />
(cons "\\(/=\\)" 'not-identical)<br />
(cons "\\(()\\)" 'nil)<br />
(cons "\\<\\(sqrt\\)\\>" 'square-root)<br />
(cons "\\(&&\\)" 'logical-and)<br />
(cons "\\(||\\)" 'logical-or)<br />
(cons "\\<\\(not\\)\\>" 'logical-neg)<br />
(cons "\\(>\\)\\[^=\\]" 'greater-than)<br />
(cons "\\(<\\)\\[^=\\]" 'less-than)<br />
(cons "\\(>=\\)" 'greater-than-or-equal-to)<br />
(cons "\\(<=\\)" 'less-than-or-equal-to)<br />
(cons "\\<\\(alpha\\)\\>" 'alpha)<br />
(cons "\\<\\(beta\\)\\>" 'beta)<br />
(cons "\\<\\(gamma\\)\\>" 'gamma)<br />
(cons "\\<\\(delta\\)\\>" 'delta)<br />
(cons "\\(<nowiki>''</nowiki>\\)" 'double-prime)<br />
(cons "\\('\\)" 'prime)<br />
(cons "\\(!!\\)" 'double-exclamation)<br />
(cons "\\(\\.\\.\\)" 'horizontal-ellipsis))))<br />
<br />
(add-hook 'haskell-mode-hook 'haskell-unicode)</code><br />
<br />
== Bugs ==<br />
Bugs and feature requests should be sent to the maintainer [mailto:svein.ove@aas.no Svein Ove Aas].<br />
For people using the Debian package, Debian maintains a [http://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=haskell-mode list of bugs] for haskell-mode, they should be reported there.<br />
<br />
===XEmacs===<br />
On some the GNU/Linux systems with XEmacs, admittedly, only verified on Ubuntu and Debian and with haskell-mode 2.2, there is a system function missing that interferes with automatic indenting. Secondly, there seems to be an issue with setting the <code-lisp>haskell-default-face</code-lisp> to <code-lisp>nil</code-lisp>.<br />
<br />
====line-end-position====<br />
<br />
To fix this, find where the haskell mode package is installed on your system. (Usually <code>/usr/share/emacs/site-lisp/haskell-mode</code>). Edit the file <code>haskell-indent.el</code> and add the lines:<br />
<pre-lisp><br />
(eval-and-compile<br />
<br />
;; If `line-end-position' isn't available provide one.<br />
(unless (fboundp 'line-end-position)<br />
(defun line-end-position (&optional n)<br />
"Return the `point' of the end of the current line."<br />
(save-excursion<br />
(end-of-line n)<br />
(point)))))<br />
</pre-lisp><br />
right after the comments at the top. That should fix the issue.<br />
<br />
====haskell-default-face====<br />
<br />
This one shows up when typing in code (at various spots - most often when typing a qualified function, such as <hask>List.map</hask>.)<br />
<br />
To fix this one, edit the file <code>haskell-font-lock.el</code>. Look for the line that says:<br />
<pre-lisp><br />
(defvar haskell-default-face nil)<br />
</pre-lisp><br />
and change this to <br />
<pre-lisp><br />
(defvar haskell-default-face 'default)<br />
</pre-lisp><br />
In my version, this is line 168.<br />
<br />
Then, look for the line that says:<br />
<pre-lisp><br />
(,qvarid 0 haskell-default-face)<br />
</pre-lisp><br />
and change it to<br />
<pre-lisp><br />
(,qvarid 0 (symbol-value 'haskell-default-face))<br />
</pre-lisp><br />
<br />
For me, this is line 326 of the file.<br />
YMMV - hope this helps.<br />
<br />
<!--<br />
=== GNU Emacs ===<br />
<br />
==== ghci buffer infested with "^J"s, C-c C-t doesn't work ====<br />
<br />
(only happens after loading a haskell file into ghci)<br />
<br />
--><br />
<br />
<br />
== inf-haskell.el: the best thing since the breadknife ==<br />
inf-haskell.el is _awesome_. At one point I decided to sit down and write a list of functions I'd love to have in haskell-mode, intending to write them myself. I thought I'd check to see whether the key shortcuts I'd chosen were free but I was surprised to find that ''every one'' of these functions is already provided by inf-haskell.el! Here's a selection of the highlights:<br />
<br />
=== Getting set up ===<br />
inf-haskell.el is usually already setup as part of the haskell-mode package, so there is nothing special to do for it. On some systems, you may need this in your .emacs:<br />
<br />
<pre-lisp><br />
(require 'inf-haskell)<br />
</pre-lisp><br />
<br />
To use the following functions, first find a .hs file, then hit C-c C-l (inferior-haskell-load-file). This fires up Hugs or Ghci (you can change this by customising haskell-program-name) on your file. Don't worry if it's not an isolated module, GHCi will load all the modules it imports as normal. You can even load entire programs this way by using C-c C-l on the Main.hs file. If everything loads without errors, you'll be able to use the functions below.<br />
<br />
=== inferior-haskell-type (C-c C-t) ===<br />
Say you have the following code:<br />
<br />
foo = foldr (+) 0 [1..20]<br />
<br />
Perhaps you've forgotten the order of arguments to foldr. It's easily done; I can never remember whether the operation or final value comes first. That's easy to check: just put your point between the 'f' and 'r' of 'foldr' and hit C-c C-t RET. The type of foldr will be revealed in the echo area. This isn't particularly impressive; haskell-doc.el already did this. However, this will work for ''any'' function in the module in question ''or'' in those modules imported by the current module (including the standard libs)!<br />
<br />
If you find that the type shown in the echo area is overwritten after a short amount of time (or any other such problem, of course), please report it as a bug. We know of no such bug, but someone apparently bumped into some such problem which he says he worked around by disabling doc-mode and decl-scan:<br />
<br />
To turn off haskell-doc-mode, add the following to your .emacs:<br />
<pre-lisp><br />
(remove-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)<br />
</pre-lisp><br />
To turn off haskell-decl-scan, just refrain from turning it on (it's not enabled by default).<br />
<br />
(P.S. I re-use haskell-doc-mode to save queried type info, and re-display it in the minibuffer. Disabling doc mode would disable that. -- mrd)<br />
<br />
Another nice feature of this function is the ability to automatically insert type signatures for the function at point on the line above. For example, suppose you have the below open in Emacs, with the point represented by -!-:<br />
<br />
-!-map _ [] = []<br />
map f (x:xs) = f x : map f xs<br />
<br />
And press C-u C-c C-t (note the prefix argument), it will result in the following:<br />
<br />
map :: (a -> b) -> [a] -> [b]<br />
-!-map _ [] = []<br />
map f (x:xs) = f x : map f xs<br />
<br />
=== inferior-haskell-info (C-c C-i) ===<br />
The :info command in GHCi/Hugs is extremely useful; it'll tell you:<br />
<br />
* The definition of an algebraic datatype given its name. E.g. try <code>:info Bool</code>. The output will contain something like <code>data Bool = True | False</code>.<br />
* The classes a type instantiates given the type's name. <code>:info Bool</code> will also give you the classes Bool instantiates. If you can't see an instance you think should be there, make sure the module where that instance is declared is loaded.<br />
* The type of a function, given its name.<br />
* The types of the methods of a class, and the number of arguments of that class, given the class name.<br />
* The expansion of a type synonym given that synonym's name.<br />
<br />
And for all of the above, :info will also tell you the filename and line where that thing is defined. inferior-haskell-info lets you hook into this power. Use it with C-c C-i on anything within a Haskell file.<br />
<br />
=== inferior-haskell-find-definition (C-c M-.) ===<br />
This one needs little explanation. Sometimes you just need to find the source of a function, or datatype, or class, or type synonym etc. to see how it works, and this function lets you do just that. Unfortunately, it won't work on the standard lib modules or anything that isn't 'local' to your project. This is one of the most useful functions inf-haskell.el provides.<br />
<br />
(Basically, it only works on interpreted code, for which ghci has location information. If you want a more general find-definition, use hasktags to create a TAGS file and then use the normal emacs <code>M-.</code> with that. -- mrd)<br />
: Note that you can also create a TAGS file using GHCi's :etags command. [[User:DavidHouse|DavidHouse]] 14:38, 29 April 2007 (UTC)<br />
<br />
: Again, :etags/:ctags only works for interpreted code.<br />
<br />
: <code>inferior-haskell-mode</code> is missing TAB completion, which in GHCi works basically for everything (GHCi commands, modules, functions, language extensions, file names etc.). -- Oleksandr Manzyuk<br />
<br />
== Tricks and tweaks ==<br />
<br />
=== Automatic unit testing ===<br />
Here's a cute trick I've evolved:<br />
<br />
I'm a great fan of [[unit test first]], as described by eXtremeProgramming on TheOriginalWiki.<br />
<br />
With the code below, I can press F12 and immediately run all of my unit tests, and immediately see whether they all passed or not.<br />
I've put all of my unit tests into their own file with a main function that runs the tests and gives an exitcode according to the test results. I've specified that the compile-command for that file compiles and runs the file.<br />
<br />
This elisp code will run the <code>compile</code> command from the F12 key in emacs. The output will popup a new window twelve lines tall. If the compilation is successful (exitcode zero) the window goes away. If the exitcode is 1 or greater, the window stays so you can see the output.<br />
<pre-lisp><br />
(require 'compile)<br />
<br />
;; this means hitting the compile button always saves the buffer<br />
;; having to separately hit C-x C-s is a waste of time<br />
(setq mode-compile-always-save-buffer-p t)<br />
;; make the compile window stick at 12 lines tall<br />
(setq compilation-window-height 12)<br />
<br />
;; from enberg on #emacs<br />
;; if the compilation has a zero exit code, <br />
;; the windows disappears after two seconds<br />
;; otherwise it stays<br />
(setq compilation-finish-function<br />
(lambda (buf str)<br />
(unless (string-match "exited abnormally" str)<br />
;;no errors, make the compilation window go away in a few seconds<br />
(run-at-time<br />
"2 sec" nil 'delete-windows-on<br />
(get-buffer-create "*compilation*"))<br />
(message "No Compilation Errors!"))))<br />
<br />
<br />
;; one-button testing, tada!<br />
(global-set-key [f12] 'compile)<br />
</pre-lisp><br />
<br />
<br />
This Haskell code has some Emacs local variable settings at the bottom specifying what the compile-command should be for this buffer.<br />
<haskell><br />
import HUnit<br />
import System<br />
<br />
myTestList = <br />
TestList [<br />
"add numbers" ~: 5 ~=? (3 + 2)<br />
,"add numbers" ~: 5 ~=? (3 + 3)<br />
]<br />
<br />
h = runTestTT myTestList<br />
<br />
main = do c <- h<br />
putStr $ show c<br />
let errs = errors c<br />
fails = failures c<br />
System.exitWith (codeGet errs fails)<br />
<br />
codeGet errs fails<br />
| fails > 0 = ExitFailure 2<br />
| errs > 0 = ExitFailure 1<br />
| otherwise = ExitSuccess<br />
<br />
-- Local Variables:<br />
-- compile-command: "ghc --make -o Test_Demo -i/home/shae/src/haskell/libraries/ HUnitDemo.hs && ./Test_Demo"<br />
-- End:<br />
</haskell><br />
<br />
<br />
If you have any questions, ideas, or suggestions for this code, the maintainer would love to hear them.<br />
<br />
=== Hoogle integration ===<br />
From haskell-mode version 2.4 onwards, the built-in function haskell-hoogle will hoogle the identifier at point.<br />
<br />
=== Using rectangular region commands ===<br />
<br />
Emacs has a set of commands which operate on the region as if it were rectangular. This turns out to be extremely useful when dealing with whitespace sensitive languages.<br />
<br />
<code>C-x r o</code> is "Open Rectangle". It will shift any text within the rectangle to the right side. Also see:<br />
<br />
<code>C-x r t</code> is "String Rectangle". It will shift any text within the rectangle over to the right, and insert a given string prefixing all the lines in the region. If comment-region didn't already exist, you could use this instead, for example.<br />
<br />
<code>C-x r d</code> is "Delete Rectangle". It will delete the contents of the rectangle and move anything on the right over.<br />
<br />
<code>C-x r r</code> is "Copy Rectangle to Register". It will prompt you for a register number so it can save it for later.<br />
<br />
<code>C-x r g</code> is "Insert register". This will insert the contents of the given register, overwriting whatever happens to be within the target rectangle. (So make room)<br />
<br />
<code>C-x r k</code> is "Kill rectangle". Delete rectangle and save contents for:<br />
<br />
<code>C-x r y</code> is "Yank rectangle". This will insert the contents of<br />
the last killed rectangle.<br />
<br />
As with all Emacs modifier combos, you can type <code>C-x r C-h</code> to find out what keys are bound beginning with the <code>C-x r</code> prefix.<br />
<br />
=== Aligning code ===<br />
<br />
Emacs22 has a neat tool called: align-regexp. Select a region you want to align text within, M-x align-regexp, and type a regexp representing the alignment delimiter.<br />
<br />
For example, I often line up my Haddock comments:<br />
<br />
<haskell><br />
f :: a -- ^ does a<br />
-> Foo b -- ^ and b<br />
-> c -- ^ to c<br />
</haskell><br />
<br />
Select the region, and let the regexp be: <code>--</code><br />
<br />
<haskell><br />
f :: a -- ^ does a<br />
-> Foo b -- ^ and b<br />
-> c -- ^ to c<br />
</haskell><br />
<br />
Of course, this works for just about anything. Personally, I've globally bound it to <code>C-x a r</code>:<br />
<br />
<code>(global-set-key (kbd "C-x a r") 'align-regexp)</code>.<br />
<br />
=== Automatically building ===<br />
Emacs 21 has a package that can be installed (included by default in 22 and up) called 'FlyMake'; the idea is that as you are editing away, it occasionally calls the interpreter/compiler automatically and keeps track of whether the code works or not. You can fairly easily get it to work for Haskell as well; see [http://www.emacswiki.org/cgi-bin/wiki/FlymakeHaskell FlymakeHaskell] on the Emacs wiki.<br />
<br />
=== Emacs Integration with Hayoo ===<br />
<br />
My newly installed system would not allow me to hoogle what I wanted (no xmonad or xmonadcontrib in hoogle) so someone suggested Hayoo.<br />
<br />
<code><br />
(define-key haskell-mode-map (kbd "<f3>") (lambda()(interactive)(browse-url (format "http://holumbus.fh-wedel.de/hayoo/hayoo.html?query=%s&start" (region-or-word-at-point)))))<br />
</code><br />
<br />
region-or-word-at-point is available in the thing-at-pt+.el library.<br />
<br />
Added 22-12-2008 - Promt for hayoo word<br />
<br />
<code><br />
(defun rgr/hayoo()<br />
(interactive)<br />
(let* ((default (region-or-word-at-point))<br />
(term (read-string (format "Hayoo for the following phrase (%s): "<br />
default))))<br />
(let ((term (if (zerop(length term)) default term)))<br />
(browse-url (format "http://holumbus.fh-wedel.de/hayoo/hayoo.html?query=%s&start" term)))))<br />
<br />
<br />
(define-key haskell-mode-map (kbd "<f3>") (lambda()(interactive)(rgr/hayoo)))<br />
</code><br />
<br />
Alteratively use the excellent browse-apropos-url stuff:<br />
<br />
http://www.emacswiki.org/emacs/BrowseAproposURL#toc6<br />
<br />
[http://richardriley.net Richard]<br />
<br />
Note: Using and URL like this should work too and will give better results (not yet tested as I'm not an emacs user):<br />
<br />
<code><br />
http://holumbus.fh-wedel.de/hayoo/hayoo.html?query=%s<br />
</code><br />
<br />
[[User:Tbh|Tbh]] 00:56, 25 January 2009 (UTC)<br />
<br />
=== Integration with HLint ===<br />
<br />
[http://www-users.cs.york.ac.uk/~ndm/hlint/ HLint] could be used directly from Emacs buffer. There is [http://www.cs.york.ac.uk/fp/darcs/hlint/data/hs-lint.el hs-lint.el] package (in HLint distribution, in the data subdirectory), that allows user to run HLint and navigate through errors, or apply suggestions to the source code.<br />
<br />
This package implements `hs-lint` command, that behaves differently depending on settings. If the `hs-lint-replace-with-suggestions` variable is set to `t`, then it will ask user and apply concrete suggested change to source code, otherwise you'll be able to navigate through list of suggestions with `next-error` command. If the `hs-lint-replace-without-ask` variable is also set to `t`, then all suggestions will applied automatically. <br />
<br />
You can also bind `hs-lint` command to some key (in this example this is `C-c l`) with following code:<br />
<br />
<code><br />
(defun my-haskell-mode-hook ()<br />
(local-set-key "\C-cl" 'hs-lint))<br />
(add-hook 'haskell-mode-hook 'my-haskell-mode-hook)<br />
</code><br />
<br />
All settings, described above are available for customization via `hs-lint` customization group.<br />
<br />
[[Category:Development tools]]<br />
<br />
=== Folding ===<br />
For folding parts of code you can use<br />
*'''hide-show.el'''<br />
*and '''hs-outline-level''' (based on py-outline-level created by Gb)<br />
<br />
<code><br />
;; this gets called by outline to deteremine the level. Just use the length of the whitespace<br />
(defun hsk-outline-level ()<br />
(let (buffer-invisibility-spec)<br />
(save-excursion<br />
(skip-chars-forward "\t ")<br />
(current-column))))<br />
<br />
;; this get called after haskell mode is enabled <br />
(add-hook<br />
'haskell-mode-hook<br />
'(lambda ()<br />
;; outline uses this regexp to find headers. I match lines with no indent and indented<br />
;; some lines, such as "--" ... "class"<br />
(setq outline-regexp "^[^\t ].*\\|^.*[\t ]+\\(where\\|of\\|do\\|in\\|if\\|then\\|else\\|let\\|module\\|import\\|deriving\\|instance\\|class\\)[\t\n ]")<br />
;; enable our level computation<br />
(setq outline-level 'hsk-outline-level)<br />
;; do not use their \C-c@ prefix, too hard to type. Note this overides some python mode bindings<br />
;;(setq outline-minor-mode-prefix "C-c")<br />
;; turn on outline mode<br />
(outline-minor-mode t)<br />
;; initially hide all but the headers<br />
;;(hide-body)<br />
))<br />
</code><br />
<br />
*Also, you can use '''toggle-selective-display''' for global folding<br />
<br />
<code><br />
;; folding for all rows, starting on the current column<br />
(defun toggle-selective-display (column)<br />
(interactive "P")<br />
(set-selective-display<br />
(or column<br />
(unless selective-display<br />
(1+ (current-column))))))<br />
<br />
(global-set-key (kbd "C-x $") 'toggle-selective-display)<br />
<br />
(defun toggle-hiding (column)<br />
(interactive "P")<br />
(if hs-minor-mode<br />
(if (condition-case nil<br />
(hs-toggle-hiding)<br />
(error t))<br />
(hs-show-all))<br />
(toggle-selective-display column)))<br />
<br />
(global-set-key (kbd "C-@") 'toggle-hiding)<br />
</code><br />
<br />
*and '''narrowing capabilities''' for folding the rest of code<br />
<code><br />
(put 'narrow-to-defun 'disabled nil)<br />
(put 'narrow-to-page 'disabled nil)<br />
(put 'narrow-to-region 'disabled nil)<br />
</code><br />
<br />
*or '''folding-mode''', if you do not mind add markers such as '''{-{{{-}''' and '''{-}}}-}''' in code.<br />
<br />
=== Speedbar ===<br />
<br />
Emacs has a [http://www.emacswiki.org/emacs/SpeedBar SpeedBar] which works quite nice together with haskell-mode and also detects syntactic elements such as variables, imports, instances, classes.<br />
<br />
Just add<br />
<code><br />
(require 'speedbar)<br />
(speedbar-add-supported-extension ".hs")<br />
</code><br />
to your .emacs file and fire up speedbar with <code>M-x speedbar</code>.</div>Hvrhttps://wiki.haskell.org/index.php?title=Structure_of_a_Haskell_project&diff=36767Structure of a Haskell project2010-09-14T15:49:12Z<p>Hvr: </p>
<hr />
<div>[[Category:Applications]]<br />
[[Category:Tutorials]]<br />
The intention behind this page is to flesh out some semi-standard for<br />
the directory structure, and the tool-setup for medium to large-sized<br />
Haskell projects. It is intended to make it easier for newcomers to<br />
start up projects, and for everybody to navigate others projects. Newcomers should also read [[How to write a Haskell program]] for more detailed instructions on setting up a new project.<br />
<br />
Especially I hope some focus can be made on how to make the different<br />
tools play well together, and giving the project structure that allows<br />
scaling.<br />
<br />
Hopefully someone more qualified than I (the initiator of this page)<br />
will be summoned and write their advices, change the faults, add<br />
missing bits and discuss differences in opinions.<br />
<br />
And perhaps a sample project (in the spirit of HNop, but with broader<br />
ambitions) should be made, so that can be used as a template.<br />
<br />
== Tools ==<br />
It is recommended to make use the following tool chain:<br />
* [[Darcs]] for revision control<br />
* [[Cabal]] for managing builds, tests and haddock'ing <br />
* [[QuickCheck]] and [[SmallCheck]] for auto-generated test-cases<br />
* [[HUnit]] for hand-coded tests<br />
* [[Haddock]] for generating API documents '''or''' [[Literate programming]] combined with latex for thorough documentation of the code<br />
<br />
== Directory Structure ==<br />
<br />
For a project called app an outline the directory structure should<br />
look like this (inspired by looking at projects like [[GHC]], PUGS, Yi,<br />
[[Haskore]], Hmp3, Fps):<br />
<br />
<pre><br />
app/ -- Root-dir<br />
src/ -- For keeping the sourcecode<br />
Main.lhs -- The main-module<br />
App/ -- Use hierarchical modules<br />
...<br />
Win32/ -- For system dependent stuff<br />
Unix/<br />
cbits/ -- For C code to be linked to the haskell program<br />
testsuite/ -- Contains the testing stuff<br />
runtests.sh -- Will run all tests<br />
tests/ -- For unit-testing and checking<br />
App/ -- Clone the module hierarchy, so that there is one <br />
testfile per sourcefile<br />
benchmarks/ -- For testing performance<br />
doc/ -- Contains the manual, and other documentation<br />
examples/ -- Example inputs for the program<br />
dev/ -- Information for new developers about the project, <br />
and eg. related literature<br />
util/ -- Auxiliary scripts for various tasks<br />
dist/ -- Directory containing what end-users should get<br />
build/ -- Contains binary files, created by cabal<br />
doc/ -- The haddock documentation goes here, created by cabal<br />
resources/ -- Images, soundfiles and other non-source stuff<br />
used by the program<br />
_DARCS/ <br />
README -- Textfile with short introduction of the project<br />
INSTALL -- Textfile describing how to build and install<br />
TODO -- Textfile describing things that ought to be done<br />
AUTHORS -- Textfile containing info on who does and has done <br />
what in this project, and their contact info<br />
LICENSE -- Textfile describing licensing terms for this project<br />
app.cabal -- Project-description-file for cabal<br />
Setup.hs -- Program for running cabal commands<br />
</pre><br />
<br />
== Technicalities ==<br />
=== The sourcefiles ===<br />
<br />
* It is recommended to write sourcefiles in plain ascii or UTF-8 with unix line-endings using only spaces (and not tabs) for indentation.<br />
* The interface (everything a module exports) should be commented in english with haddock comments.<br />
* All of the code should be a large latex document going through the code and explaining it. The latex markup should be kept light, so that it is stil readable in an editor. The main module should include all of the files somehow.<br />
* The modules should have explicit export-lists<br />
* Explicit type-annotations should be given for all top-level definitions.<br />
<br />
== Discussions ==<br />
=== Why not use lhs2Tex ===<br />
<br />
Some short experiments showed that lhs2Tex is not too happy about<br />
haddock-comments, and since these two techniques of commenting are<br />
orthogonal something else should be chosen. Eg. [http://www.acooke.org/jara/pancito/haskell.sty latex.sty]<br />
<br />
=== How is the testing framework best made? ===<br />
<br />
Here should be a recipe for making a test-framework with both<br />
HUnit-tests an QuickCheck properties, that can all be run with a<br />
simple command, and how to make darcs use that for testing before<br />
recording.<br />
<br />
[http://www.informatik.uni-freiburg.de/~wehr/software/haskell/#HTF_-_The_Haskell_Test_Framework HTF] attempts to be such a test-framework, but is currently woefully under documented (although there's a tutorial hidden in the documentation for Test.Framework.Tutorial).<br />
<br />
Alternatively, [http://batterseapower.github.com/test-framework/ test-framework] has a similiar function as HTF.</div>Hvr