https://wiki.haskell.org/api.php?action=feedcontributions&user=Jameshfisher&feedformat=atomHaskellWiki - User contributions [en]2021-09-17T08:28:14ZUser contributionsMediaWiki 1.27.4https://wiki.haskell.org/index.php?title=HsLua&diff=58617HsLua2014-07-27T16:42:02Z<p>Jameshfisher: /* Example 1: running Lua scripts */ reword strange phrasing</p>
<hr />
<div>What is Lua? It's a scripting language (like Perl) targeted to be<br />
easily integrated into any host application. You can do it in<br />
literally 5 minutes. let's try:<br />
<br />
== Example 1: running Lua scripts ==<br />
<br />
First, you need to download and unpack the brilliant HsLua package [1]<br />
written by Gracjan Polak:<br />
http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hslua<br />
<br />
As usual, in order to build and install Cabalized package, run commands:<br />
<haskell><br />
runhaskell Setup.hs configure<br />
runhaskell Setup.hs build<br />
runhaskell Setup.hs install<br />
</haskell><br />
(Assuming that you have ghc 6.6 or 6.8 installed)<br />
<br />
<br />
The simplest work where Lua may be handy is in replacing application<br />
config files with scripts. This allows one to define complex data<br />
structures and utilize the power of a full-fledged programming language. For<br />
example, the following "config" file, written in Lua:<br />
<br />
<haskell><br />
username = os.getenv("USER") or "God"<br />
password = os.getenv("PWD") or "dontdisturb"<br />
</haskell><br />
<br />
assigns to variables "username" and "password" values read from<br />
environment vars USER/PWD, but substitutes default values if they are<br />
not defined. The following Haskell program demonstrates how to get<br />
your hands on values defined in such an unusual way:<br />
<br />
<haskell><br />
import qualified Scripting.Lua as Lua<br />
main = do<br />
l <- Lua.newstate<br />
Lua.openlibs l<br />
<br />
Lua.dofile l "configfile.lua"<br />
Right name <- Lua.dostring l "return username"<br />
Right pwd <- Lua.dostring l "return password"<br />
<br />
print (name::String, pwd::String)<br />
Lua.close l<br />
</haskell><br />
<br />
Voila! Are you finished in 5 minutes? :)<br />
<br />
<br />
What we are doing here? First, we create new instance of Lua<br />
interpreter using "newstate". Lua implementation doesn't use global<br />
vars, which means that you can create as many Lua instances as you need<br />
and run them all simultaneously.<br />
<br />
Then, "openlibs" imports built-in Lua functions into this instance.<br />
Note that fresh Lua instances only have access to a dozen standard<br />
(arithmetic) operations. By careful selection of functions provided<br />
to the Lua instance, you can turn it into sandbox - e.g. disallow access<br />
to file system, network connections and so on, or provide special<br />
functions which can access only specific directory/host/whatever.<br />
<br />
The next operation, "dofile", runs script from file specified. This script<br />
defines variables "username" and "password" that we then read using<br />
"eval". Finally, "close" destructs the Lua instance, freeing memory it has<br />
grabbed.<br />
<br />
== Example 2: calling from Haskell to Lua ==<br />
<br />
Now imagine that we need more complex config capable of providing for<br />
each site we have an account in its own user/pwd pair. We can write it either<br />
as an associative table, or as a function mapping site name to user/pwd.<br />
Let's combine both approaches:<br />
<br />
<haskell><br />
function getuserpwd (site)<br />
local cookies = { ["www.ibm.com"] = {"joe", "secret"}<br />
, ["www.sun.com"] = {"hoe", "another secret"}<br />
}<br />
if cookies[site] then<br />
return cookies[site]<br />
elseif site:match("[.]google[.]com$") then<br />
return {"boss", "boss"}<br />
else<br />
return { os.getenv("USER") or "God"<br />
, os.getenv("PWD") or "dontdisturb" }<br />
end<br />
end<br />
</haskell><br />
<br />
and replace in the first Haskell program, the reading of variables with a call to the new function 'getuserpwd':<br />
<br />
<haskell><br />
[name,pwd] <- Lua.callfunc l "getuserpwd" "mail.google.com"<br />
</haskell><br />
<br />
<br />
== Example 3: calling from Lua to Haskell ==<br />
<br />
But that's not the whole story. When Lua is used as a scripting language<br />
inside your application, the communication should be two-forked.<br />
Imagine, for example, that you develop a game and Lua scripts are used<br />
to control game characters. While the Lua script fully defines their<br />
behavioural logic, it should command something that will render this<br />
behaviour to the player. Just for example:<br />
<br />
<haskell><br />
for i=1,3 do<br />
move( 1, "forward")<br />
move( 2, "backward")<br />
end<br />
</haskell><br />
<br />
This script commands our character to go 1 step forward, 2 steps backward<br />
repeating this 3 times. The "move" procedure here should be defined<br />
on Haskell side to show his behaviour. Let's go:<br />
<br />
<haskell><br />
import qualified Scripting.Lua as Lua<br />
<br />
hsMove :: Int -> String -> IO ()<br />
hsMove n direction = do<br />
putStrLn$ "going "++show n++" step(s) "++direction<br />
<br />
main = do<br />
l <- Lua.newstate<br />
<br />
Lua.register l "move" hsMove<br />
Lua.dofile l "game.lua"<br />
<br />
Lua.close l<br />
</haskell><br />
<br />
The only new call here is "register" which registers Haskell function<br />
in Lua instance. Please note that we may call any Lua<br />
function/procedure from Haskell (as we've done in previous example)<br />
and register any Haskell procedure in Lua as far as their arguments<br />
and results has simple enough types (numbers, strings, booleans, lists<br />
and maps). In such simple cases HsLua takes in its hands all the<br />
conversions of data between Haskell and Lua worlds.<br />
<br />
Also note that we omitted here a call to "openlibs", making Lua instance<br />
a real sandbox - all the communication with external world that script<br />
can do is to move it, move it :)<br />
<br />
== Exchanging data between Haskell and Lua worlds ==<br />
<br />
Lua variables have dynamic types. When we cast these values from/to<br />
Haskell world, they are mapped to the appropriate Haskell types. Type<br />
class StackValue covers Haskell types that can be casted from/to Lua<br />
values and defines the casting rules. Predefined class instances<br />
include Int, Double, String, Bool, [a] for lists and [(a,b)] for maps<br />
where a and b may be any StackValue types again. There is also an <br />
existential class wrapper XXX that allows to pass heterogeneous<br />
collections (lists/maps) from Haskell to Lua:<br />
<br />
<haskell><br />
Lua.callproc "foo" [XXX True, XXX "str", XXX [1,2,3]]<br />
Lua.callproc "bar" [(XXX 1, XXX True), (XXX 2, XXX "str"), (XXX "tag", XXX 3.14])]<br />
</haskell><br />
<br />
HsLua includes two operations which just execute operators in context<br />
of a given Lua instance: "dofile" and "dostring" (executing contents of<br />
file and string, respectively). They return 0 on success and errcode<br />
otherwise:<br />
<br />
<haskell><br />
dofile :: LuaState -> String -> IO Int<br />
dostring :: LuaState -> String -> IO Int<br />
</haskell><br />
<br />
Two other operations return result of executing string/file: "eval"<br />
and "evalfile", respectively. "eval" may also be used to evaluate<br />
expressions, as it was done in our first script. These operations<br />
return (Right a) on success, where "a" may be any type belonging to<br />
StackValue class. On an error they return (Left Int) where Int will be<br />
either errcode or 0 if casting was unsuccessful:<br />
<br />
<haskell><br />
eval :: (StackValue a) => LuaState -> String -> Either Int a<br />
evalfile :: (StackValue a) => LuaState -> String -> Either Int a<br />
</haskell><br />
<br />
The next pair of operations is "callfunc" and "callproc". They both call a<br />
Lua function passing to it arbitrary number of arguments. The only<br />
difference is that "callfunc" returns and "callproc" omits the return<br />
value of Lua function called:<br />
<br />
<haskell><br />
callfunc :: (StackValue x1, x2 ... xn, a) =><br />
LuaState -> String -> x1 -> x2 ... xn -> Either Int a<br />
callproc :: (StackValue x1, x2 ... xn) =><br />
LuaState -> String -> x1 -> x2 ... xn -> IO Int<br />
</haskell><br />
<br />
Finally, "register" operation registers in the Lua world any Haskell<br />
function/procedure that receives and returns values of StackValue types:<br />
<br />
<haskell><br />
register :: (StackValue x1, x2 ... xn, a) =><br />
LuaState -> String -> (x1 -> x2 ... xn -> {IO} a) -> IO Int<br />
</haskell><br />
<br />
where {IO} means that the IO specifier is optional here. n>=0, i.e.<br />
register/callfunc/callproc may also register/call functions having<br />
no arguments.<br />
<br />
<br />
== About Lua ==<br />
<br />
A few words about Lua as a language. It's rather close to<br />
Perl/Python/Ruby, the main difference is Lua's compactness. In<br />
particular, HsLua will add only about 200kb to your program. The Lua<br />
syntax definition is just about 40 lines long and omits many modern<br />
features such as exception handling or OOP. It provides simple means<br />
for doing simple tasks that made it perfect tool for non-professional<br />
programmers<br />
<br />
But the first impression fools you. Lua is a wolf in sheep's hide. As<br />
its author said, "Lua provides Modula syntax but Scheme semantics".<br />
The main distinctive feature of Lua is its extensibility. It provides<br />
'''semantical''' base for implementation of exceptions, OOP, data hiding,<br />
metaprogramming, persistency, functional programming, lazy evaluation,<br />
concurrency/coroutines/iterators. But special syntax for advanced<br />
features is almost non-existent and in many cases Lua gives you only<br />
a base on which you have to build yourself. For example, OOP inheritance<br />
isn't implemented but there are libraries implementing single and<br />
multiple inheritance just by manipulating metatables. So while you can<br />
learn Lua basics in a few minutes, I recommend you to spend a few days<br />
before making a final decision.<br />
<br />
<br />
== More about Lua ==<br />
<br />
If you want to know more about Lua, you can jump to the online book<br />
written by main developer of Lua and describing Lua 5.0 at<br />
http://www.lua.org/pil/ or buy new version of this book describing Lua<br />
5.1 (current version) from Amazon [2]<br />
<br />
The official Lua 5.1 manual is at http://www.lua.org/manual/5.1/ - it's<br />
clearly written but definitely not the best place to start<br />
<br />
If you need to perform more complex tasks using HsLua library, you<br />
should study C API for Lua at http://www.lua.org/pil/index.html#24 -<br />
the low-level part of HsLua mainly duplicates this API<br />
<br />
For me the most interesting part of Lua site is the list of Lua<br />
libraries, IDEs and other tools at http://lua-users.org/wiki/LuaAddons<br />
<br />
I want to shortly introduce things there that were most exciting for me:<br />
* LuaBinaryModules - compiling C library for Lua into self-described dll/so<br />
* LuaJIT - increase execution speed up to 7 times<br />
* wxLua - binding to wxWidgets and IDE with debugger and C bindings generator<br />
* MetaLua - alternative Lua frontend with FP features and extensible syntax<br />
<br />
<br />
=== [[http://lua-users.org/wiki/LuaBinaryModules LuaBinaryModules]] ===<br />
<br />
If a user of your application wants to use some Lua library written in<br />
Lua itself, that's easy - just put the source file into program<br />
directory. But what about libraries containing C parts?<br />
LuaBinaryModules solves this problem - it allows to compile any<br />
library for Lua to a dll/so file which may be imported by any Lua<br />
instance to get full library functionality. Technically speaking, LBM<br />
just adds one more function which registers all library functions and<br />
this function is called automatically by LuaBinaryModules loader<br />
<br />
As a result, LuaBinaryModules allows users of your application to<br />
install any libraries they need just by copying their dll/so files<br />
into application directory.<br />
<br />
=== LuaJIT ===<br />
<br />
While Lua bytecode interpreter being register-based VM is fastest<br />
among all dynamic languages, sometimes you need even more speed.<br />
LuaJIT compiles bytecode instructions into x86 code, improving speed<br />
up to 7 times (as tested on Great Language Shootout examples). One of<br />
its interesting features is automatic function specialization to the<br />
types of actual parameters<br />
<br />
I've quickly tested it on simple i=i+1 statements and found that with<br />
JIT computer runs at 1/10th of its full speed while without JIT it<br />
runs at 1/30th<br />
<br />
=== wxLua ===<br />
<br />
wxLua is a cross-platform (Windows, Linux, OSX) binding to wxWindows<br />
library, plus IDE written using this binding that supports debugging<br />
of Lua code and generation of Lua bindings to C libraries. So, you get<br />
a full-featured Lua IDE extensible in Lua itself.<br />
<br />
It is even more interesting that you can add the wxLua to your<br />
Lua-enabled application, providing user-written code means to build<br />
full-fledged GUI. Just imagine that now you can split your program<br />
into two parts - real work is done in Haskell part which registers its<br />
functions for Lua part and all the funny dialogs and editors are<br />
written in Lua using wxWindows widgets. The Lua part can be easily<br />
created/extended by less experienced users meaning that you may spend<br />
more time on implementing core algorithms. Isn't it beautiful?<br />
<br />
=== MetaLua ===<br />
<br />
We already mentioned that Lua semantics is rather close, may be a bit<br />
better than of other scripting languages, but its syntax is terse. But<br />
this simplicity opens up sudden and very exciting possibility - it's<br />
easy to reimplement Lua and add any other features we want without<br />
losing bytecode compatibility with official implementation<br />
<br />
MetaLua does that, reimplementing Lua compiler in Lua itself. But it<br />
goes much further: Lua syntax is described in GG, ParseC-like parsing<br />
combinators library. Unlike ParseC, it allows to change parsing rules<br />
on the fly, making it ideal basis for language with extensible syntax<br />
<br />
MetaLua adds to Lua a lot of FP-styled and other features - ADT,<br />
pattern matching, terse syntax for anonymous lambdas, list<br />
comprehensions, familiar syntax for exception handling, RAII brackets,<br />
statements inside expressions, ternary ?: operator, type/domain<br />
checking. All these implemented with usual Lua modules and as<br />
everything in Lua, they are very terse - the largest module,<br />
implementing pattern matching, is just 200 lines long. You can add new<br />
syntax just by dropping new modules into MetaLua directory. Extending<br />
MetaLua is very like to programming in Template Haskell with all its<br />
pitfalls solved and extending-syntax features added. I will be very<br />
pleased if GHC provided front-end like the MetaLua<br />
<br />
<br />
Just imagine all these features combined together: blazing fast<br />
dynamic FP language that may be easily extended by means of new<br />
libraries and new syntax just by dropping their files into program's<br />
directory and supports creation of GUIs - seamlessly integrated with<br />
your Haskell code. I think it will be invaluable tool that supplements<br />
Haskell's power with easiness and flexibility.<br />
<br />
<br />
== Further reading ==<br />
<br />
[1] http://hackage.haskell.org/packages/archive/hslua/<br />
<br />
[2] http://www.inf.puc-rio.br/~roberto/pil2<br />
<br />
[3] http://www.lua.org/uses.html<br />
<br />
[4] http://lua-users.org/wiki/ThreadsTutorial<br />
<br />
[5] http://lua-users.org/wiki/GenericInputAlgorithms</div>Jameshfisherhttps://wiki.haskell.org/index.php?title=Talk:Introduction_to_QuickCheck1&diff=55251Talk:Introduction to QuickCheck12013-01-13T19:54:24Z<p>Jameshfisher: Talk:Introduction to QuickCheck moved to Talk:Introduction to QuickCheck1: QuickCheck2 is what people will be using.</p>
<hr />
<div>Should we say up front that this applies to V1, <br />
now that that there's a V2?</div>Jameshfisherhttps://wiki.haskell.org/index.php?title=Talk:Introduction_to_QuickCheck&diff=55252Talk:Introduction to QuickCheck2013-01-13T19:54:24Z<p>Jameshfisher: Talk:Introduction to QuickCheck moved to Talk:Introduction to QuickCheck1: QuickCheck2 is what people will be using.</p>
<hr />
<div>#REDIRECT [[Talk:Introduction to QuickCheck1]]</div>Jameshfisherhttps://wiki.haskell.org/index.php?title=Introduction_to_QuickCheck1&diff=55249Introduction to QuickCheck12013-01-13T19:54:23Z<p>Jameshfisher: Introduction to QuickCheck moved to Introduction to QuickCheck1: QuickCheck2 is what people will be using.</p>
<hr />
<div>A quick introduction to QuickCheck, and testing Haskell code. See [[Introduction_to_QuickCheck2| Introduction to QuickCheck2]] for the QC2 version<br />
<br />
== Motivation ==<br />
<br />
In September 2006, Bruno Martínez<br />
[http://www.haskell.org/pipermail/haskell-cafe/2006-September/018302.html asked] <br />
the following question:<br />
<br />
<haskell><br />
-- I've written a function that looks similar to this one<br />
<br />
getList = find 5 where<br />
find 0 = return []<br />
find n = do<br />
ch <- getChar<br />
if ch `elem` ['a'..'e'] then do<br />
tl <- find (n-1)<br />
return (ch : tl) else<br />
find n<br />
<br />
-- I want to test this function, without hitting the filesystem. In C++ I<br />
-- would use a istringstream. I couldn't find a function that returns a<br />
-- Handle from a String. The closer thing that may work that I could find<br />
-- was making a pipe and converting the file descriptor. Can I simplify<br />
-- that function to take it out of the IO monad?<br />
</haskell><br />
<br />
So the problem is: how to effectively test this function in Haskell? The<br />
solution we turn to is refactoring and QuickCheck.<br />
<br />
== Keeping things pure ==<br />
<br />
The reason your getList is hard to test, is that the side effecting monadic code <br />
is mixed in with the pure computation, making it difficult to test<br />
without moving entirely into a "black box" IO-based testing model.<br />
Such a mixture is not good for reasoning about code.<br />
<br />
Let's untangle that, and then test the referentially transparent<br />
parts simply with QuickCheck. We can take advantage of lazy IO firstly,<br />
to avoid all the unpleasant low-level IO handling. <br />
<br />
So the first step is to factor out the IO part of the function into a<br />
thin "skin" layer:<br />
<br />
<haskell><br />
-- A thin monadic skin layer<br />
getList :: IO [Char]<br />
getList = fmap take5 getContents<br />
<br />
-- The actual worker<br />
take5 :: [Char] -> [Char]<br />
take5 = take 5 . filter (`elem` ['a'..'e'])<br />
</haskell><br />
<br />
== Testing with QuickCheck ==<br />
<br />
Now we can test the 'guts' of the algorithm, the take5 function, in<br />
isolation. Let's use QuickCheck. First we need an Arbitrary instance for<br />
the Char type -- this takes care of generating random Chars for us to<br />
test with. I'll restrict it to a range of nice chars just for<br />
simplicity:<br />
<br />
<haskell><br />
import Data.Char<br />
import Test.QuickCheck<br />
<br />
instance Arbitrary Char where<br />
arbitrary = choose ('\32', '\128')<br />
coarbitrary c = variant (ord c `rem` 4)<br />
</haskell><br />
<br />
Let's fire up GHCi (or Hugs) and try some generic properties (its nice<br />
that we can use the QuickCheck testing framework directly from the<br />
Haskell prompt). An easy one first, a [Char] is equal to itself:<br />
<br />
<haskell><br />
*A> quickCheck ((\s -> s == s) :: [Char] -> Bool)<br />
OK, passed 100 tests.<br />
</haskell><br />
<br />
What just happened? QuickCheck generated 100 random [Char] values, and<br />
applied our property, checking the result was True for all cases.<br />
QuickCheck ''generated the test sets for us''!<br />
<br />
A more interesting property now: reversing twice is the identity:<br />
<br />
<haskell><br />
*A> quickCheck ((\s -> (reverse.reverse) s == s) :: [Char] -> Bool)<br />
OK, passed 100 tests.<br />
</haskell><br />
<br />
Great!<br />
<br />
== Testing take5 ==<br />
<br />
The first step to testing with QuickCheck is to work out some properties<br />
that are true of the function, for all inputs. That is, we need to find<br />
''invariants''.<br />
<br />
A simple invariant might be:<br />
<math>\forall~s~.~length~(take5~s)~=~5</math><br />
<br />
So let's write that as a QuickCheck property:<br />
<haskell><br />
\s -> length (take5 s) == 5<br />
</haskell><br />
<br />
Which we can then run in QuickCheck as:<br />
<haskell><br />
*A> quickCheck (\s -> length (take5 s) == 5)<br />
Falsifiable, after 0 tests:<br />
""<br />
</haskell><br />
<br />
Ah! QuickCheck caught us out. If the input string contains less than 5<br />
filterable characters, the resulting string will be less than 5<br />
characters long. So let's weaken the property a bit:<br />
<math>\forall~s~.~length~(take5~s)~\le~5</math><br />
<br />
That is, take5 returns a string of at most 5 characters long. Let's test<br />
this: <br />
<haskell><br />
*A> quickCheck (\s -> length (take5 s) <= 5)<br />
OK, passed 100 tests.<br />
</haskell><br />
<br />
Good!<br />
<br />
== Another property ==<br />
<br />
Another thing to check would be that the correct characters are<br />
returned. That is, for all returned characters, those characters are<br />
members of the set ['a','b','c','d','e'].<br />
<br />
We can specify that as:<br />
<math>\forall~s~.~\forall~e~.~e~\in~take5~s~\to~e~\in~[abcde] </math><br />
<br />
And in QuickCheck:<br />
<haskell><br />
*A> quickCheck (\s -> all (`elem` ['a'..'e']) (take5 s))<br />
OK, passed 100 tests.<br />
</haskell><br />
<br />
Excellent. So we can have some confidence that the function neither<br />
returns strings that are too long, nor includes invalid characters.<br />
<br />
== Coverage ==<br />
<br />
One issue with the default QuickCheck configuration, when testing<br />
[Char], is that the standard 100 tests isn't enough for our situation.<br />
In fact, QuickCheck never generates a String greater than 5 characters<br />
long, when using the supplied Arbitrary instance for Char! We can confirm<br />
this:<br />
<br />
<haskell><br />
*A> quickCheck (\s -> length (take5 s) < 5)<br />
OK, passed 100 tests.<br />
</haskell><br />
<br />
QuickCheck wastes its time generating different Chars, when what we<br />
really need is longer strings. One solution to this is to modify<br />
QuickCheck's default configuration to test deeper:<br />
<br />
<haskell><br />
deepCheck p = check (defaultConfig { configMaxTest = 10000}) p<br />
</haskell><br />
<br />
This instructs the system to find at least 10000 test cases before<br />
concluding that all is well. Let's check that it is generating longer<br />
strings:<br />
<br />
<haskell><br />
*A> deepCheck (\s -> length (take5 s) < 5)<br />
Falsifiable, after 125 tests:<br />
";:iD^*NNi~Y\\RegMob\DEL@krsx/=dcf7kub|EQi\DELD*"<br />
</haskell><br />
<br />
We can check the test data QuickCheck is generating using the<br />
'verboseCheck' hook. Here, testing on integers lists:<br />
<br />
<haskell><br />
*A> verboseCheck (\s -> length s < 5)<br />
0: []<br />
1: [0]<br />
2: []<br />
3: []<br />
4: []<br />
5: [1,2,1,1]<br />
6: [2]<br />
7: [-2,4,-4,0,0]<br />
Falsifiable, after 7 tests:<br />
[-2,4,-4,0,0]<br />
</haskell><br />
<br />
== Going further ==<br />
<br />
QuickCheck is effectively an embedded domain specific language for<br />
testing Haskell code, and allows for much more complex properties than<br />
those you've seen here to be tested. Some sources for further reading<br />
are:<br />
* [http://code.haskell.org/QuickCheck/stable/Test/ The QuickCheck source]<br />
* [http://hackage.haskell.org/package/QuickCheck-2.4.2 QuickCheck Library documentation]<br />
* [http://www.cse.chalmers.se/~rjmh/QuickCheck/manual.html QuickCheck v1 Manual]<br />
* [http://hackage.haskell.org/trac/ghc/browser/libraries/bytestring/tests?rev=bc96abdb6d3777bdc4eaaccf37494f535405d4e1 A large testsuite of QuickCheck code]<br />
* Tutorial: [[QuickCheck as a test set generator]]<br />
* Tutorial: [[QuickCheck / GADT]]<br />
* More [[Research_papers/Testing_and_correctness | research on correctness and testing]] in Haskell<br />
<br />
* 2012 Blog article: [http://ics.p.lodz.pl/~stolarek/blog/2012/10/code-testing-in-haskell/ Code testing in Haskell]<br />
* 2009 Blog article: [http://koweycode.blogspot.com/2009/07/some-ideas-for-practical-quickcheck.html some ideas for practical QuickCheck]<br />
* 2004 Paper [http://dl.acm.org/citation.cfm?doid=351240.351266 QuickCheck: Specification-based Random Testing], Koen Claessen. Presentation at Summer Institute on Trends in Testing: Theory, Techniques and Tools, August 2004.<br />
* 2003 Paper [http://www.cs.utexas.edu/~ragerdl/fmcad11/slides/tutorial-a.pdf Specification Based Testing with QuickCheck], Koen Claessen and John Hughes. In Jeremy Gibbons and Oege de Moor (eds.), The Fun of Programming, Cornerstones of Computing, pp. 17--40, Palgrave, 2003.<br />
* 2002 Paper [http://www.cse.chalmers.se/~rjmh/Papers/QuickCheckST.ps Testing Monadic Programs with QuickCheck], Koen Claessen, John Hughes. SIGPLAN Notices 37(12): 47-59 (2002):<br />
* 2000 Paper [http://www.eecs.northwestern.edu/~robby/courses/395-495-2009-fall/quick.pdf QuickCheck: A Lightweight Tool for Random Testing of Haskell Programs], Koen Claessen and John Hughes. In Proc. of International Conference on Functional Programming (ICFP), ACM SIGPLAN, 2000.<br />
<br />
Note, QuickCheck doesn't need to just be an embedded domain specific language for testing ''Haskell'' code. By making instances of Arbitrary for FFI types you can use Haskell and QuickCheck to check code in other languages.<br />
<br />
[[Category:Tutorials]]</div>Jameshfisherhttps://wiki.haskell.org/index.php?title=Introduction_to_QuickCheck&diff=55250Introduction to QuickCheck2013-01-13T19:54:23Z<p>Jameshfisher: Introduction to QuickCheck moved to Introduction to QuickCheck1: QuickCheck2 is what people will be using.</p>
<hr />
<div>#REDIRECT [[Introduction to QuickCheck1]]</div>Jameshfisherhttps://wiki.haskell.org/index.php?title=Lazy_vs._non-strict&diff=44972Lazy vs. non-strict2012-03-22T09:11:10Z<p>Jameshfisher: /* Direction of evaluation */ single line breaks seem to trigger new paragraphs; eliminate them</p>
<hr />
<div>Haskell is often described as a lazy language.<br />
However, the language specification simply states that Haskell is [[Non-strict semantics|non-strict]], which is not quite the same thing as [[lazy evaluation|lazy]].<br />
<br />
<br />
== Direction of evaluation ==<br />
<br />
[[Non-strict semantics|Non-strictness]] means that [[reduction]] (the mathematical term for [[evaluation]]) proceeds from the outside in, so if you have <hask>(a+(b*c))</hask> then first you reduce the <hask>+</hask>, then you reduce the inner <hask>(b*c)</hask>. Strict languages work the other way around, starting with the innermost brackets and working outwards.<br />
<br />
This matters to the semantics because if you have an expression that evaluates to [[bottom]] (i.e. an <hask>error</hask> or endless loop) then any language that starts at the inside and works outwards will always find that bottom value, and hence the bottom will propagate outwards. However if you start from the outside and work in then some of the sub-expressions are eliminated by the outer reductions, so they don't get evaluated and you don't get "bottom".<br />
<br />
[[Lazy evaluation]], on the other hand, means only evaluating an expression when its results are needed (note the shift from "reduction" to "evaluation"). So when the evaluation engine sees an expression it builds a [[thunk]] data structure containing whatever values are needed to evaluate the expression, plus a pointer to the expression itself. When the result is actually needed the evaluation engine calls the expression and then replaces the thunk with the result for future reference.<br />
<br />
Obviously there is a strong correspondence between a thunk and a partly-evaluated expression. Hence in most cases the terms "lazy" and "non-strict" are synonyms. But not quite. For instance you could imagine an evaluation engine on highly parallel hardware that fires off sub-expression evaluation eagerly, but then throws away results that are not needed.<br />
<br />
In practice Haskell is not a purely lazy language: for instance pattern matching is usually strict (So trying a pattern match forces evaluation to happen at least far enough to accept or reject the match. You can prepend a <hask>~</hask> in order to make pattern matches lazy). The [[strictness analyzer]] also looks for cases where sub-expressions are ''always'' required by the outer expression, and converts those into eager evaluation. It can do this because the semantics (in terms of "bottom") don't change. Programmers can also use the <hask>seq</hask> primitive to force an expression to evaluate regardless of whether the result will ever be used. <hask>$!</hask> is defined in terms of <hask>seq</hask>.<br />
<br />
<br />
Source:<br />
* Paul Johnson in Haskell Cafe [http://www.haskell.org/pipermail/haskell-cafe/2007-November/034814.html What is the role of $! ?]<br />
<br />
== WHNF ==<br />
<br />
WHNF is an abbreviation for [[weak head normal form]].<br />
<br />
<br />
== Further references ==<br />
<br />
Laziness is simply a common implementation technique for non-strict languages, but it is not the only possible technique. One major drawback with lazy implementations is that they are not generally amenable to parallelisation. This paper states that experiments indicate that little parallelism can be extracted from lazy programs:<br />
<br />
"The Impact of Laziness on Parallelism and the Limits of Strictness Analysis"<br />
(G. Tremblay G. R. Gao)<br />
http://citeseer.ist.psu.edu/tremblay95impact.html<br />
<br />
Lenient, or optimistic, evaluation is an implementation approach that lies somewhere between lazy and strict, and combines eager evaluation with non-strict semantics. This seems to be considered more promising for parallelisation.<br />
<br />
This paper implies (section 2.2.1) that lenient evaluation can handle circular data structures and recursive definitions, but cannot express infinite structures without explicit use of delays:<br />
<br />
"How Much Non-strictness do Lenient Programs Require?"<br />
(Klaus E. Schauser, Seth C. Goldstein)<br />
http://citeseer.ist.psu.edu/schauser95how.html<br />
<br />
Some experiments with non-lazy Haskell compilers have been attempted:<br />
[[Research_papers/Runtime_systems#Optimistic_Evaluation]]<br />
<br />
[[Category:Theoretical_foundations]]</div>Jameshfisherhttps://wiki.haskell.org/index.php?title=Foldable_and_Traversable&diff=44646Foldable and Traversable2012-02-23T21:51:46Z<p>Jameshfisher: /* Generalising zipWith */</p>
<hr />
<div>[[Category:Code]] [[Category:Idioms]]<br />
<br />
<center>'''Notes on Foldable, Traversable and other useful classes'''</center><br />
<center>'' or "Where is Data.Sequence.toList?"''</center><br />
<br />
[http://haskell.org/ghc/docs/latest/html/libraries/containers/Data-Sequence.html Data.Sequence] is recommended as an efficient alternative to [list]s,<br />
with a more symmetric feel and better complexity on various<br />
operations.<br />
<br />
When you've been using it for a little while, there seem to be some baffling omissions from the API. The first couple you are likely to notice are the absence of "<hask>map</hask>" and "<hask>toList</hask>".<br />
The answer to these lies in the long list of instances which Sequence has:<br />
* The Sequence version of map is "<hask>fmap</hask>", which comes from the Functor class. <br />
* The Sequence version of <hask>toList</hask> is in the <hask>Foldable</hask> [[class]].<br />
<br />
When working with <hask>Sequence</hask> you also want to refer to the documentation<br />
for at least <hask>Foldable</hask> and <hask>Traversable</hask>. <hask>Functor</hask> only has the single [[method]], so we've already covered that.<br />
<br />
==What do these classes all mean? A brief tour:==<br />
<br />
[[Image:FunctorHierarchy.svg]]<br />
<br />
===<hask>Functor</hask>===<br />
<br />
A [[functor]] is simply a [[container]]. Given a container, and a [[function]] which works on the elements, we can apply that function to each element. For lists, the familiar "<hask>map</hask>" does exactly this.<br />
<br />
Note that the function can produce elements of a different [[type]], so we<br />
may have a different type at the end.<br />
<br />
Examples:<br />
<br />
<haskell><br />
Prelude Data.Sequence> map (\n -> replicate n 'a') [1,3,5]<br />
["a","aaa","aaaaa"]<br />
Prelude Data.Sequence> fmap (\n -> replicate n 'a') (1 <| 3 <| 5 <| empty)<br />
fromList ["a","aaa","aaaaa"]<br />
</haskell><br />
<br />
===Foldable===<br />
<br />
A <hask>Foldable</hask> [[type]] is also a [[container]] (although the [[class]] does not<br />
technically require <hask>Functor</hask>, interesting <hask>Foldable</hask>s are all <hask>Functor</hask>s). It is a container with the added property that its items can be 'folded' to a summary value. In other words, it is a type which supports "<hask>foldr</hask>".<br />
<br />
Once you support <hask>foldr</hask>, of course, you can be turned into a list, by using <hask>toList = foldr (:) []</hask>. This means that all <hask>Foldable</hask>s have a representation as a list, but the order of the items may or may not have any particular significance. However, if a <hask>Foldable</hask> is also a <hask>Functor</hask>, [[parametricity]] and the [[Functor law]] guarantee that <hask>toList</hask> and <hask>fmap</hask> commute. Further, in the case of <hask>Data.Sequence</hask>, there '''is''' a well defined order and it is exposed as expected by <hask>toList</hask>.<br />
<br />
A particular kind of fold well-used by Haskell programmers is <hask>mapM_</hask>, which is a kind of fold over <hask>(>>)</hask>, and <hask>Foldable</hask> provides this along with the related <hask>sequence_</hask>.<br />
<br />
===Traversable===<br />
<br />
A <hask>Traversable</hask> [[type]] is a kind of upgraded <hask>Foldable</hask>. Where <hask>Foldable</hask> gives you the ability to go through the structure processing the elements (<hask>foldr</hask>) but throwing away the shape, <hask>Traversable</hask> allows you to do that whilst preserving the shape and, e.g., putting new values in.<br />
<br />
<hask>Traversable</hask> is what we need for <hask>mapM</hask> and <hask>sequence</hask> : note the apparently surprising fact that the "_" versions are in a different [[typeclass]].<br />
<br />
== Some trickier functions: concatMap and filter ==<br />
<br />
Neither <hask>Traversable</hask> nor <hask>Foldable</hask> contain elements for <hask>concatMap</hask> and <hask>filter</hask>. That is because <hask>Foldable</hask> is about tearing down the structure completely, while <hask>Traversable</hask> is about preserving the structure exactly as-is. On the other hand <hask>concatMap</hask> tries to 'squeeze more elements in' at a place and <hask>filter</hask> tries to cut them out.<br />
<br />
You can write <hask>concatMap</hask> for <hask>Sequence</hask> as follows:<br />
<br />
<haskell><br />
concatMap :: (a -> Seq b) -> Seq a -> Seq b<br />
concatMap = foldMap<br />
</haskell><br />
<br />
But why does it work? It works because sequence is an instance of <hask>Monoid</hask>, where the [[monoid]]al operation is "appending". The same definition works for lists, and we can write it more generally as:<br />
<br />
<haskell><br />
concatMap :: (Foldable f, Monoid (f b)) => (a -> f b) -> f a -> f b<br />
concatMap = foldMap<br />
</haskell><br />
<br />
And that works with lists and sequences both. Does it work with any Monoid which is Foldable? Only if the Monoid 'means the right thing'. If you have <hask>toList (f `mappend` g) = toList f ++ toList g</hask> then it definitely makes sense. In fact this easy to write condition is stronger than needed; it would be good enough if they were permutations of each other.<br />
<br />
<hask>filter</hask> turns out to be slightly harder still. You need something like 'singleton' (from <hask>Sequence</hask>), or <hask>\a -> [a]</hask> for lists. We can use <hask>pure</hask> from <hask>Applicative</hask>, although it's not really right to bring <hask>Applicative</hask> in for this, and get:<br />
<br />
<haskell><br />
filter :: (Applicative f, Foldable f, Monoid (f a)) => <br />
(a -> Bool) -> f a -> f a<br />
filter p = foldMap (\a -> if p a then pure a else mempty)<br />
</haskell><br />
<br />
It's interesting to note that, under these conditions, we have a candidate to help us turn the <hask>Foldable</hask> into a <hask>Monad</hask>, since <hask>concatMap</hask> is a good definition for <hask>>>=</hask>, and we can use <hask>pure</hask> for <hask>return</hask>.<br />
<br />
== Generalising zipWith ==<br />
<br />
Another really useful list [[combinator]] that doesn't appear in the interfaces for <hask>Sequence</hask>, <hask>Foldable</hask> or <hask>Traversable</hask> is <hask>zipWith</hask>. The most general kind of <hask>zipWith</hask> over <hask>Traversable</hask>s will keep the exact shape of the <hask>Traversable</hask> on the left, whilst zipping against the values on the right. It turns out you can get away with a <hask>Foldable</hask> on the right, but you need to use a <hask>Monad</hask> (or an <hask>Applicative</hask>, actually) to thread the values through:<br />
<br />
<haskell><br />
import Prelude hiding (sequence)<br />
<br />
import Data.Sequence<br />
import Data.Foldable<br />
import Data.Traversable<br />
import Control.Applicative<br />
<br />
<br />
data Supply s v = Supply { unSupply :: [s] -> ([s],v) }<br />
<br />
instance Functor (Supply s) where <br />
fmap f av = Supply (\l -> let (l',v) = unSupply av l in (l',f v))<br />
<br />
instance Applicative (Supply s) where<br />
pure v = Supply (\l -> (l,v))<br />
af <*> av = Supply (\l -> let (l',f) = unSupply af l<br />
(l'',v) = unSupply av l'<br />
in (l'',f v))<br />
<br />
runSupply :: (Supply s v) -> [s] -> v<br />
runSupply av l = snd $ unSupply av l<br />
<br />
supply :: Supply s s<br />
supply = Supply (\(x:xs) -> (xs,x))<br />
<br />
zipTF :: (Traversable t, Foldable f) => t a -> f b -> t (a,b)<br />
zipTF t f = runSupply (traverse (\a -> (,) a <$> supply) t) (toList f)<br />
<br />
zipWithTF :: (Traversable t,Foldable f) => (a -> b -> c) -> t a -> f b -> t c<br />
zipWithTF g t f = runSupply (traverse (\a -> g a <$> supply) t) (toList f)<br />
<br />
zipWithTFM :: (Traversable t,Foldable f,Monad m) => <br />
(a -> b -> m c) -> t a -> f b -> m (t c)<br />
zipWithTFM g t f = sequence (zipWithTF g t f)<br />
<br />
zipWithTFA :: (Traversable t,Foldable f,Applicative m) => <br />
(a -> b -> m c) -> t a -> f b -> m (t c)<br />
zipWithTFA g t f = sequenceA (zipWithTF g t f)<br />
</haskell><br />
<br />
The code above fails with a [[pattern match]] error when the <hask>Foldable</hask> container doesn't have enough input. Here is an alternative version which provides friendlier error reports and makes use of <hask>State</hask> instead of the self defined Supply [[monad]].<br />
<br />
<haskell><br />
module GenericZip <br />
(zipWithTF,<br />
zipTF,<br />
zipWithTFA,<br />
zipWithTFM) where<br />
<br />
<br />
import Data.Foldable<br />
import Data.Traversable<br />
import qualified Data.Traversable as T<br />
import Control.Applicative<br />
import Control.Monad.State <br />
<br />
-- | The state contains the list of values obtained form the foldable container<br />
-- and a String indicating the name of the function currectly being executed<br />
data ZipState a = ZipState {fName :: String,<br />
list :: [a]}<br />
<br />
-- | State monad containing ZipState<br />
type ZipM l a = State (ZipState l) a<br />
<br />
-- | pops the first element of the list inside the state<br />
pop :: ZipM l l<br />
pop = do <br />
st <- get <br />
let xs = list st<br />
n = fName st<br />
case xs of<br />
(a:as) -> do put st{list=as}<br />
return a<br />
[] -> error $ n ++ ": insufficient input"<br />
<br />
-- | pop a value form the state and supply it to the second <br />
-- argument of a binary function <br />
supplySecond :: (a -> b -> c) -> a -> ZipM b c<br />
supplySecond f a = do b <- pop <br />
return $ f a b<br />
<br />
zipWithTFError :: (Traversable t,Foldable f) => <br />
String -> (a -> b -> c) -> t a -> f b -> t c <br />
zipWithTFError str g t f = evalState (T.mapM (supplySecond g) t) <br />
(ZipState str (toList f))<br />
<br />
<br />
zipWithTF :: (Traversable t,Foldable f) => (a -> b -> c) -> t a -> f b -> t c<br />
zipWithTF = zipWithTFError "GenericZip.zipWithTF"<br />
<br />
zipTF :: (Traversable t, Foldable f) => t a -> f b -> t (a,b)<br />
zipTF = zipWithTFError "GenericZip.zipTF" (,) <br />
<br />
<br />
zipWithTFM :: (Traversable t,Foldable f,Monad m) => <br />
(a -> b -> m c) -> t a -> f b -> m (t c)<br />
zipWithTFM g t f = T.sequence (zipWithTFError "GenericZip.zipWithTFM" g t f)<br />
<br />
zipWithTFA :: (Traversable t,Foldable f,Applicative m) => <br />
(a -> b -> m c) -> t a -> f b -> m (t c)<br />
zipWithTFA g t f = sequenceA (zipWithTFError "GenericZip.zipWithTFA" g t f)<br />
</haskell><br />
Recent versions of <hask>Data.Traversable</hask> include generalizations of <hask>mapAccumL</hask> and <hask>mapAccumR</hask> from lists to Traversables (encapsulating the state monad used above):<br />
<haskell><br />
mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
</haskell><br />
Using these, the first version above can be written as<br />
<haskell><br />
zipWithTF :: (Traversable t, Foldable f) => (a -> b -> c) -> t a -> f b -> t c<br />
zipWithTF g t f = snd (mapAccumL map_one (toList f) t)<br />
where map_one (x:xs) y = (xs, g y x)<br />
</haskell><br />
Replace <hask>mapAccumL</hask> with <hask>mapAccumR</hask> and the elements of the Foldable are zipped in reverse order. Similarly, we can define a generalization of <hask>reverse</hask> on Traversables, which preserves the shape but reverses the left-to-right position of the elements:<br />
<haskell><br />
reverseT :: (Traversable t) => t a -> t a<br />
reverseT t = snd (mapAccumR (\ (x:xs) _ -> (xs, x)) (toList t) t)<br />
</haskell></div>Jameshfisherhttps://wiki.haskell.org/index.php?title=Foldable_and_Traversable&diff=44645Foldable and Traversable2012-02-23T21:51:26Z<p>Jameshfisher: /* Generalising zipWith */</p>
<hr />
<div>[[Category:Code]] [[Category:Idioms]]<br />
<br />
<center>'''Notes on Foldable, Traversable and other useful classes'''</center><br />
<center>'' or "Where is Data.Sequence.toList?"''</center><br />
<br />
[http://haskell.org/ghc/docs/latest/html/libraries/containers/Data-Sequence.html Data.Sequence] is recommended as an efficient alternative to [list]s,<br />
with a more symmetric feel and better complexity on various<br />
operations.<br />
<br />
When you've been using it for a little while, there seem to be some baffling omissions from the API. The first couple you are likely to notice are the absence of "<hask>map</hask>" and "<hask>toList</hask>".<br />
The answer to these lies in the long list of instances which Sequence has:<br />
* The Sequence version of map is "<hask>fmap</hask>", which comes from the Functor class. <br />
* The Sequence version of <hask>toList</hask> is in the <hask>Foldable</hask> [[class]].<br />
<br />
When working with <hask>Sequence</hask> you also want to refer to the documentation<br />
for at least <hask>Foldable</hask> and <hask>Traversable</hask>. <hask>Functor</hask> only has the single [[method]], so we've already covered that.<br />
<br />
==What do these classes all mean? A brief tour:==<br />
<br />
[[Image:FunctorHierarchy.svg]]<br />
<br />
===<hask>Functor</hask>===<br />
<br />
A [[functor]] is simply a [[container]]. Given a container, and a [[function]] which works on the elements, we can apply that function to each element. For lists, the familiar "<hask>map</hask>" does exactly this.<br />
<br />
Note that the function can produce elements of a different [[type]], so we<br />
may have a different type at the end.<br />
<br />
Examples:<br />
<br />
<haskell><br />
Prelude Data.Sequence> map (\n -> replicate n 'a') [1,3,5]<br />
["a","aaa","aaaaa"]<br />
Prelude Data.Sequence> fmap (\n -> replicate n 'a') (1 <| 3 <| 5 <| empty)<br />
fromList ["a","aaa","aaaaa"]<br />
</haskell><br />
<br />
===Foldable===<br />
<br />
A <hask>Foldable</hask> [[type]] is also a [[container]] (although the [[class]] does not<br />
technically require <hask>Functor</hask>, interesting <hask>Foldable</hask>s are all <hask>Functor</hask>s). It is a container with the added property that its items can be 'folded' to a summary value. In other words, it is a type which supports "<hask>foldr</hask>".<br />
<br />
Once you support <hask>foldr</hask>, of course, you can be turned into a list, by using <hask>toList = foldr (:) []</hask>. This means that all <hask>Foldable</hask>s have a representation as a list, but the order of the items may or may not have any particular significance. However, if a <hask>Foldable</hask> is also a <hask>Functor</hask>, [[parametricity]] and the [[Functor law]] guarantee that <hask>toList</hask> and <hask>fmap</hask> commute. Further, in the case of <hask>Data.Sequence</hask>, there '''is''' a well defined order and it is exposed as expected by <hask>toList</hask>.<br />
<br />
A particular kind of fold well-used by Haskell programmers is <hask>mapM_</hask>, which is a kind of fold over <hask>(>>)</hask>, and <hask>Foldable</hask> provides this along with the related <hask>sequence_</hask>.<br />
<br />
===Traversable===<br />
<br />
A <hask>Traversable</hask> [[type]] is a kind of upgraded <hask>Foldable</hask>. Where <hask>Foldable</hask> gives you the ability to go through the structure processing the elements (<hask>foldr</hask>) but throwing away the shape, <hask>Traversable</hask> allows you to do that whilst preserving the shape and, e.g., putting new values in.<br />
<br />
<hask>Traversable</hask> is what we need for <hask>mapM</hask> and <hask>sequence</hask> : note the apparently surprising fact that the "_" versions are in a different [[typeclass]].<br />
<br />
== Some trickier functions: concatMap and filter ==<br />
<br />
Neither <hask>Traversable</hask> nor <hask>Foldable</hask> contain elements for <hask>concatMap</hask> and <hask>filter</hask>. That is because <hask>Foldable</hask> is about tearing down the structure completely, while <hask>Traversable</hask> is about preserving the structure exactly as-is. On the other hand <hask>concatMap</hask> tries to 'squeeze more elements in' at a place and <hask>filter</hask> tries to cut them out.<br />
<br />
You can write <hask>concatMap</hask> for <hask>Sequence</hask> as follows:<br />
<br />
<haskell><br />
concatMap :: (a -> Seq b) -> Seq a -> Seq b<br />
concatMap = foldMap<br />
</haskell><br />
<br />
But why does it work? It works because sequence is an instance of <hask>Monoid</hask>, where the [[monoid]]al operation is "appending". The same definition works for lists, and we can write it more generally as:<br />
<br />
<haskell><br />
concatMap :: (Foldable f, Monoid (f b)) => (a -> f b) -> f a -> f b<br />
concatMap = foldMap<br />
</haskell><br />
<br />
And that works with lists and sequences both. Does it work with any Monoid which is Foldable? Only if the Monoid 'means the right thing'. If you have <hask>toList (f `mappend` g) = toList f ++ toList g</hask> then it definitely makes sense. In fact this easy to write condition is stronger than needed; it would be good enough if they were permutations of each other.<br />
<br />
<hask>filter</hask> turns out to be slightly harder still. You need something like 'singleton' (from <hask>Sequence</hask>), or <hask>\a -> [a]</hask> for lists. We can use <hask>pure</hask> from <hask>Applicative</hask>, although it's not really right to bring <hask>Applicative</hask> in for this, and get:<br />
<br />
<haskell><br />
filter :: (Applicative f, Foldable f, Monoid (f a)) => <br />
(a -> Bool) -> f a -> f a<br />
filter p = foldMap (\a -> if p a then pure a else mempty)<br />
</haskell><br />
<br />
It's interesting to note that, under these conditions, we have a candidate to help us turn the <hask>Foldable</hask> into a <hask>Monad</hask>, since <hask>concatMap</hask> is a good definition for <hask>>>=</hask>, and we can use <hask>pure</hask> for <hask>return</hask>.<br />
<br />
== Generalising zipWith ==<br />
<br />
Another really useful list [[combinator]] that doesn't appear in the interfaces for <hask>Sequence</hask>, <hask>Foldable</hask> or <hask>Traversable</hask> is <hask>zipWith</hask>. The most general kind of <hask>zipWith</hask> over <hask>Traversable</hask>s will keep the exact shape of the <hask>Traversable</hask> on the left, whilst zipping against the values on the right. It turns out you can get away with a <hask>Foldable</hask> on the right, but you need to use a <hask>Monad</hask> (or an <hask>Applicative</hask>, actually) to thread the<br />
values through:<br />
<br />
<haskell><br />
import Prelude hiding (sequence)<br />
<br />
import Data.Sequence<br />
import Data.Foldable<br />
import Data.Traversable<br />
import Control.Applicative<br />
<br />
<br />
data Supply s v = Supply { unSupply :: [s] -> ([s],v) }<br />
<br />
instance Functor (Supply s) where <br />
fmap f av = Supply (\l -> let (l',v) = unSupply av l in (l',f v))<br />
<br />
instance Applicative (Supply s) where<br />
pure v = Supply (\l -> (l,v))<br />
af <*> av = Supply (\l -> let (l',f) = unSupply af l<br />
(l'',v) = unSupply av l'<br />
in (l'',f v))<br />
<br />
runSupply :: (Supply s v) -> [s] -> v<br />
runSupply av l = snd $ unSupply av l<br />
<br />
supply :: Supply s s<br />
supply = Supply (\(x:xs) -> (xs,x))<br />
<br />
zipTF :: (Traversable t, Foldable f) => t a -> f b -> t (a,b)<br />
zipTF t f = runSupply (traverse (\a -> (,) a <$> supply) t) (toList f)<br />
<br />
zipWithTF :: (Traversable t,Foldable f) => (a -> b -> c) -> t a -> f b -> t c<br />
zipWithTF g t f = runSupply (traverse (\a -> g a <$> supply) t) (toList f)<br />
<br />
zipWithTFM :: (Traversable t,Foldable f,Monad m) => <br />
(a -> b -> m c) -> t a -> f b -> m (t c)<br />
zipWithTFM g t f = sequence (zipWithTF g t f)<br />
<br />
zipWithTFA :: (Traversable t,Foldable f,Applicative m) => <br />
(a -> b -> m c) -> t a -> f b -> m (t c)<br />
zipWithTFA g t f = sequenceA (zipWithTF g t f)<br />
</haskell><br />
<br />
The code above fails with a [[pattern match]] error when the <hask>Foldable</hask> container doesn't have enough input. Here is an alternative version which provides friendlier error reports and makes use of <hask>State</hask> instead of the self defined Supply [[monad]].<br />
<br />
<haskell><br />
module GenericZip <br />
(zipWithTF,<br />
zipTF,<br />
zipWithTFA,<br />
zipWithTFM) where<br />
<br />
<br />
import Data.Foldable<br />
import Data.Traversable<br />
import qualified Data.Traversable as T<br />
import Control.Applicative<br />
import Control.Monad.State <br />
<br />
-- | The state contains the list of values obtained form the foldable container<br />
-- and a String indicating the name of the function currectly being executed<br />
data ZipState a = ZipState {fName :: String,<br />
list :: [a]}<br />
<br />
-- | State monad containing ZipState<br />
type ZipM l a = State (ZipState l) a<br />
<br />
-- | pops the first element of the list inside the state<br />
pop :: ZipM l l<br />
pop = do <br />
st <- get <br />
let xs = list st<br />
n = fName st<br />
case xs of<br />
(a:as) -> do put st{list=as}<br />
return a<br />
[] -> error $ n ++ ": insufficient input"<br />
<br />
-- | pop a value form the state and supply it to the second <br />
-- argument of a binary function <br />
supplySecond :: (a -> b -> c) -> a -> ZipM b c<br />
supplySecond f a = do b <- pop <br />
return $ f a b<br />
<br />
zipWithTFError :: (Traversable t,Foldable f) => <br />
String -> (a -> b -> c) -> t a -> f b -> t c <br />
zipWithTFError str g t f = evalState (T.mapM (supplySecond g) t) <br />
(ZipState str (toList f))<br />
<br />
<br />
zipWithTF :: (Traversable t,Foldable f) => (a -> b -> c) -> t a -> f b -> t c<br />
zipWithTF = zipWithTFError "GenericZip.zipWithTF"<br />
<br />
zipTF :: (Traversable t, Foldable f) => t a -> f b -> t (a,b)<br />
zipTF = zipWithTFError "GenericZip.zipTF" (,) <br />
<br />
<br />
zipWithTFM :: (Traversable t,Foldable f,Monad m) => <br />
(a -> b -> m c) -> t a -> f b -> m (t c)<br />
zipWithTFM g t f = T.sequence (zipWithTFError "GenericZip.zipWithTFM" g t f)<br />
<br />
zipWithTFA :: (Traversable t,Foldable f,Applicative m) => <br />
(a -> b -> m c) -> t a -> f b -> m (t c)<br />
zipWithTFA g t f = sequenceA (zipWithTFError "GenericZip.zipWithTFA" g t f)<br />
</haskell><br />
Recent versions of <hask>Data.Traversable</hask> include generalizations of <hask>mapAccumL</hask> and <hask>mapAccumR</hask> from lists to Traversables (encapsulating the state monad used above):<br />
<haskell><br />
mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
</haskell><br />
Using these, the first version above can be written as<br />
<haskell><br />
zipWithTF :: (Traversable t, Foldable f) => (a -> b -> c) -> t a -> f b -> t c<br />
zipWithTF g t f = snd (mapAccumL map_one (toList f) t)<br />
where map_one (x:xs) y = (xs, g y x)<br />
</haskell><br />
Replace <hask>mapAccumL</hask> with <hask>mapAccumR</hask> and the elements of the Foldable are zipped in reverse order. Similarly, we can define a generalization of <hask>reverse</hask> on Traversables, which preserves the shape but reverses the left-to-right position of the elements:<br />
<haskell><br />
reverseT :: (Traversable t) => t a -> t a<br />
reverseT t = snd (mapAccumR (\ (x:xs) _ -> (xs, x)) (toList t) t)<br />
</haskell></div>Jameshfisherhttps://wiki.haskell.org/index.php?title=Foldable_and_Traversable&diff=44644Foldable and Traversable2012-02-23T21:50:25Z<p>Jameshfisher: /* Some trickier functions: concatMap and filter */</p>
<hr />
<div>[[Category:Code]] [[Category:Idioms]]<br />
<br />
<center>'''Notes on Foldable, Traversable and other useful classes'''</center><br />
<center>'' or "Where is Data.Sequence.toList?"''</center><br />
<br />
[http://haskell.org/ghc/docs/latest/html/libraries/containers/Data-Sequence.html Data.Sequence] is recommended as an efficient alternative to [list]s,<br />
with a more symmetric feel and better complexity on various<br />
operations.<br />
<br />
When you've been using it for a little while, there seem to be some baffling omissions from the API. The first couple you are likely to notice are the absence of "<hask>map</hask>" and "<hask>toList</hask>".<br />
The answer to these lies in the long list of instances which Sequence has:<br />
* The Sequence version of map is "<hask>fmap</hask>", which comes from the Functor class. <br />
* The Sequence version of <hask>toList</hask> is in the <hask>Foldable</hask> [[class]].<br />
<br />
When working with <hask>Sequence</hask> you also want to refer to the documentation<br />
for at least <hask>Foldable</hask> and <hask>Traversable</hask>. <hask>Functor</hask> only has the single [[method]], so we've already covered that.<br />
<br />
==What do these classes all mean? A brief tour:==<br />
<br />
[[Image:FunctorHierarchy.svg]]<br />
<br />
===<hask>Functor</hask>===<br />
<br />
A [[functor]] is simply a [[container]]. Given a container, and a [[function]] which works on the elements, we can apply that function to each element. For lists, the familiar "<hask>map</hask>" does exactly this.<br />
<br />
Note that the function can produce elements of a different [[type]], so we<br />
may have a different type at the end.<br />
<br />
Examples:<br />
<br />
<haskell><br />
Prelude Data.Sequence> map (\n -> replicate n 'a') [1,3,5]<br />
["a","aaa","aaaaa"]<br />
Prelude Data.Sequence> fmap (\n -> replicate n 'a') (1 <| 3 <| 5 <| empty)<br />
fromList ["a","aaa","aaaaa"]<br />
</haskell><br />
<br />
===Foldable===<br />
<br />
A <hask>Foldable</hask> [[type]] is also a [[container]] (although the [[class]] does not<br />
technically require <hask>Functor</hask>, interesting <hask>Foldable</hask>s are all <hask>Functor</hask>s). It is a container with the added property that its items can be 'folded' to a summary value. In other words, it is a type which supports "<hask>foldr</hask>".<br />
<br />
Once you support <hask>foldr</hask>, of course, you can be turned into a list, by using <hask>toList = foldr (:) []</hask>. This means that all <hask>Foldable</hask>s have a representation as a list, but the order of the items may or may not have any particular significance. However, if a <hask>Foldable</hask> is also a <hask>Functor</hask>, [[parametricity]] and the [[Functor law]] guarantee that <hask>toList</hask> and <hask>fmap</hask> commute. Further, in the case of <hask>Data.Sequence</hask>, there '''is''' a well defined order and it is exposed as expected by <hask>toList</hask>.<br />
<br />
A particular kind of fold well-used by Haskell programmers is <hask>mapM_</hask>, which is a kind of fold over <hask>(>>)</hask>, and <hask>Foldable</hask> provides this along with the related <hask>sequence_</hask>.<br />
<br />
===Traversable===<br />
<br />
A <hask>Traversable</hask> [[type]] is a kind of upgraded <hask>Foldable</hask>. Where <hask>Foldable</hask> gives you the ability to go through the structure processing the elements (<hask>foldr</hask>) but throwing away the shape, <hask>Traversable</hask> allows you to do that whilst preserving the shape and, e.g., putting new values in.<br />
<br />
<hask>Traversable</hask> is what we need for <hask>mapM</hask> and <hask>sequence</hask> : note the apparently surprising fact that the "_" versions are in a different [[typeclass]].<br />
<br />
== Some trickier functions: concatMap and filter ==<br />
<br />
Neither <hask>Traversable</hask> nor <hask>Foldable</hask> contain elements for <hask>concatMap</hask> and <hask>filter</hask>. That is because <hask>Foldable</hask> is about tearing down the structure completely, while <hask>Traversable</hask> is about preserving the structure exactly as-is. On the other hand <hask>concatMap</hask> tries to 'squeeze more elements in' at a place and <hask>filter</hask> tries to cut them out.<br />
<br />
You can write <hask>concatMap</hask> for <hask>Sequence</hask> as follows:<br />
<br />
<haskell><br />
concatMap :: (a -> Seq b) -> Seq a -> Seq b<br />
concatMap = foldMap<br />
</haskell><br />
<br />
But why does it work? It works because sequence is an instance of <hask>Monoid</hask>, where the [[monoid]]al operation is "appending". The same definition works for lists, and we can write it more generally as:<br />
<br />
<haskell><br />
concatMap :: (Foldable f, Monoid (f b)) => (a -> f b) -> f a -> f b<br />
concatMap = foldMap<br />
</haskell><br />
<br />
And that works with lists and sequences both. Does it work with any Monoid which is Foldable? Only if the Monoid 'means the right thing'. If you have <hask>toList (f `mappend` g) = toList f ++ toList g</hask> then it definitely makes sense. In fact this easy to write condition is stronger than needed; it would be good enough if they were permutations of each other.<br />
<br />
<hask>filter</hask> turns out to be slightly harder still. You need something like 'singleton' (from <hask>Sequence</hask>), or <hask>\a -> [a]</hask> for lists. We can use <hask>pure</hask> from <hask>Applicative</hask>, although it's not really right to bring <hask>Applicative</hask> in for this, and get:<br />
<br />
<haskell><br />
filter :: (Applicative f, Foldable f, Monoid (f a)) => <br />
(a -> Bool) -> f a -> f a<br />
filter p = foldMap (\a -> if p a then pure a else mempty)<br />
</haskell><br />
<br />
It's interesting to note that, under these conditions, we have a candidate to help us turn the <hask>Foldable</hask> into a <hask>Monad</hask>, since <hask>concatMap</hask> is a good definition for <hask>>>=</hask>, and we can use <hask>pure</hask> for <hask>return</hask>.<br />
<br />
== Generalising zipWith ==<br />
<br />
Another really useful list [[combinator]] that doesn't appear in the<br />
interfaces for <hask>Sequence</hask>, <hask>Foldable</hask> or <hask>Traversable</hask> is <hask>zipWith</hask>. The most general kind of <hask>zipWith</hask> over <hask>Traversable</hask>s will keep the exact shape of<br />
the <hask>Traversable</hask> on the left, whilst zipping against the values on the right. It turns out you can get away with a <hask>Foldable</hask> on the right, but you need to use a <hask>Monad</hask> (or an <hask>Applicative</hask>, actually) to thread the<br />
values through:<br />
<br />
<haskell><br />
import Prelude hiding (sequence)<br />
<br />
import Data.Sequence<br />
import Data.Foldable<br />
import Data.Traversable<br />
import Control.Applicative<br />
<br />
<br />
data Supply s v = Supply { unSupply :: [s] -> ([s],v) }<br />
<br />
instance Functor (Supply s) where <br />
fmap f av = Supply (\l -> let (l',v) = unSupply av l in (l',f v))<br />
<br />
instance Applicative (Supply s) where<br />
pure v = Supply (\l -> (l,v))<br />
af <*> av = Supply (\l -> let (l',f) = unSupply af l<br />
(l'',v) = unSupply av l'<br />
in (l'',f v))<br />
<br />
runSupply :: (Supply s v) -> [s] -> v<br />
runSupply av l = snd $ unSupply av l<br />
<br />
supply :: Supply s s<br />
supply = Supply (\(x:xs) -> (xs,x))<br />
<br />
zipTF :: (Traversable t, Foldable f) => t a -> f b -> t (a,b)<br />
zipTF t f = runSupply (traverse (\a -> (,) a <$> supply) t) (toList f)<br />
<br />
zipWithTF :: (Traversable t,Foldable f) => (a -> b -> c) -> t a -> f b -> t c<br />
zipWithTF g t f = runSupply (traverse (\a -> g a <$> supply) t) (toList f)<br />
<br />
zipWithTFM :: (Traversable t,Foldable f,Monad m) => <br />
(a -> b -> m c) -> t a -> f b -> m (t c)<br />
zipWithTFM g t f = sequence (zipWithTF g t f)<br />
<br />
zipWithTFA :: (Traversable t,Foldable f,Applicative m) => <br />
(a -> b -> m c) -> t a -> f b -> m (t c)<br />
zipWithTFA g t f = sequenceA (zipWithTF g t f)<br />
</haskell><br />
<br />
The code above fails with a [[pattern match]] error when the <hask>Foldable</hask> container doesn't have enough input. Here is an alternative version which provides friendlier error reports and makes use of <hask>State</hask> instead of the self defined Supply [[monad]].<br />
<br />
<haskell><br />
module GenericZip <br />
(zipWithTF,<br />
zipTF,<br />
zipWithTFA,<br />
zipWithTFM) where<br />
<br />
<br />
import Data.Foldable<br />
import Data.Traversable<br />
import qualified Data.Traversable as T<br />
import Control.Applicative<br />
import Control.Monad.State <br />
<br />
-- | The state contains the list of values obtained form the foldable container<br />
-- and a String indicating the name of the function currectly being executed<br />
data ZipState a = ZipState {fName :: String,<br />
list :: [a]}<br />
<br />
-- | State monad containing ZipState<br />
type ZipM l a = State (ZipState l) a<br />
<br />
-- | pops the first element of the list inside the state<br />
pop :: ZipM l l<br />
pop = do <br />
st <- get <br />
let xs = list st<br />
n = fName st<br />
case xs of<br />
(a:as) -> do put st{list=as}<br />
return a<br />
[] -> error $ n ++ ": insufficient input"<br />
<br />
-- | pop a value form the state and supply it to the second <br />
-- argument of a binary function <br />
supplySecond :: (a -> b -> c) -> a -> ZipM b c<br />
supplySecond f a = do b <- pop <br />
return $ f a b<br />
<br />
zipWithTFError :: (Traversable t,Foldable f) => <br />
String -> (a -> b -> c) -> t a -> f b -> t c <br />
zipWithTFError str g t f = evalState (T.mapM (supplySecond g) t) <br />
(ZipState str (toList f))<br />
<br />
<br />
zipWithTF :: (Traversable t,Foldable f) => (a -> b -> c) -> t a -> f b -> t c<br />
zipWithTF = zipWithTFError "GenericZip.zipWithTF"<br />
<br />
zipTF :: (Traversable t, Foldable f) => t a -> f b -> t (a,b)<br />
zipTF = zipWithTFError "GenericZip.zipTF" (,) <br />
<br />
<br />
zipWithTFM :: (Traversable t,Foldable f,Monad m) => <br />
(a -> b -> m c) -> t a -> f b -> m (t c)<br />
zipWithTFM g t f = T.sequence (zipWithTFError "GenericZip.zipWithTFM" g t f)<br />
<br />
zipWithTFA :: (Traversable t,Foldable f,Applicative m) => <br />
(a -> b -> m c) -> t a -> f b -> m (t c)<br />
zipWithTFA g t f = sequenceA (zipWithTFError "GenericZip.zipWithTFA" g t f)<br />
</haskell><br />
Recent versions of <hask>Data.Traversable</hask> include generalizations of <hask>mapAccumL</hask> and <hask>mapAccumR</hask> from lists to Traversables (encapsulating the state monad used above):<br />
<haskell><br />
mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
</haskell><br />
Using these, the first version above can be written as<br />
<haskell><br />
zipWithTF :: (Traversable t, Foldable f) => (a -> b -> c) -> t a -> f b -> t c<br />
zipWithTF g t f = snd (mapAccumL map_one (toList f) t)<br />
where map_one (x:xs) y = (xs, g y x)<br />
</haskell><br />
Replace <hask>mapAccumL</hask> with <hask>mapAccumR</hask> and the elements of the Foldable are zipped in reverse order.<br />
Similarly, we can define a generalization of <hask>reverse</hask> on Traversables, which preserves the shape but reverses the left-to-right position of the elements:<br />
<haskell><br />
reverseT :: (Traversable t) => t a -> t a<br />
reverseT t = snd (mapAccumR (\ (x:xs) _ -> (xs, x)) (toList t) t)<br />
</haskell></div>Jameshfisherhttps://wiki.haskell.org/index.php?title=Foldable_and_Traversable&diff=44643Foldable and Traversable2012-02-23T21:48:45Z<p>Jameshfisher: /* Some trickier functions: concatMap and filter */</p>
<hr />
<div>[[Category:Code]] [[Category:Idioms]]<br />
<br />
<center>'''Notes on Foldable, Traversable and other useful classes'''</center><br />
<center>'' or "Where is Data.Sequence.toList?"''</center><br />
<br />
[http://haskell.org/ghc/docs/latest/html/libraries/containers/Data-Sequence.html Data.Sequence] is recommended as an efficient alternative to [list]s,<br />
with a more symmetric feel and better complexity on various<br />
operations.<br />
<br />
When you've been using it for a little while, there seem to be some baffling omissions from the API. The first couple you are likely to notice are the absence of "<hask>map</hask>" and "<hask>toList</hask>".<br />
The answer to these lies in the long list of instances which Sequence has:<br />
* The Sequence version of map is "<hask>fmap</hask>", which comes from the Functor class. <br />
* The Sequence version of <hask>toList</hask> is in the <hask>Foldable</hask> [[class]].<br />
<br />
When working with <hask>Sequence</hask> you also want to refer to the documentation<br />
for at least <hask>Foldable</hask> and <hask>Traversable</hask>. <hask>Functor</hask> only has the single [[method]], so we've already covered that.<br />
<br />
==What do these classes all mean? A brief tour:==<br />
<br />
[[Image:FunctorHierarchy.svg]]<br />
<br />
===<hask>Functor</hask>===<br />
<br />
A [[functor]] is simply a [[container]]. Given a container, and a [[function]] which works on the elements, we can apply that function to each element. For lists, the familiar "<hask>map</hask>" does exactly this.<br />
<br />
Note that the function can produce elements of a different [[type]], so we<br />
may have a different type at the end.<br />
<br />
Examples:<br />
<br />
<haskell><br />
Prelude Data.Sequence> map (\n -> replicate n 'a') [1,3,5]<br />
["a","aaa","aaaaa"]<br />
Prelude Data.Sequence> fmap (\n -> replicate n 'a') (1 <| 3 <| 5 <| empty)<br />
fromList ["a","aaa","aaaaa"]<br />
</haskell><br />
<br />
===Foldable===<br />
<br />
A <hask>Foldable</hask> [[type]] is also a [[container]] (although the [[class]] does not<br />
technically require <hask>Functor</hask>, interesting <hask>Foldable</hask>s are all <hask>Functor</hask>s). It is a container with the added property that its items can be 'folded' to a summary value. In other words, it is a type which supports "<hask>foldr</hask>".<br />
<br />
Once you support <hask>foldr</hask>, of course, you can be turned into a list, by using <hask>toList = foldr (:) []</hask>. This means that all <hask>Foldable</hask>s have a representation as a list, but the order of the items may or may not have any particular significance. However, if a <hask>Foldable</hask> is also a <hask>Functor</hask>, [[parametricity]] and the [[Functor law]] guarantee that <hask>toList</hask> and <hask>fmap</hask> commute. Further, in the case of <hask>Data.Sequence</hask>, there '''is''' a well defined order and it is exposed as expected by <hask>toList</hask>.<br />
<br />
A particular kind of fold well-used by Haskell programmers is <hask>mapM_</hask>, which is a kind of fold over <hask>(>>)</hask>, and <hask>Foldable</hask> provides this along with the related <hask>sequence_</hask>.<br />
<br />
===Traversable===<br />
<br />
A <hask>Traversable</hask> [[type]] is a kind of upgraded <hask>Foldable</hask>. Where <hask>Foldable</hask> gives you the ability to go through the structure processing the elements (<hask>foldr</hask>) but throwing away the shape, <hask>Traversable</hask> allows you to do that whilst preserving the shape and, e.g., putting new values in.<br />
<br />
<hask>Traversable</hask> is what we need for <hask>mapM</hask> and <hask>sequence</hask> : note the apparently surprising fact that the "_" versions are in a different [[typeclass]].<br />
<br />
== Some trickier functions: concatMap and filter ==<br />
<br />
Neither <hask>Traversable</hask> nor <hask>Foldable</hask> contain elements for <hask>concatMap</hask> and <hask>filter</hask>. That is because <hask>Foldable</hask> is about tearing down the structure<br />
completely, while <hask>Traversable</hask> is about preserving the structure<br />
exactly as-is. On the other hand <hask>concatMap</hask> tries to<br />
'squeeze more elements in' at a place and <hask>filter</hask> tries to<br />
cut them out.<br />
<br />
You can write <hask>concatMap</hask> for <hask>Sequence</hask> as follows:<br />
<br />
<haskell><br />
concatMap :: (a -> Seq b) -> Seq a -> Seq b<br />
concatMap = foldMap<br />
</haskell><br />
<br />
But why does it work? It works because sequence is an instance of <hask>Monoid</hask>, where the [[monoid]]al operation is "appending". The same<br />
definition works for lists, and we can write it more generally as:<br />
<br />
<haskell><br />
concatMap :: (Foldable f, Monoid (f b)) => (a -> f b) -> f a -> f b<br />
concatMap = foldMap<br />
</haskell><br />
<br />
And that works with lists and sequences both. Does it work with any<br />
Monoid which is Foldable? Only if the Monoid 'means the right thing'. If you have <hask>toList (f `mappend` g) = toList f ++ toList g</hask> then it definitely makes sense. In fact this easy to write<br />
condition is stronger than needed; it would be good enough if they<br />
were permutations of each other.<br />
<br />
<hask>filter</hask> turns out to be slightly harder still. You need<br />
something like 'singleton' (from <hask>Sequence</hask>), or <hask>\a -> [a]</hask><br />
for lists. We can use <hask>pure</hask> from <hask>Applicative</hask>, although<br />
it's not really right to bring <hask>Applicative</hask> in for this, and get:<br />
<br />
<haskell><br />
filter :: (Applicative f, Foldable f, Monoid (f a)) => <br />
(a -> Bool) -> f a -> f a<br />
filter p = foldMap (\a -> if p a then pure a else mempty)<br />
</haskell><br />
<br />
It's interesting to note that, under these conditions, we have a candidate<br />
to help us turn the <hask>Foldable</hask> into a <hask>Monad</hask>, since <hask>concatMap</hask> is a good<br />
definition for <hask>>>=</hask>, and we can use <hask>pure</hask> for <hask>return</hask>.<br />
<br />
== Generalising zipWith ==<br />
<br />
Another really useful list [[combinator]] that doesn't appear in the<br />
interfaces for <hask>Sequence</hask>, <hask>Foldable</hask> or <hask>Traversable</hask> is <hask>zipWith</hask>. The most general kind of <hask>zipWith</hask> over <hask>Traversable</hask>s will keep the exact shape of<br />
the <hask>Traversable</hask> on the left, whilst zipping against the values on the right. It turns out you can get away with a <hask>Foldable</hask> on the right, but you need to use a <hask>Monad</hask> (or an <hask>Applicative</hask>, actually) to thread the<br />
values through:<br />
<br />
<haskell><br />
import Prelude hiding (sequence)<br />
<br />
import Data.Sequence<br />
import Data.Foldable<br />
import Data.Traversable<br />
import Control.Applicative<br />
<br />
<br />
data Supply s v = Supply { unSupply :: [s] -> ([s],v) }<br />
<br />
instance Functor (Supply s) where <br />
fmap f av = Supply (\l -> let (l',v) = unSupply av l in (l',f v))<br />
<br />
instance Applicative (Supply s) where<br />
pure v = Supply (\l -> (l,v))<br />
af <*> av = Supply (\l -> let (l',f) = unSupply af l<br />
(l'',v) = unSupply av l'<br />
in (l'',f v))<br />
<br />
runSupply :: (Supply s v) -> [s] -> v<br />
runSupply av l = snd $ unSupply av l<br />
<br />
supply :: Supply s s<br />
supply = Supply (\(x:xs) -> (xs,x))<br />
<br />
zipTF :: (Traversable t, Foldable f) => t a -> f b -> t (a,b)<br />
zipTF t f = runSupply (traverse (\a -> (,) a <$> supply) t) (toList f)<br />
<br />
zipWithTF :: (Traversable t,Foldable f) => (a -> b -> c) -> t a -> f b -> t c<br />
zipWithTF g t f = runSupply (traverse (\a -> g a <$> supply) t) (toList f)<br />
<br />
zipWithTFM :: (Traversable t,Foldable f,Monad m) => <br />
(a -> b -> m c) -> t a -> f b -> m (t c)<br />
zipWithTFM g t f = sequence (zipWithTF g t f)<br />
<br />
zipWithTFA :: (Traversable t,Foldable f,Applicative m) => <br />
(a -> b -> m c) -> t a -> f b -> m (t c)<br />
zipWithTFA g t f = sequenceA (zipWithTF g t f)<br />
</haskell><br />
<br />
The code above fails with a [[pattern match]] error when the <hask>Foldable</hask> container doesn't have enough input. Here is an alternative version which provides friendlier error reports and makes use of <hask>State</hask> instead of the self defined Supply [[monad]].<br />
<br />
<haskell><br />
module GenericZip <br />
(zipWithTF,<br />
zipTF,<br />
zipWithTFA,<br />
zipWithTFM) where<br />
<br />
<br />
import Data.Foldable<br />
import Data.Traversable<br />
import qualified Data.Traversable as T<br />
import Control.Applicative<br />
import Control.Monad.State <br />
<br />
-- | The state contains the list of values obtained form the foldable container<br />
-- and a String indicating the name of the function currectly being executed<br />
data ZipState a = ZipState {fName :: String,<br />
list :: [a]}<br />
<br />
-- | State monad containing ZipState<br />
type ZipM l a = State (ZipState l) a<br />
<br />
-- | pops the first element of the list inside the state<br />
pop :: ZipM l l<br />
pop = do <br />
st <- get <br />
let xs = list st<br />
n = fName st<br />
case xs of<br />
(a:as) -> do put st{list=as}<br />
return a<br />
[] -> error $ n ++ ": insufficient input"<br />
<br />
-- | pop a value form the state and supply it to the second <br />
-- argument of a binary function <br />
supplySecond :: (a -> b -> c) -> a -> ZipM b c<br />
supplySecond f a = do b <- pop <br />
return $ f a b<br />
<br />
zipWithTFError :: (Traversable t,Foldable f) => <br />
String -> (a -> b -> c) -> t a -> f b -> t c <br />
zipWithTFError str g t f = evalState (T.mapM (supplySecond g) t) <br />
(ZipState str (toList f))<br />
<br />
<br />
zipWithTF :: (Traversable t,Foldable f) => (a -> b -> c) -> t a -> f b -> t c<br />
zipWithTF = zipWithTFError "GenericZip.zipWithTF"<br />
<br />
zipTF :: (Traversable t, Foldable f) => t a -> f b -> t (a,b)<br />
zipTF = zipWithTFError "GenericZip.zipTF" (,) <br />
<br />
<br />
zipWithTFM :: (Traversable t,Foldable f,Monad m) => <br />
(a -> b -> m c) -> t a -> f b -> m (t c)<br />
zipWithTFM g t f = T.sequence (zipWithTFError "GenericZip.zipWithTFM" g t f)<br />
<br />
zipWithTFA :: (Traversable t,Foldable f,Applicative m) => <br />
(a -> b -> m c) -> t a -> f b -> m (t c)<br />
zipWithTFA g t f = sequenceA (zipWithTFError "GenericZip.zipWithTFA" g t f)<br />
</haskell><br />
Recent versions of <hask>Data.Traversable</hask> include generalizations of <hask>mapAccumL</hask> and <hask>mapAccumR</hask> from lists to Traversables (encapsulating the state monad used above):<br />
<haskell><br />
mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)<br />
</haskell><br />
Using these, the first version above can be written as<br />
<haskell><br />
zipWithTF :: (Traversable t, Foldable f) => (a -> b -> c) -> t a -> f b -> t c<br />
zipWithTF g t f = snd (mapAccumL map_one (toList f) t)<br />
where map_one (x:xs) y = (xs, g y x)<br />
</haskell><br />
Replace <hask>mapAccumL</hask> with <hask>mapAccumR</hask> and the elements of the Foldable are zipped in reverse order.<br />
Similarly, we can define a generalization of <hask>reverse</hask> on Traversables, which preserves the shape but reverses the left-to-right position of the elements:<br />
<haskell><br />
reverseT :: (Traversable t) => t a -> t a<br />
reverseT t = snd (mapAccumR (\ (x:xs) _ -> (xs, x)) (toList t) t)<br />
</haskell></div>Jameshfisherhttps://wiki.haskell.org/index.php?title=OpenGLTutorial1&diff=44580OpenGLTutorial12012-02-20T00:48:55Z<p>Jameshfisher: /* Callbacks - how we react to changes */ typo, code</p>
<hr />
<div>''This tutorial [http://blog.mikael.johanssons.org/archive/2006/09/opengl-programming-in-haskell-a-tutorial-part-1/] was originally written by Mikael Vejdemo Johansson, and was copied here with permission.''<br />
<br />
After having failed following the [http://www.cs.hs-rm.de/~panitz/hopengl/skript.html googled tutorial in HOpenGL programming], I thought I'd write down the steps I actually can get to work in a tutorial-like fashion. It may be a good idea to read this in parallell to the tutorial linked, since Panitz actually brings a lot of good explanations, even though his syntax isn't up to speed with the latest HOpenGL at all points.<br />
<br />
Note: GHCI interactive shell has problems running these program on some platforms (such as Mac OS X). <strong>Vompile these programs with ghc, and run the generated executables.<br />
</strong><br />
<br />
==Hello World==<br />
First of all, we'll want to load the OpenGL libraries, throw up a window, and generally get to grips with what needs to be done to get a program running at all. <br />
<br />
<haskell><br />
import Graphics.Rendering.OpenGL<br />
import Graphics.UI.GLUT<br />
<br />
main :: IO ()<br />
main = do <br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= flush<br />
mainLoop<br />
</haskell><br />
<br />
This code throws up a window, with a given title, and sets the main display function to do nothing but flush the (empty) graphics buffer. This is the skeleton that we'll be building on to.<br />
<br />
Save it to HelloWorld.hs and compile it by running <hask>ghc -package GLUT HelloWorld.hs -o HelloWorld</hask>.<br />
<br />
You will see a window open, with the title "Hello World", with either a blank canvas, or with some garbage graphics content pulled from somewhere in your system's graphics memory.<br />
<br />
In either case, this program is profoundly worthless.<br />
<br />
At a minimum, let's have our program display a clean blank canvas:<br />
<br />
So we modify our code to the following:<br />
<br />
<haskell><br />
import Graphics.Rendering.OpenGL<br />
import Graphics.UI.GLUT<br />
<br />
main :: IO ()<br />
main = do<br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= display<br />
mainLoop<br />
<br />
display :: IO ()<br />
display = do<br />
clear [ ColorBuffer ]; flush<br />
<br />
</haskell><br />
<br />
This defines a function "display" that calls a few OpenGL functions: "clear" to clear out the graphics color state (so we get a blank canvas), and "flush" to push our OpenGL commands down to the system graphics for actual display.<br />
<br />
We don't call "display" directly. (In fact, we don't call any graphics drawing functions directly). Instead, we set a display callback, and then call mainLoop. In mainLoop, OpenGL akes over, handles all the details of interacting with the OS and refreshing our window, calling our displayCallback to draw graphics.<br />
<br />
displayCallback is a Data.IORef (mutable state variable), which we set using a call to <hask>($=)</hask>.<br />
<br />
Save this to the HelloWorld.hs, recompile, and rerun. This program displays an endless series of blank canvases (a solid blank image).<br />
<br />
The displayCallback is a globally defined IORef, which can be accessed through a host of functions defined in Data.IORef. In [http://hackage.haskell.org/packages/archive/OpenGL/2.2.2.0/doc/html/Graphics-Rendering-OpenGL-GL-StateVar.html OpenGL StateVar module], there is a HasSetter type class and an IORef implementation providing functions <hask>($=)</hask> (assignment) and <hask>get</hask> to fascilitate interactions with these state variables. <br />
<br />
<haskell><br />
height = newIORef 1.0<br />
currentheight <- get height<br />
height $= 1.5<br />
</haskell><br />
<br />
==Using the drawing canvas==<br />
So, we have a window, we have a display callback that clears the canvas. Don't we want more out of it? Sure we do. So let's draw some things.<br />
<haskell><br />
import Graphics.Rendering.OpenGL<br />
import Graphics.UI.GLUT<br />
myPoints :: [(GLfloat,GLfloat,GLfloat)]<br />
myPoints = map (\k -> (sin(2*pi*k/12),cos(2*pi*k/12),0.0)) [1..12]<br />
main = do <br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= display<br />
mainLoop<br />
display = do <br />
clear [ColorBuffer]<br />
renderPrimitive Points $ mapM_ (\(x, y, z)->vertex$Vertex3 x y z) myPoints<br />
flush<br />
</haskell><br />
<br />
Now, the important thing to notice in this code extract is that last line. It starts a rendering definition, gives the type to be rendered, and then a sequence of function calls, each of which adds a vertex to the rendering canvas. The statement is basically equivalent to something along the lines of<br />
<haskell><br />
renderPrimitive Points do<br />
vertex Vertex3 ...<br />
vertex Vertex3 ...<br />
</haskell><br />
for appropriate triples of coordinate values at the appropriate places. This results in the rendition here:<br />
<br />
[[image:OG-Points.png]]<br />
<br />
We can replace <code>Points</code> with other primitives, leading to the rendering of:<br />
<br />
===<code>Triangles</code>===<br />
[[image:OG-Triangles.png]]<br />
<br />
Each three coordinates following each other define a triangle. The last n mod 3 coordinates are ignored.<br />
<br />
Keyword <code>Triangles</code><br />
<br />
===Triangle strips===<br />
[[image:OG-Trianglestrip.png]]<br />
<br />
Triangles are drawn according to a “moving window” of size three, so the two last coordinates in the previous triangle become the two first in the next triangle.<br />
<br />
Keyword <code>TriangleStrip</code><br />
<br />
===Triangle fans===<br />
[[image:OG-Trianglesfan.png]]<br />
<br />
<code>TriangleFan</code>s have the first given coordinate as a basepoint, and takes each pair of subsequent coordinates to define a triangle together with the first coordinate.<br />
<br />
Keyword <code>TriangleFan</code><br />
<br />
===Lines===<br />
[[image:OG-Lines.png]]<br />
<br />
Each pair of coordinates define a line.<br />
<br />
Keyword <code>Lines</code><br />
<br />
===Line loops===<br />
[[image:OG-Lineloop.png]]<br />
<br />
With <code>LineLoop</code>s, each further coordinate defines a line together with the last coordinate used. Once all coordinates are used up, an additional line is drawn back to the beginning.<br />
<br />
Keyword <code>LineLoop</code><br />
<br />
===Line strips===<br />
[[image:OG-Linestrip.png]]<br />
<br />
<code>LineStrip</code>s are like <code>LineLoop</code>s, only without the last link added.<br />
<br />
Keyword <code>LineStrip</code><br />
<br />
===Quadrangles===<br />
[[image:OG-Quad.png]]<br />
<br />
For the <code>Quads</code> keyword, each four coordinates given define a quadrangle.<br />
<br />
Keyword <code>Quads</code><br />
<br />
===Quadrangle strips===<br />
[[image:OG-Quadstrip.png]]<br />
<br />
And a <code>QuadStrip</code> works as the <code>TriangleStrip</code>, only the window is 4 coordinates wide and steps 2 steps each time, so each new pair of coordinates attaches a new quadrangle to the last edge of the last quadrangle.<br />
<br />
Keyword <code>QuadStrip</code><br />
<br />
===Polygon===<br />
[[image:OG-Polygon.png]]<br />
<br />
A <code>Polygon</code> is a filled line loop. Simple as that!<br />
<br />
Keyword <code>Polygon</code><br />
<br />
There are more things we can do on our canvas than just spreading out coordinates. Within the command list constructed after a renderPrimitive, we can give several different commands that control what things are supposed to look like, so for instance we could use the following:<br />
<haskell><br />
display = do <br />
clear [ColorBuffer]<br />
renderPrimitive Quads $ do<br />
color $ (Color3 (1.0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0.2 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) 0.2 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) 0 0)<br />
color $ (Color3 (0::GLfloat) 1 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) 0 0)<br />
color $ (Color3 (0::GLfloat) 0 1)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 ((-0.2)::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 ((-0.2)::GLfloat) 0 0)<br />
color $ (Color3 (1::GLfloat) 0 1)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0.2 0)<br />
vertex $ (Vertex3 ((-0.2::GLfloat)) 0.2 0)<br />
vertex $ (Vertex3 ((-0.2::GLfloat)) 0 0)<br />
flush<br />
</haskell><br />
in order to produce these four coloured squares:<br />
<br />
[[image:OG-Colorsquares.png]]<br />
<br />
where each color command sets the color for the next item drawn, and the vertex commands give vertices for the four squares.<br />
<br />
==Callbacks - how we react to changes==<br />
We have already seen one callback in action: <code>displayCallback</code>. The Callbacks are state variables of the HOpenGL system, and are called in order to handle various things that may happen to the place the drawing canvas lives. For a first exercise, go resize the latest window you've used. Go on, do it now.<br />
<br />
I bet it looked ugly, didn't it?<br />
<br />
This is because we have no code handling what to do if the window should suddenly change. Handling this is done in a callback, residing in the <code>IORef reshapeCallback</code>. Similarly, repainting is done in <code>displayCallback</code>, keyboard and mouse input is in <code>keyboardMouseCallback</code>, and so on. We can refer to the HOpenGL documentation for [http://hackage.haskell.org/packages/archive/GLUT/latest/doc/html/Graphics-UI-GLUT-Callbacks-Window.html window callbacks] and for [http://hackage.haskell.org/packages/archive/GLUT/latest/doc/html/Graphics-UI-GLUT-Callbacks-Global.html global callbacks]. Window callbacks are things like display, keyboard and mouse, and reshape. Global callbacks deal with timing issues (for those snazzy animations) and the menu interface systems.<br />
<br />
In order for a callback to possibly not be defined, most are typed within the <code>Maybe</code> monad, so by setting the state variable to <code>Nothing</code>, a callback can be disabled. Thus, setting callbacks is done using the keyword <code>Just</code>. We'll add a callback for reshaping the window to our neat code, changing the main function to:<br />
<haskell><br />
main = do <br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= display<br />
reshapeCallback $= Just reshape<br />
mainLoop<br />
reshape s@(Size w h) = do<br />
viewport $= (Position 0 0, s)<br />
postRedisplay Nothing<br />
</haskell><br />
<br />
Here, the code for the reshape function resizes the viewport so that our drawing area contains the entire new window. After setting the new viewport, it also tells the windowing system that something has happened to the window, and that therefore, the display function should be called.<br />
<br />
==Summary==<br />
So, in conclusion, so far we can display a window, post basic callbacks to get the windowhandling to run smoothly, and draw in our window. Next installment of the tutorial will bring you 3d drawing, keyboard and mouse interactions, the incredible power of matrices and the ability to rotate 3d objects for your leisure. Possibly, we'll even look into animations.<br />
<br />
[[OpenGLTutorial2|Continue with part 2]]</div>Jameshfisherhttps://wiki.haskell.org/index.php?title=OpenGLTutorial1&diff=44579OpenGLTutorial12012-02-20T00:44:55Z<p>Jameshfisher: /* Using the drawing canvas */ code</p>
<hr />
<div>''This tutorial [http://blog.mikael.johanssons.org/archive/2006/09/opengl-programming-in-haskell-a-tutorial-part-1/] was originally written by Mikael Vejdemo Johansson, and was copied here with permission.''<br />
<br />
After having failed following the [http://www.cs.hs-rm.de/~panitz/hopengl/skript.html googled tutorial in HOpenGL programming], I thought I'd write down the steps I actually can get to work in a tutorial-like fashion. It may be a good idea to read this in parallell to the tutorial linked, since Panitz actually brings a lot of good explanations, even though his syntax isn't up to speed with the latest HOpenGL at all points.<br />
<br />
Note: GHCI interactive shell has problems running these program on some platforms (such as Mac OS X). <strong>Vompile these programs with ghc, and run the generated executables.<br />
</strong><br />
<br />
==Hello World==<br />
First of all, we'll want to load the OpenGL libraries, throw up a window, and generally get to grips with what needs to be done to get a program running at all. <br />
<br />
<haskell><br />
import Graphics.Rendering.OpenGL<br />
import Graphics.UI.GLUT<br />
<br />
main :: IO ()<br />
main = do <br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= flush<br />
mainLoop<br />
</haskell><br />
<br />
This code throws up a window, with a given title, and sets the main display function to do nothing but flush the (empty) graphics buffer. This is the skeleton that we'll be building on to.<br />
<br />
Save it to HelloWorld.hs and compile it by running <hask>ghc -package GLUT HelloWorld.hs -o HelloWorld</hask>.<br />
<br />
You will see a window open, with the title "Hello World", with either a blank canvas, or with some garbage graphics content pulled from somewhere in your system's graphics memory.<br />
<br />
In either case, this program is profoundly worthless.<br />
<br />
At a minimum, let's have our program display a clean blank canvas:<br />
<br />
So we modify our code to the following:<br />
<br />
<haskell><br />
import Graphics.Rendering.OpenGL<br />
import Graphics.UI.GLUT<br />
<br />
main :: IO ()<br />
main = do<br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= display<br />
mainLoop<br />
<br />
display :: IO ()<br />
display = do<br />
clear [ ColorBuffer ]; flush<br />
<br />
</haskell><br />
<br />
This defines a function "display" that calls a few OpenGL functions: "clear" to clear out the graphics color state (so we get a blank canvas), and "flush" to push our OpenGL commands down to the system graphics for actual display.<br />
<br />
We don't call "display" directly. (In fact, we don't call any graphics drawing functions directly). Instead, we set a display callback, and then call mainLoop. In mainLoop, OpenGL akes over, handles all the details of interacting with the OS and refreshing our window, calling our displayCallback to draw graphics.<br />
<br />
displayCallback is a Data.IORef (mutable state variable), which we set using a call to <hask>($=)</hask>.<br />
<br />
Save this to the HelloWorld.hs, recompile, and rerun. This program displays an endless series of blank canvases (a solid blank image).<br />
<br />
The displayCallback is a globally defined IORef, which can be accessed through a host of functions defined in Data.IORef. In [http://hackage.haskell.org/packages/archive/OpenGL/2.2.2.0/doc/html/Graphics-Rendering-OpenGL-GL-StateVar.html OpenGL StateVar module], there is a HasSetter type class and an IORef implementation providing functions <hask>($=)</hask> (assignment) and <hask>get</hask> to fascilitate interactions with these state variables. <br />
<br />
<haskell><br />
height = newIORef 1.0<br />
currentheight <- get height<br />
height $= 1.5<br />
</haskell><br />
<br />
==Using the drawing canvas==<br />
So, we have a window, we have a display callback that clears the canvas. Don't we want more out of it? Sure we do. So let's draw some things.<br />
<haskell><br />
import Graphics.Rendering.OpenGL<br />
import Graphics.UI.GLUT<br />
myPoints :: [(GLfloat,GLfloat,GLfloat)]<br />
myPoints = map (\k -> (sin(2*pi*k/12),cos(2*pi*k/12),0.0)) [1..12]<br />
main = do <br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= display<br />
mainLoop<br />
display = do <br />
clear [ColorBuffer]<br />
renderPrimitive Points $ mapM_ (\(x, y, z)->vertex$Vertex3 x y z) myPoints<br />
flush<br />
</haskell><br />
<br />
Now, the important thing to notice in this code extract is that last line. It starts a rendering definition, gives the type to be rendered, and then a sequence of function calls, each of which adds a vertex to the rendering canvas. The statement is basically equivalent to something along the lines of<br />
<haskell><br />
renderPrimitive Points do<br />
vertex Vertex3 ...<br />
vertex Vertex3 ...<br />
</haskell><br />
for appropriate triples of coordinate values at the appropriate places. This results in the rendition here:<br />
<br />
[[image:OG-Points.png]]<br />
<br />
We can replace <code>Points</code> with other primitives, leading to the rendering of:<br />
<br />
===<code>Triangles</code>===<br />
[[image:OG-Triangles.png]]<br />
<br />
Each three coordinates following each other define a triangle. The last n mod 3 coordinates are ignored.<br />
<br />
Keyword <code>Triangles</code><br />
<br />
===Triangle strips===<br />
[[image:OG-Trianglestrip.png]]<br />
<br />
Triangles are drawn according to a “moving window” of size three, so the two last coordinates in the previous triangle become the two first in the next triangle.<br />
<br />
Keyword <code>TriangleStrip</code><br />
<br />
===Triangle fans===<br />
[[image:OG-Trianglesfan.png]]<br />
<br />
<code>TriangleFan</code>s have the first given coordinate as a basepoint, and takes each pair of subsequent coordinates to define a triangle together with the first coordinate.<br />
<br />
Keyword <code>TriangleFan</code><br />
<br />
===Lines===<br />
[[image:OG-Lines.png]]<br />
<br />
Each pair of coordinates define a line.<br />
<br />
Keyword <code>Lines</code><br />
<br />
===Line loops===<br />
[[image:OG-Lineloop.png]]<br />
<br />
With <code>LineLoop</code>s, each further coordinate defines a line together with the last coordinate used. Once all coordinates are used up, an additional line is drawn back to the beginning.<br />
<br />
Keyword <code>LineLoop</code><br />
<br />
===Line strips===<br />
[[image:OG-Linestrip.png]]<br />
<br />
<code>LineStrip</code>s are like <code>LineLoop</code>s, only without the last link added.<br />
<br />
Keyword <code>LineStrip</code><br />
<br />
===Quadrangles===<br />
[[image:OG-Quad.png]]<br />
<br />
For the <code>Quads</code> keyword, each four coordinates given define a quadrangle.<br />
<br />
Keyword <code>Quads</code><br />
<br />
===Quadrangle strips===<br />
[[image:OG-Quadstrip.png]]<br />
<br />
And a <code>QuadStrip</code> works as the <code>TriangleStrip</code>, only the window is 4 coordinates wide and steps 2 steps each time, so each new pair of coordinates attaches a new quadrangle to the last edge of the last quadrangle.<br />
<br />
Keyword <code>QuadStrip</code><br />
<br />
===Polygon===<br />
[[image:OG-Polygon.png]]<br />
<br />
A <code>Polygon</code> is a filled line loop. Simple as that!<br />
<br />
Keyword <code>Polygon</code><br />
<br />
There are more things we can do on our canvas than just spreading out coordinates. Within the command list constructed after a renderPrimitive, we can give several different commands that control what things are supposed to look like, so for instance we could use the following:<br />
<haskell><br />
display = do <br />
clear [ColorBuffer]<br />
renderPrimitive Quads $ do<br />
color $ (Color3 (1.0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0.2 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) 0.2 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) 0 0)<br />
color $ (Color3 (0::GLfloat) 1 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) 0 0)<br />
color $ (Color3 (0::GLfloat) 0 1)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 ((-0.2)::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 ((-0.2)::GLfloat) 0 0)<br />
color $ (Color3 (1::GLfloat) 0 1)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0.2 0)<br />
vertex $ (Vertex3 ((-0.2::GLfloat)) 0.2 0)<br />
vertex $ (Vertex3 ((-0.2::GLfloat)) 0 0)<br />
flush<br />
</haskell><br />
in order to produce these four coloured squares:<br />
<br />
[[image:OG-Colorsquares.png]]<br />
<br />
where each color command sets the color for the next item drawn, and the vertex commands give vertices for the four squares.<br />
<br />
==Callbacks - how we react to changes==<br />
We have already seen one callback in action: displayCallBack. The Callbacks are state variables of the HOpenGL system, and are called in order to handle various things that may happen to the place the drawing canvas lives. For a first exercise, go resize the latest window you've used. Go on, do it now.<br />
<br />
I bet it looked ugly, didn't it?<br />
<br />
This is because we have no code handling what to do if the window should suddenly change. Handling this is done in a callback, residing in the IORef reshapeCallback. Similarily, repainting is done in displayCallback, keyboard and mouse input is in keyboardMouseCallback, and so on. We can refer to the HOpenGL documentation for [http://hackage.haskell.org/packages/archive/GLUT/latest/doc/html/Graphics-UI-GLUT-Callbacks-Window.html window callbacks] and for [http://hackage.haskell.org/packages/archive/GLUT/latest/doc/html/Graphics-UI-GLUT-Callbacks-Global.html global callbacks]. Window callbacks are things like display, keyboard and mouse, and reshape. Global callbacks deal with timing issues (for those snazzy animations) and the menu interface systems.<br />
<br />
In order for a callback to possibly not be defined, most are typed within the Maybe monad, so by setting the state variable to Nothing, a callback can be disabled. Thus, setting callbacks is done using the keyword Just. We'll add a callback for reshaping the window to our neat code, changing the main function to:<br />
<haskell><br />
main = do <br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= display<br />
reshapeCallback $= Just reshape<br />
mainLoop<br />
reshape s@(Size w h) = do<br />
viewport $= (Position 0 0, s)<br />
postRedisplay Nothing<br />
</haskell><br />
<br />
Here, the code for the reshape function resizes the viewport so that our drawing area contains the entire new window. After setting the new viewport, it also tells the windowing system that something has happened to the window, and that therefore, the display function should be called.<br />
<br />
==Summary==<br />
So, in conclusion, so far we can display a window, post basic callbacks to get the windowhandling to run smoothly, and draw in our window. Next installment of the tutorial will bring you 3d drawing, keyboard and mouse interactions, the incredible power of matrices and the ability to rotate 3d objects for your leisure. Possibly, we'll even look into animations.<br />
<br />
[[OpenGLTutorial2|Continue with part 2]]</div>Jameshfisherhttps://wiki.haskell.org/index.php?title=OpenGLTutorial1&diff=44578OpenGLTutorial12012-02-20T00:38:20Z<p>Jameshfisher: /* Using the drawing canvas */ typo</p>
<hr />
<div>''This tutorial [http://blog.mikael.johanssons.org/archive/2006/09/opengl-programming-in-haskell-a-tutorial-part-1/] was originally written by Mikael Vejdemo Johansson, and was copied here with permission.''<br />
<br />
After having failed following the [http://www.cs.hs-rm.de/~panitz/hopengl/skript.html googled tutorial in HOpenGL programming], I thought I'd write down the steps I actually can get to work in a tutorial-like fashion. It may be a good idea to read this in parallell to the tutorial linked, since Panitz actually brings a lot of good explanations, even though his syntax isn't up to speed with the latest HOpenGL at all points.<br />
<br />
Note: GHCI interactive shell has problems running these program on some platforms (such as Mac OS X). <strong>Vompile these programs with ghc, and run the generated executables.<br />
</strong><br />
<br />
==Hello World==<br />
First of all, we'll want to load the OpenGL libraries, throw up a window, and generally get to grips with what needs to be done to get a program running at all. <br />
<br />
<haskell><br />
import Graphics.Rendering.OpenGL<br />
import Graphics.UI.GLUT<br />
<br />
main :: IO ()<br />
main = do <br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= flush<br />
mainLoop<br />
</haskell><br />
<br />
This code throws up a window, with a given title, and sets the main display function to do nothing but flush the (empty) graphics buffer. This is the skeleton that we'll be building on to.<br />
<br />
Save it to HelloWorld.hs and compile it by running <hask>ghc -package GLUT HelloWorld.hs -o HelloWorld</hask>.<br />
<br />
You will see a window open, with the title "Hello World", with either a blank canvas, or with some garbage graphics content pulled from somewhere in your system's graphics memory.<br />
<br />
In either case, this program is profoundly worthless.<br />
<br />
At a minimum, let's have our program display a clean blank canvas:<br />
<br />
So we modify our code to the following:<br />
<br />
<haskell><br />
import Graphics.Rendering.OpenGL<br />
import Graphics.UI.GLUT<br />
<br />
main :: IO ()<br />
main = do<br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= display<br />
mainLoop<br />
<br />
display :: IO ()<br />
display = do<br />
clear [ ColorBuffer ]; flush<br />
<br />
</haskell><br />
<br />
This defines a function "display" that calls a few OpenGL functions: "clear" to clear out the graphics color state (so we get a blank canvas), and "flush" to push our OpenGL commands down to the system graphics for actual display.<br />
<br />
We don't call "display" directly. (In fact, we don't call any graphics drawing functions directly). Instead, we set a display callback, and then call mainLoop. In mainLoop, OpenGL akes over, handles all the details of interacting with the OS and refreshing our window, calling our displayCallback to draw graphics.<br />
<br />
displayCallback is a Data.IORef (mutable state variable), which we set using a call to <hask>($=)</hask>.<br />
<br />
Save this to the HelloWorld.hs, recompile, and rerun. This program displays an endless series of blank canvases (a solid blank image).<br />
<br />
The displayCallback is a globally defined IORef, which can be accessed through a host of functions defined in Data.IORef. In [http://hackage.haskell.org/packages/archive/OpenGL/2.2.2.0/doc/html/Graphics-Rendering-OpenGL-GL-StateVar.html OpenGL StateVar module], there is a HasSetter type class and an IORef implementation providing functions <hask>($=)</hask> (assignment) and <hask>get</hask> to fascilitate interactions with these state variables. <br />
<br />
<haskell><br />
height = newIORef 1.0<br />
currentheight <- get height<br />
height $= 1.5<br />
</haskell><br />
<br />
==Using the drawing canvas==<br />
So, we have a window, we have a display callback that clears the canvas. Don't we want more out of it? Sure we do. So let's draw some things.<br />
<haskell><br />
import Graphics.Rendering.OpenGL<br />
import Graphics.UI.GLUT<br />
myPoints :: [(GLfloat,GLfloat,GLfloat)]<br />
myPoints = map (\k -> (sin(2*pi*k/12),cos(2*pi*k/12),0.0)) [1..12]<br />
main = do <br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= display<br />
mainLoop<br />
display = do <br />
clear [ColorBuffer]<br />
renderPrimitive Points $ mapM_ (\(x, y, z)->vertex$Vertex3 x y z) myPoints<br />
flush<br />
</haskell><br />
<br />
Now, the important thing to notice in this code extract is that last line. It starts a rendering definition, gives the type to be rendered, and then a sequence of function calls, each of which adds a vertex to the rendering canvas. The statement is basically equivalent to something along the lines of<br />
<haskell><br />
renderPrimitive Points do<br />
vertex Vertex3 ...<br />
vertex Vertex3 ...<br />
</haskell><br />
for appropriate triples of coordinate values at the appropriate places. This results in the rendition here:<br />
<br />
[[image:OG-Points.png]]<br />
<br />
We can replace Points with other primitives, leading to the rendering of:<br />
<br />
===Triangles===<br />
[[image:OG-Triangles.png]]<br />
<br />
Each three coordinates following each other define a triangle. The last n mod 3 coordinates are ignored.<br />
<br />
Keyword Triangles<br />
<br />
===Triangle strips===<br />
[[image:OG-Trianglestrip.png]]<br />
<br />
Triangles are drawn according to a “moving window” of size three, so the two last coordinates in the previous triangle become the two first in the next triangle.<br />
<br />
Keyword TriangleStrip<br />
<br />
===Triangle fans===<br />
[[image:OG-Trianglesfan.png]]<br />
<br />
Triangle fans have the first given coordinate as a basepoint, and takes each pair of subsequent coordinates to define a triangle together with the first coordinate.<br />
<br />
Keyword TriangleFan<br />
<br />
===Lines===<br />
[[image:OG-Lines.png]]<br />
<br />
Each pair of coordinates define a line.<br />
<br />
Keyword Lines<br />
<br />
===Line loops===<br />
[[image:OG-Lineloop.png]]<br />
<br />
With line loops, each further coordinate defines a line together with the last coordinate used. Once all coordinates are used up, an additional line is drawn back to the beginning.<br />
<br />
Keyword LineLoop<br />
<br />
===Line strips===<br />
[[image:OG-Linestrip.png]]<br />
<br />
Line strips are like line loops, only without the last link added.<br />
<br />
Keyword LineStrip<br />
<br />
===Quadrangles===<br />
[[image:OG-Quad.png]]<br />
<br />
For the Quads keyword, each four coordinates given define a quadrangle.<br />
<br />
Keyword Quads<br />
<br />
===Quadrangle strips===<br />
[[image:OG-Quadstrip.png]]<br />
<br />
And a Quadstrip works as the trianglestrip, only the window is 4 coordinates wide and steps 2 steps each time, so each new pair of coordinates attaches a new quadrangle to the last edge of the last quadrangle.<br />
<br />
Keyword QuadStrip<br />
<br />
===Polygon===<br />
[[image:OG-Polygon.png]]<br />
<br />
A Polygon is a filled line loop. Simple as that!<br />
<br />
Keyword Polygon<br />
<br />
There are more things we can do on our canvas than just spreading out coordinates. Within the command list constructed after a renderPrimitive, we can give several different commands that control what things are supposed to look like, so for instance we could use the following:<br />
<haskell><br />
display = do <br />
clear [ColorBuffer]<br />
renderPrimitive Quads $ do<br />
color $ (Color3 (1.0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0.2 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) 0.2 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) 0 0)<br />
color $ (Color3 (0::GLfloat) 1 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) 0 0)<br />
color $ (Color3 (0::GLfloat) 0 1)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 ((-0.2)::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 ((-0.2)::GLfloat) 0 0)<br />
color $ (Color3 (1::GLfloat) 0 1)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0.2 0)<br />
vertex $ (Vertex3 ((-0.2::GLfloat)) 0.2 0)<br />
vertex $ (Vertex3 ((-0.2::GLfloat)) 0 0)<br />
flush<br />
</haskell><br />
in order to produce these four coloured squares:<br />
<br />
[[image:OG-Colorsquares.png]]<br />
<br />
where each color command sets the color for the next item drawn, and the vertex commands give vertices for the four squares.<br />
<br />
==Callbacks - how we react to changes==<br />
We have already seen one callback in action: displayCallBack. The Callbacks are state variables of the HOpenGL system, and are called in order to handle various things that may happen to the place the drawing canvas lives. For a first exercise, go resize the latest window you've used. Go on, do it now.<br />
<br />
I bet it looked ugly, didn't it?<br />
<br />
This is because we have no code handling what to do if the window should suddenly change. Handling this is done in a callback, residing in the IORef reshapeCallback. Similarily, repainting is done in displayCallback, keyboard and mouse input is in keyboardMouseCallback, and so on. We can refer to the HOpenGL documentation for [http://hackage.haskell.org/packages/archive/GLUT/latest/doc/html/Graphics-UI-GLUT-Callbacks-Window.html window callbacks] and for [http://hackage.haskell.org/packages/archive/GLUT/latest/doc/html/Graphics-UI-GLUT-Callbacks-Global.html global callbacks]. Window callbacks are things like display, keyboard and mouse, and reshape. Global callbacks deal with timing issues (for those snazzy animations) and the menu interface systems.<br />
<br />
In order for a callback to possibly not be defined, most are typed within the Maybe monad, so by setting the state variable to Nothing, a callback can be disabled. Thus, setting callbacks is done using the keyword Just. We'll add a callback for reshaping the window to our neat code, changing the main function to:<br />
<haskell><br />
main = do <br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= display<br />
reshapeCallback $= Just reshape<br />
mainLoop<br />
reshape s@(Size w h) = do<br />
viewport $= (Position 0 0, s)<br />
postRedisplay Nothing<br />
</haskell><br />
<br />
Here, the code for the reshape function resizes the viewport so that our drawing area contains the entire new window. After setting the new viewport, it also tells the windowing system that something has happened to the window, and that therefore, the display function should be called.<br />
<br />
==Summary==<br />
So, in conclusion, so far we can display a window, post basic callbacks to get the windowhandling to run smoothly, and draw in our window. Next installment of the tutorial will bring you 3d drawing, keyboard and mouse interactions, the incredible power of matrices and the ability to rotate 3d objects for your leisure. Possibly, we'll even look into animations.<br />
<br />
[[OpenGLTutorial2|Continue with part 2]]</div>Jameshfisherhttps://wiki.haskell.org/index.php?title=OpenGLTutorial1&diff=44577OpenGLTutorial12012-02-19T23:45:43Z<p>Jameshfisher: /* Hello World */ typo</p>
<hr />
<div>''This tutorial [http://blog.mikael.johanssons.org/archive/2006/09/opengl-programming-in-haskell-a-tutorial-part-1/] was originally written by Mikael Vejdemo Johansson, and was copied here with permission.''<br />
<br />
After having failed following the [http://www.cs.hs-rm.de/~panitz/hopengl/skript.html googled tutorial in HOpenGL programming], I thought I'd write down the steps I actually can get to work in a tutorial-like fashion. It may be a good idea to read this in parallell to the tutorial linked, since Panitz actually brings a lot of good explanations, even though his syntax isn't up to speed with the latest HOpenGL at all points.<br />
<br />
Note: GHCI interactive shell has problems running these program on some platforms (such as Mac OS X). <strong>Vompile these programs with ghc, and run the generated executables.<br />
</strong><br />
<br />
==Hello World==<br />
First of all, we'll want to load the OpenGL libraries, throw up a window, and generally get to grips with what needs to be done to get a program running at all. <br />
<br />
<haskell><br />
import Graphics.Rendering.OpenGL<br />
import Graphics.UI.GLUT<br />
<br />
main :: IO ()<br />
main = do <br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= flush<br />
mainLoop<br />
</haskell><br />
<br />
This code throws up a window, with a given title, and sets the main display function to do nothing but flush the (empty) graphics buffer. This is the skeleton that we'll be building on to.<br />
<br />
Save it to HelloWorld.hs and compile it by running <hask>ghc -package GLUT HelloWorld.hs -o HelloWorld</hask>.<br />
<br />
You will see a window open, with the title "Hello World", with either a blank canvas, or with some garbage graphics content pulled from somewhere in your system's graphics memory.<br />
<br />
In either case, this program is profoundly worthless.<br />
<br />
At a minimum, let's have our program display a clean blank canvas:<br />
<br />
So we modify our code to the following:<br />
<br />
<haskell><br />
import Graphics.Rendering.OpenGL<br />
import Graphics.UI.GLUT<br />
<br />
main :: IO ()<br />
main = do<br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= display<br />
mainLoop<br />
<br />
display :: IO ()<br />
display = do<br />
clear [ ColorBuffer ]; flush<br />
<br />
</haskell><br />
<br />
This defines a function "display" that calls a few OpenGL functions: "clear" to clear out the graphics color state (so we get a blank canvas), and "flush" to push our OpenGL commands down to the system graphics for actual display.<br />
<br />
We don't call "display" directly. (In fact, we don't call any graphics drawing functions directly). Instead, we set a display callback, and then call mainLoop. In mainLoop, OpenGL akes over, handles all the details of interacting with the OS and refreshing our window, calling our displayCallback to draw graphics.<br />
<br />
displayCallback is a Data.IORef (mutable state variable), which we set using a call to <hask>($=)</hask>.<br />
<br />
Save this to the HelloWorld.hs, recompile, and rerun. This program displays an endless series of blank canvases (a solid blank image).<br />
<br />
The displayCallback is a globally defined IORef, which can be accessed through a host of functions defined in Data.IORef. In [http://hackage.haskell.org/packages/archive/OpenGL/2.2.2.0/doc/html/Graphics-Rendering-OpenGL-GL-StateVar.html OpenGL StateVar module], there is a HasSetter type class and an IORef implementation providing functions <hask>($=)</hask> (assignment) and <hask>get</hask> to fascilitate interactions with these state variables. <br />
<br />
<haskell><br />
height = newIORef 1.0<br />
currentheight <- get height<br />
height $= 1.5<br />
</haskell><br />
<br />
==Using the drawing canvas==<br />
So, we have a window, we have a display callback that clears the canvas. Don't we want more out of it? Sure we do. So let's draw some things.<br />
<haskell><br />
import Graphics.Rendering.OpenGL<br />
import Graphics.UI.GLUT<br />
myPoints :: [(GLfloat,GLfloat,GLfloat)]<br />
myPoints = map (\k -> (sin(2*pi*k/12),cos(2*pi*k/12),0.0)) [1..12]<br />
main = do <br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= display<br />
mainLoop<br />
display = do <br />
clear [ColorBuffer]<br />
renderPrimitive Points $ mapM_ (\(x, y, z)->vertex$Vertex3 x y z) myPoints<br />
flush<br />
</haskell><br />
<br />
Now, the important thing to notice in this codeextract is that last line. It starts a rendering definition, gives the type to be rendered, and then a sequence of function calls, each of which adds a vertex to the rendering canvas. The statement is basically equivalent to something along the lines of<br />
<haskell><br />
renderPrimitive Points do<br />
vertex Vertex3 ...<br />
vertex Vertex3 ...<br />
</haskell><br />
for appropriate triples of coordinate values at the appropriate places. This results in the rendition here:<br />
<br />
[[image:OG-Points.png]]<br />
<br />
We can replace Points with other primitives, leading to the rendering of:<br />
<br />
===Triangles===<br />
[[image:OG-Triangles.png]]<br />
<br />
Each three coordinates following each other define a triangle. The last n mod 3 coordinates are ignored.<br />
<br />
Keyword Triangles<br />
<br />
===Triangle strips===<br />
[[image:OG-Trianglestrip.png]]<br />
<br />
Triangles are drawn according to a “moving window” of size three, so the two last coordinates in the previous triangle become the two first in the next triangle.<br />
<br />
Keyword TriangleStrip<br />
<br />
===Triangle fans===<br />
[[image:OG-Trianglesfan.png]]<br />
<br />
Triangle fans have the first given coordinate as a basepoint, and takes each pair of subsequent coordinates to define a triangle together with the first coordinate.<br />
<br />
Keyword TriangleFan<br />
<br />
===Lines===<br />
[[image:OG-Lines.png]]<br />
<br />
Each pair of coordinates define a line.<br />
<br />
Keyword Lines<br />
<br />
===Line loops===<br />
[[image:OG-Lineloop.png]]<br />
<br />
With line loops, each further coordinate defines a line together with the last coordinate used. Once all coordinates are used up, an additional line is drawn back to the beginning.<br />
<br />
Keyword LineLoop<br />
<br />
===Line strips===<br />
[[image:OG-Linestrip.png]]<br />
<br />
Line strips are like line loops, only without the last link added.<br />
<br />
Keyword LineStrip<br />
<br />
===Quadrangles===<br />
[[image:OG-Quad.png]]<br />
<br />
For the Quads keyword, each four coordinates given define a quadrangle.<br />
<br />
Keyword Quads<br />
<br />
===Quadrangle strips===<br />
[[image:OG-Quadstrip.png]]<br />
<br />
And a Quadstrip works as the trianglestrip, only the window is 4 coordinates wide and steps 2 steps each time, so each new pair of coordinates attaches a new quadrangle to the last edge of the last quadrangle.<br />
<br />
Keyword QuadStrip<br />
<br />
===Polygon===<br />
[[image:OG-Polygon.png]]<br />
<br />
A Polygon is a filled line loop. Simple as that!<br />
<br />
Keyword Polygon<br />
<br />
There are more things we can do on our canvas than just spreading out coordinates. Within the command list constructed after a renderPrimitive, we can give several different commands that control what things are supposed to look like, so for instance we could use the following:<br />
<haskell><br />
display = do <br />
clear [ColorBuffer]<br />
renderPrimitive Quads $ do<br />
color $ (Color3 (1.0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0.2 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) 0.2 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) 0 0)<br />
color $ (Color3 (0::GLfloat) 1 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) 0 0)<br />
color $ (Color3 (0::GLfloat) 0 1)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 ((-0.2)::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 ((-0.2)::GLfloat) 0 0)<br />
color $ (Color3 (1::GLfloat) 0 1)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0.2 0)<br />
vertex $ (Vertex3 ((-0.2::GLfloat)) 0.2 0)<br />
vertex $ (Vertex3 ((-0.2::GLfloat)) 0 0)<br />
flush<br />
</haskell><br />
in order to produce these four coloured squares:<br />
<br />
[[image:OG-Colorsquares.png]]<br />
<br />
where each color command sets the color for the next item drawn, and the vertex commands give vertices for the four squares.<br />
<br />
==Callbacks - how we react to changes==<br />
We have already seen one callback in action: displayCallBack. The Callbacks are state variables of the HOpenGL system, and are called in order to handle various things that may happen to the place the drawing canvas lives. For a first exercise, go resize the latest window you've used. Go on, do it now.<br />
<br />
I bet it looked ugly, didn't it?<br />
<br />
This is because we have no code handling what to do if the window should suddenly change. Handling this is done in a callback, residing in the IORef reshapeCallback. Similarily, repainting is done in displayCallback, keyboard and mouse input is in keyboardMouseCallback, and so on. We can refer to the HOpenGL documentation for [http://hackage.haskell.org/packages/archive/GLUT/latest/doc/html/Graphics-UI-GLUT-Callbacks-Window.html window callbacks] and for [http://hackage.haskell.org/packages/archive/GLUT/latest/doc/html/Graphics-UI-GLUT-Callbacks-Global.html global callbacks]. Window callbacks are things like display, keyboard and mouse, and reshape. Global callbacks deal with timing issues (for those snazzy animations) and the menu interface systems.<br />
<br />
In order for a callback to possibly not be defined, most are typed within the Maybe monad, so by setting the state variable to Nothing, a callback can be disabled. Thus, setting callbacks is done using the keyword Just. We'll add a callback for reshaping the window to our neat code, changing the main function to:<br />
<haskell><br />
main = do <br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= display<br />
reshapeCallback $= Just reshape<br />
mainLoop<br />
reshape s@(Size w h) = do<br />
viewport $= (Position 0 0, s)<br />
postRedisplay Nothing<br />
</haskell><br />
<br />
Here, the code for the reshape function resizes the viewport so that our drawing area contains the entire new window. After setting the new viewport, it also tells the windowing system that something has happened to the window, and that therefore, the display function should be called.<br />
<br />
==Summary==<br />
So, in conclusion, so far we can display a window, post basic callbacks to get the windowhandling to run smoothly, and draw in our window. Next installment of the tutorial will bring you 3d drawing, keyboard and mouse interactions, the incredible power of matrices and the ability to rotate 3d objects for your leisure. Possibly, we'll even look into animations.<br />
<br />
[[OpenGLTutorial2|Continue with part 2]]</div>Jameshfisherhttps://wiki.haskell.org/index.php?title=OpenGLTutorial1&diff=44576OpenGLTutorial12012-02-19T23:45:14Z<p>Jameshfisher: /* Hello World */ typo</p>
<hr />
<div>''This tutorial [http://blog.mikael.johanssons.org/archive/2006/09/opengl-programming-in-haskell-a-tutorial-part-1/] was originally written by Mikael Vejdemo Johansson, and was copied here with permission.''<br />
<br />
After having failed following the [http://www.cs.hs-rm.de/~panitz/hopengl/skript.html googled tutorial in HOpenGL programming], I thought I'd write down the steps I actually can get to work in a tutorial-like fashion. It may be a good idea to read this in parallell to the tutorial linked, since Panitz actually brings a lot of good explanations, even though his syntax isn't up to speed with the latest HOpenGL at all points.<br />
<br />
Note: GHCI interactive shell has problems running these program on some platforms (such as Mac OS X). <strong>Vompile these programs with ghc, and run the generated executables.<br />
</strong><br />
<br />
==Hello World==<br />
First of all, we'll want to load the OpenGL libraries, throw up a window, and generally get to grips with what needs to be done to get a program running at all. <br />
<br />
<haskell><br />
import Graphics.Rendering.OpenGL<br />
import Graphics.UI.GLUT<br />
<br />
main :: IO ()<br />
main = do <br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= flush<br />
mainLoop<br />
</haskell><br />
<br />
This code throws up a window, with a given title, and sets the main display function to do nothing but flush the (empty) graphics buffer. This is the skeleton that we'll be building on to.<br />
<br />
Save it to HelloWorld.hs and compile it by running <hask>ghc -package GLUT HelloWorld.hs -o HelloWorld</hask>.<br />
<br />
You will see a window open, with titled "Hello World", with either a blank canvas, or with some garbage graphics content pulled from somewhere in your system's graphics memory.<br />
<br />
In either case, this program is profoundly worthless.<br />
<br />
At a minimum, let's have our program display a clean blank canvas:<br />
<br />
So we modify our code to the following:<br />
<br />
<haskell><br />
import Graphics.Rendering.OpenGL<br />
import Graphics.UI.GLUT<br />
<br />
main :: IO ()<br />
main = do<br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= display<br />
mainLoop<br />
<br />
display :: IO ()<br />
display = do<br />
clear [ ColorBuffer ]; flush<br />
<br />
</haskell><br />
<br />
This defines a function "display" that calls a few OpenGL functions: "clear" to clear out the graphics color state (so we get a blank canvas), and "flush" to push our OpenGL commands down to the system graphics for actual display.<br />
<br />
We don't call "display" directly. (In fact, we don't call any graphics drawing functions directly). Instead, we set a display callback, and then call mainLoop. In mainLoop, OpenGL akes over, handles all the details of interacting with the OS and refreshing our window, calling our displayCallback to draw graphics.<br />
<br />
displayCallback is a Data.IORef (mutable state variable), which we set using a call to <hask>($=)</hask>.<br />
<br />
Save this to the HelloWorld.hs, recompile, and rerun. This program displays an endless series of blank canvases (a solid blank image).<br />
<br />
The displayCallback is a globally defined IORef, which can be accessed through a host of functions defined in Data.IORef. In [http://hackage.haskell.org/packages/archive/OpenGL/2.2.2.0/doc/html/Graphics-Rendering-OpenGL-GL-StateVar.html OpenGL StateVar module], there is a HasSetter type class and an IORef implementation providing functions <hask>($=)</hask> (assignment) and <hask>get</hask> to fascilitate interactions with these state variables. <br />
<br />
<haskell><br />
height = newIORef 1.0<br />
currentheight <- get height<br />
height $= 1.5<br />
</haskell><br />
<br />
==Using the drawing canvas==<br />
So, we have a window, we have a display callback that clears the canvas. Don't we want more out of it? Sure we do. So let's draw some things.<br />
<haskell><br />
import Graphics.Rendering.OpenGL<br />
import Graphics.UI.GLUT<br />
myPoints :: [(GLfloat,GLfloat,GLfloat)]<br />
myPoints = map (\k -> (sin(2*pi*k/12),cos(2*pi*k/12),0.0)) [1..12]<br />
main = do <br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= display<br />
mainLoop<br />
display = do <br />
clear [ColorBuffer]<br />
renderPrimitive Points $ mapM_ (\(x, y, z)->vertex$Vertex3 x y z) myPoints<br />
flush<br />
</haskell><br />
<br />
Now, the important thing to notice in this codeextract is that last line. It starts a rendering definition, gives the type to be rendered, and then a sequence of function calls, each of which adds a vertex to the rendering canvas. The statement is basically equivalent to something along the lines of<br />
<haskell><br />
renderPrimitive Points do<br />
vertex Vertex3 ...<br />
vertex Vertex3 ...<br />
</haskell><br />
for appropriate triples of coordinate values at the appropriate places. This results in the rendition here:<br />
<br />
[[image:OG-Points.png]]<br />
<br />
We can replace Points with other primitives, leading to the rendering of:<br />
<br />
===Triangles===<br />
[[image:OG-Triangles.png]]<br />
<br />
Each three coordinates following each other define a triangle. The last n mod 3 coordinates are ignored.<br />
<br />
Keyword Triangles<br />
<br />
===Triangle strips===<br />
[[image:OG-Trianglestrip.png]]<br />
<br />
Triangles are drawn according to a “moving window” of size three, so the two last coordinates in the previous triangle become the two first in the next triangle.<br />
<br />
Keyword TriangleStrip<br />
<br />
===Triangle fans===<br />
[[image:OG-Trianglesfan.png]]<br />
<br />
Triangle fans have the first given coordinate as a basepoint, and takes each pair of subsequent coordinates to define a triangle together with the first coordinate.<br />
<br />
Keyword TriangleFan<br />
<br />
===Lines===<br />
[[image:OG-Lines.png]]<br />
<br />
Each pair of coordinates define a line.<br />
<br />
Keyword Lines<br />
<br />
===Line loops===<br />
[[image:OG-Lineloop.png]]<br />
<br />
With line loops, each further coordinate defines a line together with the last coordinate used. Once all coordinates are used up, an additional line is drawn back to the beginning.<br />
<br />
Keyword LineLoop<br />
<br />
===Line strips===<br />
[[image:OG-Linestrip.png]]<br />
<br />
Line strips are like line loops, only without the last link added.<br />
<br />
Keyword LineStrip<br />
<br />
===Quadrangles===<br />
[[image:OG-Quad.png]]<br />
<br />
For the Quads keyword, each four coordinates given define a quadrangle.<br />
<br />
Keyword Quads<br />
<br />
===Quadrangle strips===<br />
[[image:OG-Quadstrip.png]]<br />
<br />
And a Quadstrip works as the trianglestrip, only the window is 4 coordinates wide and steps 2 steps each time, so each new pair of coordinates attaches a new quadrangle to the last edge of the last quadrangle.<br />
<br />
Keyword QuadStrip<br />
<br />
===Polygon===<br />
[[image:OG-Polygon.png]]<br />
<br />
A Polygon is a filled line loop. Simple as that!<br />
<br />
Keyword Polygon<br />
<br />
There are more things we can do on our canvas than just spreading out coordinates. Within the command list constructed after a renderPrimitive, we can give several different commands that control what things are supposed to look like, so for instance we could use the following:<br />
<haskell><br />
display = do <br />
clear [ColorBuffer]<br />
renderPrimitive Quads $ do<br />
color $ (Color3 (1.0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0.2 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) 0.2 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) 0 0)<br />
color $ (Color3 (0::GLfloat) 1 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 (0.2::GLfloat) 0 0)<br />
color $ (Color3 (0::GLfloat) 0 1)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 ((-0.2)::GLfloat) (-0.2) 0)<br />
vertex $ (Vertex3 ((-0.2)::GLfloat) 0 0)<br />
color $ (Color3 (1::GLfloat) 0 1)<br />
vertex $ (Vertex3 (0::GLfloat) 0 0)<br />
vertex $ (Vertex3 (0::GLfloat) 0.2 0)<br />
vertex $ (Vertex3 ((-0.2::GLfloat)) 0.2 0)<br />
vertex $ (Vertex3 ((-0.2::GLfloat)) 0 0)<br />
flush<br />
</haskell><br />
in order to produce these four coloured squares:<br />
<br />
[[image:OG-Colorsquares.png]]<br />
<br />
where each color command sets the color for the next item drawn, and the vertex commands give vertices for the four squares.<br />
<br />
==Callbacks - how we react to changes==<br />
We have already seen one callback in action: displayCallBack. The Callbacks are state variables of the HOpenGL system, and are called in order to handle various things that may happen to the place the drawing canvas lives. For a first exercise, go resize the latest window you've used. Go on, do it now.<br />
<br />
I bet it looked ugly, didn't it?<br />
<br />
This is because we have no code handling what to do if the window should suddenly change. Handling this is done in a callback, residing in the IORef reshapeCallback. Similarily, repainting is done in displayCallback, keyboard and mouse input is in keyboardMouseCallback, and so on. We can refer to the HOpenGL documentation for [http://hackage.haskell.org/packages/archive/GLUT/latest/doc/html/Graphics-UI-GLUT-Callbacks-Window.html window callbacks] and for [http://hackage.haskell.org/packages/archive/GLUT/latest/doc/html/Graphics-UI-GLUT-Callbacks-Global.html global callbacks]. Window callbacks are things like display, keyboard and mouse, and reshape. Global callbacks deal with timing issues (for those snazzy animations) and the menu interface systems.<br />
<br />
In order for a callback to possibly not be defined, most are typed within the Maybe monad, so by setting the state variable to Nothing, a callback can be disabled. Thus, setting callbacks is done using the keyword Just. We'll add a callback for reshaping the window to our neat code, changing the main function to:<br />
<haskell><br />
main = do <br />
(progname, _) <- getArgsAndInitialize<br />
createWindow "Hello World"<br />
displayCallback $= display<br />
reshapeCallback $= Just reshape<br />
mainLoop<br />
reshape s@(Size w h) = do<br />
viewport $= (Position 0 0, s)<br />
postRedisplay Nothing<br />
</haskell><br />
<br />
Here, the code for the reshape function resizes the viewport so that our drawing area contains the entire new window. After setting the new viewport, it also tells the windowing system that something has happened to the window, and that therefore, the display function should be called.<br />
<br />
==Summary==<br />
So, in conclusion, so far we can display a window, post basic callbacks to get the windowhandling to run smoothly, and draw in our window. Next installment of the tutorial will bring you 3d drawing, keyboard and mouse interactions, the incredible power of matrices and the ability to rotate 3d objects for your leisure. Possibly, we'll even look into animations.<br />
<br />
[[OpenGLTutorial2|Continue with part 2]]</div>Jameshfisherhttps://wiki.haskell.org/index.php?title=How_to_write_a_Haskell_program&diff=44552How to write a Haskell program2012-02-17T12:17:08Z<p>Jameshfisher: /* Stick it in darcs */ darcs -> version control</p>
<hr />
<div>A developers' guide to creating a new Haskell project or program, and working in the Haskell developer ecosystem.<br />
<br />
''Note: for learning the Haskell language itself we recommend [http://haskell.org/haskellwiki/Tutorials#Introductions_to_Haskell these resources].''<br />
<br />
== Recommended tools ==<br />
<br />
Almost all new Haskell projects use the following tools. Each is<br />
intrinsically useful, but using a set of common tools also helps<br />
everyone by increasing productivity, and you're more likely to get<br />
patches.<br />
<br />
=== Revision control ===<br />
<br />
Use [http://git-scm.com/ git] or [http://darcs.net darcs] unless you have a specific reason not to. Both are lightweight distributed revision control systems (and darcs is written in Haskell). Both have massive market share in the Haskell world, if you want to encourage contributions from other Haskell hackers git or darcs are the best. Darcs hosting is available on [http://code.haskell.org code.haskell.org] and [http://patch-tag.com patch-tag]. [http://github.com/ github] for git is very popular.<br />
<br />
=== Build system ===<br />
<br />
[[Image:Cabal-With-Text-small.png|frame|Built with Cabal]]<br />
<br />
Use [http://haskell.org/cabal/ Cabal].<br />
You should read at least the start of section 2 of the [http://www.haskell.org/cabal/users-guide/ Cabal User's Guide].<br />
<br />
You should use [http://haskell.org/cabal/download.html cabal-install] as a front-end for installing your Cabal library. Cabal-install provides commands not only for building libraries but also for installing them from, and uploading them to, Hackage. As a bonus, for almost all programs, it's faster than using Setup.hs scripts directly, since no time is wasted compiling the scripts. (This does not apply for programs that use custom Setup.hs scripts, since those need to be compiled even when using cabal-install.)<br />
<br />
cabal-install is widely available, as part of the [http://haskell.org/platform Haskell Platform], so you can probably assume your users will have it too.<br />
<br />
=== Documentation ===<br />
<br />
For libraries, use [http://haskell.org/haddock/ Haddock]. We recommend<br />
using the version of Haddock that ships with the Haskell Platform. Haddock generates [http://hackage.haskell.org/packages/archive/base/4.3.1.0/doc/html/Prelude.html nice markup], with links to source.<br />
<br />
=== Testing ===<br />
<br />
You can use [http://hackage.haskell.org/package/QuickCheck QuickCheck] or [http://www.mail-archive.com/haskell@haskell.org/msg19215.html SmallCheck] to test pure code. To test impure code, use [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/HUnit HUnit]. See [http://hackage.haskell.org/packages/archive/hashable/1.1.2.2/hashable.cabal this Cabal file] for an example of how to include tests in your Cabal package.<br />
<br />
To get started, try [[Introduction to QuickCheck]]. For a slightly more advanced introduction, [http://blog.codersbase.com/2006/09/simple-unit-testing-in-haskell.html Simple Unit Testing in Haskell] is a blog article about creating a testing framework for QuickCheck using some Template Haskell. For HUnit, see [[HUnit 1.0 User's Guide]]<br />
<br />
=== Distribution ===<br />
<br />
The standard mechanism for distributing Haskell libraries and<br />
applications is [http://hackage.haskell.org/packages/hackage.html Hackage]. Hackage can<br />
host your cabalised tarball releases, and link to any library<br />
dependencies your code has. Users will find and install your packages via "cabal install", and your package will be integrated into Haskell search engines, like [http://www.haskell.org/hoogle/ hoogle]<br />
<br />
=== Target Environment ===<br />
<br />
If at all possible, depend on libraries that are provided by the [http://haskell.org/platform Haskell Platform], and libraries that in turn build against the Haskell Platform. This set of libraries is designed to be widely available, so your end users will be able to build your software.<br />
<br />
== Structure of a simple project ==<br />
<br />
The basic structure of a new Haskell project can be adopted from<br />
[http://semantic.org/hnop/ HNop], the minimal Haskell project. It<br />
consists of the following files, for the mythical project "haq".<br />
<br />
* Haq.hs -- the main haskell source file<br />
* haq.cabal -- the cabal build description<br />
* Setup.hs -- build script itself<br />
* _darcs -- revision control<br />
* README -- info<br />
* LICENSE -- license<br />
<br />
Of course, you can elaborate on this, with subdirectories and multiple<br />
modules. See [[Structure of a Haskell project]] for an example of a larger project's directory structure.<br />
<br />
Here is a transcript that shows how you'd create a minimal darcs and cabalised<br />
Haskell project for the cool new Haskell program "haq", build it,<br />
install it and release.<br />
<br />
''Note'': The new tool "cabal init" automates all this for you, but you should<br />
understand all the parts even so. <br />
<br />
We will now walk through the creation of the infrastructure for a simple<br />
Haskell executable. Advice for libraries follows after.<br />
<br />
=== Create a directory ===<br />
<br />
Create somewhere for the source:<br />
<br />
<code><br />
$ mkdir haq<br />
$ cd haq<br />
</code><br />
<br />
=== Write some Haskell source ===<br />
<br />
Write your program:<br />
<br />
<haskell><br />
$ cat > Haq.hs<br />
--<br />
-- Copyright (c) 2006 Don Stewart - http://www.cse.unsw.edu.au/~dons/<br />
-- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html)<br />
--<br />
import System.Environment<br />
<br />
-- | 'main' runs the main program<br />
main :: IO ()<br />
main = getArgs >>= print . haqify . head<br />
<br />
haqify s = "Haq! " ++ s<br />
</haskell><br />
<br />
=== Stick it in version control ===<br />
<br />
Place the source under revision control (you may need to enter your e-mail address first, to identify you as maintainer of this source):<br />
<br />
<code><br />
$ darcs init<br />
$ darcs add Haq.hs <br />
$ darcs record<br />
addfile ./Haq.hs<br />
Shall I record this change? (1/?) [ynWsfqadjkc], or ? for help: y<br />
hunk ./Haq.hs 1<br />
+--<br />
+-- Copyright (c) 2006 Don Stewart - http://www.cse.unsw.edu.au/~dons/<br />
+-- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html)<br />
+--<br />
+import System.Environment<br />
+<br />
+-- | 'main' runs the main program<br />
+main :: IO ()<br />
+main = getArgs >>= print . haqify . head<br />
+<br />
+haqify s = "Haq! " ++ s<br />
Shall I record this change? (2/?) [ynWsfqadjkc], or ? for help: y<br />
What is the patch name? Import haq source<br />
Do you want to add a long comment? [yn]n<br />
Finished recording patch 'Import haq source'<br />
</code><br />
<br />
And we can see that darcs is now running the show:<br />
<br />
<code><br />
$ ls<br />
Haq.hs _darcs<br />
</code><br />
<br />
=== Add a build system ===<br />
<br />
Create a .cabal file describing how to build your project:<br />
<br />
<code><br />
$ cat > haq.cabal<br />
Name: haq<br />
Version: 0.0<br />
Description: Super cool mega lambdas<br />
License: GPL<br />
License-file: LICENSE<br />
Author: Don Stewart<br />
Maintainer: dons@cse.unsw.edu.au<br />
Build-Type: Simple<br />
Cabal-Version: >=1.2<br />
<br />
Executable haq<br />
Main-is: Haq.hs<br />
Build-Depends: base >= 3 && < 5<br />
</code><br />
<br />
(If your package uses other packages, e.g. <tt>haskell98</tt>, you'll need to add them to the <tt>Build-Depends:</tt> field as a comma separated list.)<br />
Add a <tt>Setup.hs</tt> that will actually do the building:<br />
<br />
<haskell><br />
$ cat > Setup.hs<br />
import Distribution.Simple<br />
main = defaultMain<br />
</haskell><br />
Cabal allows either <tt>Setup.hs</tt> or <tt>Setup.lhs</tt>.<br />
<br />
Now would also be a good time to add a LICENSE file and a README file. Examples are in the tarball for HNop.<br />
<br />
Record your changes:<br />
<br />
<code><br />
$ darcs add haq.cabal Setup.hs LICENSE README<br />
$ darcs record --all<br />
What is the patch name? Add a build system<br />
Do you want to add a long comment? [yn]n<br />
Finished recording patch 'Add a build system'<br />
</code><br />
<br />
=== Build your project ===<br />
<br />
Now build it! There are two methods of accessing Cabal functionality: through your Setup.hs script or through cabal-install. In most cases, cabal-install is now the preferred method.<br />
<br />
Building using cabal-install:<br />
<br />
<code><br />
$ cabal install --prefix=$HOME --user<br />
</code><br />
<br />
Building using the traditional Setup.hs method:<br />
<br />
<code><br />
$ runhaskell Setup configure --prefix=$HOME --user<br />
$ runhaskell Setup build<br />
$ runhaskell Setup install<br />
</code><br />
<br />
This will install your newly minted haq program in $HOME/bin.<br />
<br />
=== Run it ===<br />
<br />
And now you can run your cool project:<br />
<code><br />
$ haq me<br />
"Haq! me"<br />
</code><br />
<br />
You can also run it in-place, even if you skip the install phase:<br />
<code><br />
$ dist/build/haq/haq you<br />
"Haq! you"<br />
</code><br />
<br />
=== Build some haddock documentation ===<br />
<br />
Generate some API documentation into dist/doc/*<br />
<br />
Using cabal install:<br />
<code><br />
$ cabal haddock<br />
</code><br />
<br />
Traditional method:<br />
<code><br />
$ runhaskell Setup haddock<br />
</code><br />
<br />
which generates files in dist/doc/ including:<br />
<br />
<code><br />
$ w3m -dump dist/doc/html/haq/Main.html<br />
haq Contents Index<br />
Main<br />
<br />
Synopsis<br />
main :: IO ()<br />
<br />
Documentation<br />
<br />
main :: IO ()<br />
main runs the main program<br />
<br />
Produced by Haddock version 0.7<br />
</code><br />
<br />
No output? Make sure you have actually installed haddock. It is a separate program, not something that comes with Cabal. Note that the stylized comment in the source gets picked up by Haddock.<br />
<br />
=== (Optional) Improve your code: HLint ===<br />
<br />
[http://hackage.haskell.org/package/hlint HLint] can be a valuable tool for improving your coding style, particularly if you're new to Haskell. Let's run it now.<br />
<br />
<code><br />
$ hlint .<br />
./Haq.hs:11:1: Warning: Eta reduce<br />
Found:<br />
haqify s = "Haq! " ++ s<br />
Why not:<br />
haqify = ("Haq! " ++)<br />
</code><br />
<br />
The existing code will work, but let's follow that suggestion. Open Haq.hs in your favourite editor and change the line:<br />
<br />
<haskell><br />
where haqify s = "Haq! " ++ s<br />
</haskell><br />
<br />
to:<br />
<br />
<haskell><br />
where haqify = ("Haq! " ++)<br />
</haskell><br />
<br />
=== Add some automated testing: QuickCheck ===<br />
<br />
==== QuickCheck v1 ====<br />
<br />
We'll use QuickCheck to specify a simple property of our Haq.hs code. Create a tests module, Tests.hs, with some QuickCheck boilerplate:<br />
<br />
<haskell><br />
$ cat > Tests.hs<br />
import Char<br />
import List<br />
import Test.QuickCheck<br />
import Text.Printf<br />
<br />
main = mapM_ (\(s,a) -> printf "%-25s: " s >> a) tests<br />
<br />
instance Arbitrary Char where<br />
arbitrary = choose ('\0', '\128')<br />
coarbitrary c = variant (ord c `rem` 4)<br />
</haskell><br />
<br />
Now let's write a simple property:<br />
<br />
<haskell><br />
$ cat >> Tests.hs <br />
-- reversing twice a finite list, is the same as identity<br />
prop_reversereverse s = (reverse . reverse) s == id s<br />
where _ = s :: [Int]<br />
<br />
-- and add this to the tests list<br />
tests = [("reverse.reverse/id", test prop_reversereverse)]<br />
</haskell><br />
<br />
We can now run this test, and have QuickCheck generate the test data:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : OK, passed 100 tests.<br />
</code><br />
<br />
Let's add a test for the 'haqify' function:<br />
<br />
<haskell><br />
-- Dropping the "Haq! " string is the same as identity<br />
prop_haq s = drop (length "Haq! ") (haqify s) == id s<br />
where haqify s = "Haq! " ++ s<br />
<br />
tests = [("reverse.reverse/id", test prop_reversereverse)<br />
,("drop.haq/id", test prop_haq)]<br />
</haskell><br />
<br />
and let's test that:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : OK, passed 100 tests.<br />
drop.haq/id : OK, passed 100 tests.<br />
</code><br />
<br />
Great!<br />
<br />
==== QuickCheck v2 ====<br />
<br />
If you're using version 2 of QuickCheck, the code in the previous section needs some minor modifications:<br />
<br />
<haskell><br />
$ cat > Tests.hs<br />
import Char<br />
import List<br />
import Test.QuickCheck<br />
import Text.Printf<br />
<br />
main = mapM_ (\(s,a) -> printf "%-25s: " s >> a) tests<br />
<br />
-- reversing twice a finite list, is the same as identity<br />
prop_reversereverse s = (reverse . reverse) s == id s<br />
where _ = s :: [Int]<br />
<br />
-- Dropping the "Haq! " string is the same as identity<br />
prop_haq s = drop (length "Haq! ") (haqify s) == id s<br />
where haqify s = "Haq! " ++ s<br />
<br />
tests = [("reverse.reverse/id", quickCheck prop_reversereverse)<br />
,("drop.haq/id", quickCheck prop_haq)]<br />
</haskell><br />
<br />
To run the test:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : +++ OK, passed 100 tests.<br />
drop.haq/id : +++ OK, passed 100 tests.<br />
</code><br />
<br />
Success!<br />
<br />
=== Running the test suite from darcs ===<br />
<br />
We can arrange for darcs to run the test suite on every commit that is run with the flag --test:<br />
<br />
<code><br />
$ darcs setpref test "runhaskell Tests.hs"<br />
Changing value of test from '' to 'runhaskell Tests.hs'<br />
</code><br />
<br />
will run the full set of QuickChecks.<br />
If your test requires it, you may need to ensure other things are built too -- for example:<code>darcs setpref test "alex Tokens.x;happy Grammar.y;runhaskell Tests.hs"</code>.<br />
You will encounter that this way a darcs patch is also accepted if a QuickCheck test fails.<br />
You have two choices to [http://www.haskell.org/pipermail/haskell-cafe/2007-October/033834.html work around] this:<br />
* Use <hask>quickCheck'</hask> from the package QuickCheck-2 and call <hask>exitWithFailure</hask> if it return <hask>False</hask>.<br />
* Keep the test program as it is, and implement the failure on the shell level:<br />
: <code>runhaskell Tests.hs | tee test.log && if grep Falsifiable test.log >/dev/null; then exit 1; fi</code><br />
<br />
Let's commit a new patch:<br />
<br />
<code><br />
$ darcs add Tests.hs<br />
$ darcs record --all --test<br />
What is the patch name? Add testsuite<br />
Do you want to add a long comment? [yn]n<br />
Running test...<br />
reverse.reverse/id : OK, passed 100 tests.<br />
drop.haq/id : OK, passed 100 tests.<br />
Test ran successfully.<br />
Looks like a good patch.<br />
Finished recording patch 'Add testsuite'<br />
</code><br />
<br />
Excellent: now, patches must pass the test suite before they can be committed provided the --test flag is passed.<br />
<br />
=== Tag the stable version, create a tarball, and sell it! ===<br />
<br />
Tag the stable version:<br />
<br />
<code><br />
$ darcs tag<br />
What is the version name? 0.0<br />
Finished tagging patch 'TAG 0.0'<br />
</code><br />
<br />
==== Create a tarball ====<br />
You can do this using either Cabal or darcs, or even an explicit <tt>tar</tt> command.<br />
<br />
===== Using Cabal =====<br />
<br />
Since the code is cabalised, we can create a tarball with cabal-install<br />
directly (you can also use <tt>runhaskell Setup.hs sdist</tt>, but you need <tt>tar</tt> on your system [http://thread.gmane.org/gmane.comp.lang.haskell.cafe/60617/focus=60653]):<br />
<br />
<code><br />
$ cabal sdist<br />
Building source dist for haq-0.0...<br />
Source tarball created: dist/haq-0.0.tar.gz<br />
</code><br />
This has the advantage that Cabal will do a bit more checking, and<br />
ensure that the tarball has the structure that HackageDB expects. <br />
Note that it does require the LICENSE file to exist.<br />
It packages up the files needed to build the project; to include other files (such as <tt>Test.hs</tt> in the above example, and our README), we need to add:<br />
<br />
<code><br />
extra-source-files: Tests.hs README<br />
</code><br />
<br />
to the .cabal file to have everything included.<br />
<br />
===== Using darcs =====<br />
<br />
Alternatively, you can use darcs:<br />
<code><br />
$ darcs dist -d haq-0.0<br />
Created dist as haq-0.0.tar.gz<br />
</code><br />
<br />
And you're all set up!<br />
<br />
==== Check that your source package is complete ====<br />
<br />
Just to make sure everything works, try building the source package in some temporary directory:<br />
<code><br />
$ tar xzf haq-0.0.tar.gz<br />
$ cd haq-0.0<br />
$ cabal configure<br />
$ cabal build<br />
</code><br />
and for packages containing libraries,<br />
<code><br />
$ cabal haddock<br />
</code><br />
<br />
==== Upload your package to Hackage ====<br />
<br />
Whichever of the above methods you've used to create your package, you can upload it to the Hackage package collection via a [http://hackage.haskell.org/packages/upload.html web interface].<br />
You may wish to use the package checking interface there first, and fix things it warns about, before uploading your package.<br />
<br />
=== Summary ===<br />
<br />
The following files were created:<br />
<br />
$ ls<br />
Haq.hs Tests.hs dist haq.cabal<br />
Setup.hs _darcs haq-0.0.tar.gz<br />
<br />
== Libraries ==<br />
<br />
The process for creating a Haskell library is almost identical. The differences<br />
are as follows, for the hypothetical "ltree" library:<br />
<br />
=== Hierarchical source ===<br />
<br />
The source should live under a directory path that fits into the<br />
existing [[Hierarchical module names|module layout guide]].<br />
So we would create the following directory structure, for the module<br />
Data.LTree:<br />
<br />
$ mkdir Data<br />
$ cat > Data/LTree.hs <br />
module Data.LTree where<br />
<br />
So our Data.LTree module lives in Data/LTree.hs<br />
<br />
=== The Cabal file ===<br />
<br />
Cabal files for libraries list the publically visible modules, and have<br />
no executable section:<br />
<br />
$ cat > ltree.cabal <br />
Name: ltree<br />
Version: 0.1<br />
Description: Lambda tree implementation<br />
License: BSD3<br />
License-file: LICENSE<br />
Author: Don Stewart<br />
Maintainer: dons@cse.unsw.edu.au<br />
Build-Type: Simple<br />
Cabal-Version: >=1.2<br />
<br />
Library<br />
Build-Depends: base >= 3 && < 5<br />
Exposed-modules: Data.LTree<br />
ghc-options: -Wall<br />
<br />
We can thus build our library:<br />
<br />
$ cabal configure --prefix=$HOME --user<br />
$ cabal build <br />
Preprocessing library ltree-0.1...<br />
Building ltree-0.1...<br />
[1 of 1] Compiling Data.LTree ( Data/LTree.hs, dist/build/Data/LTree.o )<br />
/usr/bin/ar: creating dist/build/libHSltree-0.1.a<br />
<br />
and our library has been created as a object archive. Now install it:<br />
<br />
$ cabal install<br />
Installing: /home/dons/lib/ltree-0.1/ghc-6.6 & /home/dons/bin ltree-0.1...<br />
Registering ltree-0.1...<br />
Reading package info from ".installed-pkg-config" ... done.<br />
Saving old package config file... done.<br />
Writing new package config file... done.<br />
<br />
And we're done!<br />
To try it out, first make sure that your working directory is anything but the source directory of your library:<br />
<br />
$ cd ..<br />
<br />
And then use your new library from, for example, ghci:<br />
<br />
$ ghci -package ltree<br />
Prelude> :m + Data.LTree<br />
Prelude Data.LTree> <br />
<br />
The new library is in scope, and ready to go.<br />
<br />
=== More complex build systems ===<br />
<br />
For larger projects, you may want to store source trees in subdirectories. This can be done simply by creating a directory -- for example, "src" -- into which you will put your src tree.<br />
<br />
To have Cabal find this code, you add the following line to your Cabal<br />
file:<br />
<br />
hs-source-dirs: src<br />
<br />
You can also set up Cabal to run configure scripts, among other features. For more information consult the<br />
[http://www.haskell.org/cabal/users-guide/ Cabal user guide].<br />
<br />
== Automation ==<br />
<br />
A tool to automatically populate a new cabal project is available:<br />
<br />
cabal init<br />
<br />
Usage is:<br />
<br />
<code><br />
$ cabal init<br />
Package name [default "haq"]? <br />
Package version [default "0.1"]? <br />
Please choose a license:<br />
1) GPL<br />
2) GPL-2<br />
3) GPL-3<br />
4) LGPL<br />
5) LGPL-2.1<br />
6) LGPL-3<br />
* 7) BSD3<br />
8) BSD4<br />
9) MIT<br />
10) PublicDomain<br />
11) AllRightsReserved<br />
12) OtherLicense<br />
13) Other (specify)<br />
Your choice [default "BSD3"]? <br />
Author name? Henry Laxen<br />
Maintainer email? nadine.and.henry@pobox.com<br />
Project homepage/repo URL? http://somewhere.com/haq/<br />
Project synopsis? A wonderful little module<br />
Project category:<br />
1) Codec<br />
2) Concurrency<br />
3) Control<br />
4) Data<br />
5) Database<br />
6) Development<br />
7) Distribution<br />
8) Game<br />
9) Graphics<br />
10) Language<br />
11) Math<br />
12) Network<br />
13) Sound<br />
14) System<br />
15) Testing<br />
16) Text<br />
17) Web<br />
18) Other (specify)<br />
Your choice? 3<br />
What does the package build:<br />
1) Library<br />
2) Executable<br />
Your choice? 1<br />
Generating LICENSE...<br />
Generating Setup.hs...<br />
Generating haq.cabal...<br />
<br />
You may want to edit the .cabal file and add a Description field.<br />
</code><br />
<br />
== Licenses ==<br />
<br />
Code for the common base library package must be BSD licensed. Otherwise, it<br />
is entirely up to you as the author.<br />
Choose a licence (inspired by [http://www.dina.dk/~abraham/rants/license.html this]).<br />
Check the licences of things you use (both other Haskell packages and C<br />
libraries), since these may impose conditions you must follow.<br />
Use the same licence as related projects, where possible. The Haskell community is<br />
split into 2 camps, roughly: those who release everything under BSD, and<br />
(L)GPLers. Some Haskellers recommend avoiding LGPL, due to cross-module optimisation<br />
issues. Like many licensing questions, this advice is controversial. Several Haskell projects<br />
(wxHaskell, HaXml, etc) use the LGPL with an extra permissive clause which gets round the<br />
cross-module optimisation problem.<br />
<br />
== Releases ==<br />
<br />
It's important to release your code as stable, tagged tarballs. Don't<br />
just [http://awayrepl.blogspot.com/2006/11/we-dont-do-releases.html rely on darcs for distribution].<br />
<br />
* '''darcs dist''' generates tarballs directly from a darcs repository<br />
<br />
For example:<br />
<br />
$ cd fps<br />
$ ls <br />
Data LICENSE README Setup.hs TODO _darcs cbits dist fps.cabal tests<br />
$ darcs dist -d fps-0.8<br />
Created dist as fps-0.8.tar.gz<br />
<br />
You can now just post your fps-0.8.tar.gz<br />
<br />
You can also have darcs do the equivalent of 'daily snapshots' for you by using a post-hook.<br />
<br />
put the following in _darcs/prefs/defaults:<br />
apply posthook darcs dist<br />
apply run-posthook<br />
<br />
Advice:<br />
* Tag each release using '''darcs tag'''. For example:<br />
<br />
$ darcs tag 0.8<br />
Finished tagging patch 'TAG 0.8'<br />
<br />
Then people can <tt>darcs pull --partial -t 0.8</tt>, to get just the tagged version (and not the entire history).<br />
<br />
== Hosting ==<br />
<br />
Hosting for repos is available from the Haskell community server:<br />
<br />
http://community.haskell.org/<br />
<br />
A Darcs repository can be published simply by making it available from a<br />
web page.<br />
<br />
== Web page ==<br />
<br />
Create a web page documenting your project! An easy way to do this is to<br />
add a project specific page to [[Haskell|the Haskell wiki]]<br />
<br />
== The user experience ==<br />
<br />
When developing a new Haskell library, it is important to remember how the user expects to be able to build and use a library.<br />
<br />
=== Introductory information and build guide ===<br />
<br />
A typical library user expects to:<br />
<br />
# Visit [[Haskell|Haskell.org]]<br />
# Find the library/program they are looking for:<br />
## if not found, try mailing list; <br />
## if it is hidden, try improving the documentation on haskell.org;<br />
## if it does not exist, try contributing code and documentation) <br />
# Download<br />
# Build and install<br />
# Enjoy<br />
<br />
Each of these steps can pose potential road blocks, and code authors can<br />
do a lot to help code users avoid such blocks. Steps 1..2 may be easy enough, and many coders and users are mainly concerned with step 5. Steps 3..4 are the ones that often get in the way. In particular, the<br />
following questions should have clear answers:<br />
<br />
* Which is the latest version? <br />
* What state is it in? <br />
* What are its aims? <br />
* Where is the documentation?<br />
* Which is the right version for given OS and Haskell implementation?<br />
* How is it packaged, and what tools are needed to get and unpack it?<br />
* How is it installed, and what tools are needed to install it?<br />
* How do we handle dependencies?<br />
* How do we provide/acquire the knowledge and tool-chains needed?<br />
<br />
The best place to answer these questions is a README file,<br />
distributed with the library or application, and often accompanied with<br />
similar text on a more extensive web page.<br />
<br />
=== Tutorials ===<br />
<br />
Generated haddock documentation is usually not enough to help new<br />
programmers learn how to use a library. You must also provide accompanying examples, and even tutorials about the library.<br />
<br />
Please consider providing example code for your library or application. The code should be type-correct and well-commented.<br />
<br />
== Program structure ==<br />
<br />
Monad transformers are very useful for programming in the large,<br />
encapsulating state, and controlling side effects. To learn more about this approach, try [http://www.grabmueller.de/martin/www/pub/Transformers.en.html Monad Transformers Step by Step].<br />
<br />
== Publicity ==<br />
<br />
The best code in the world is meaningless if nobody knows about it. The<br />
process to follow once you've tagged and released your code is:<br />
<br />
=== Join the community ===<br />
<br />
If you haven't already, join the community. The best way to do this is to [http://haskell.org/haskellwiki/Mailing_lists subscribe] to at least haskell-cafe@ and haskell@ mailing lists. Joining the [[IRC_channel|#haskell IRC channel]] is also an excellent idea.<br />
<br />
=== Announce your project on haskell@ ===<br />
<br />
Most important: announce your project releases to the haskell@haskell.org mailing list. Tag your email subject line with "ANNOUNCE: ...". This ensure it will then make it into the [http://haskell.org/haskellwiki/HWN Haskell Weekly News]. To be doubly sure, you can email the release text to the [[HWN|HWN editor]].<br />
<br />
=== Add your code to the public collections ===<br />
<br />
* Add your library or application to the [[Libraries and tools]] page, under the relevant category, so people can find it.<br />
<br />
* If your release is a Cabal package, add it to the [http://hackage.haskell.org/packages/hackage.html Hackage database] (Haskell's CPAN wanna-be).<br />
<br />
=== Blog about it ===<br />
<br />
Blog about it! Blog about your new code on [http://planet.haskell.org Planet Haskell].<br />
Write about your project in your blog, then email the [http://planet.haskell.org/ Planet Haskell] maintainer (ibid on [[IRC channel|#haskell]]) the RSS feed url for your blog<br />
<br />
== Example ==<br />
<br />
[http://cgi.cse.unsw.edu.au/~dons/blog/2006/12/11#release-a-library-today A complete example] of writing, packaging and releasing a new Haskell library under this process has been documented.<br />
<br />
[[Category:Community]]<br />
[[Category:Tutorials]]</div>Jameshfisherhttps://wiki.haskell.org/index.php?title=Jobs&diff=44414Jobs2012-02-10T20:20:51Z<p>Jameshfisher: possible broken link</p>
<hr />
<div>This page collects advertisements for commercial and academic positions involving Haskell or related technologies. <br />
<br />
If you are seeking Haskell jobs, or wish to recruit, good places to follow are the Haskell and Haskell-cafe mailing lists, the [http://cufp.org/jobs CUFP Job Opportunities list] and the Types mailing list (particularly for research jobs). Contacting those organisations listed on the [[Haskell in industry]] is a good idea. Joining the nascent networking site [http://haskellers.com Haskellers] may also prove beneficial.<br />
<br />
Please also supply the date when you add a new job opening to the list below.<br />
<br />
==Industry positions==<br />
<br />
*[http://www.aetion.com/ Aetion Technologies LLC] (Broken link?)<br />
*[http://www.bluespec.com/about/careers.htm Bluespec, Inc.]<br />
*[http://www.galois.com/company/careers Galois, Inc]<br />
*[http://www.starling-software.com/en/employment/ Starling Software K.K.]<br />
*[http://www.tsurucapital.com/en/ Tsuru Capital LLC] <br />
<br />
===Related positions===<br />
* [http://www.erlang-solutions.com/jobs/ Erlang Solutions]<br />
* [http://www.simcorp.com/Home/Careers/Jobs/Denmark.aspx SimCorp is looking for Ocaml Software Developers]<br />
<br />
==Academic positions==<br />
* [http://cufp.org/jobs/programming-languages-researcher-haskell-expertise] Programming Languages Researcher with Haskell Expertise (added Sep 2010)<br />
<br />
==PhD/MSc Studentships==<br />
<br />
* [http://users.ugent.be/~tschrijv/phdposition2.html PhD studentship at Ghent University] <br />
* PhD studentships in Nottingham (deadline 1st March 2011) [http://www.cs.nott.ac.uk/~gmh/phd-advert.txt]<br />
<br />
==Internships==<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/Internships Internships on Haskell and GHC, at Microsoft Research, Cambridge]<br />
* [http://www.haskellers.com/jobs/5/ Spring Internship at Intel to develop EDSL for parallel vector computation] (added Nov 2010)<br />
<br />
<br />
==Job sites==<br />
<br />
* [http://www.haskellers.com/jobs/ Haskellers]<br />
* [http://cufp.org/jobs/language/31 Commercial Users of Functional Programming]<br />
* [http://functionaljobs.com/ Functional Jobs]<br />
<br />
[[Category:Community]]</div>Jameshfisherhttps://wiki.haskell.org/index.php?title=Haskell_in_industry&diff=44412Haskell in industry2012-02-10T17:43:12Z<p>Jameshfisher: added Haskellers.com jobs page link</p>
<hr />
<div>__NOTOC__<br />
<br />
Haskell has a diverse range of use commercially, from aerospace and defense, to finance, to web startups, hardware design firms and a lawnmower manufacturer. This page collects resources on the industrial use of Haskell.<br />
<br />
[http://industry.haskell.org/ http://industry.haskell.org/ihg-logo.png]<br />
<br />
In February 2009 the [http://industry.haskell.org/ Industrial Haskell Group] was launched to support the needs of commercial users of the Haskell programming language. Phase 2 of the effort, expanding membership to research groups and startups with smaller budgets, was [http://www.haskell.org/pipermail/haskell/2009-November/021734.html launched in November 2009]<br />
<br />
The main user conference for industrial Haskell use is CUFP - the [http://cufp.org/ Commercial Users of Functional Programming Workshop]. The annual conference is coming up in October 2010.<br />
<br />
== Industrial Haskell: 2009 status report ==<br />
<br />
===Industrial Haskell Group===<br />
<br />
For the first time, in 2009, a consortium of companies came together to fund continued development of Haskell and its toolchain. The result is the [http://industry.haskell.org IHG], [http://www.haskell.org/pipermail/haskell/2009-March/021060.html launched] earlier in the year. The initial round of funding resulted in [http://industry.haskell.org/status several improvements to the ecosystem.] The group is seeking to [http://industry.haskell.org/join expand membership in 2010] to further consolidate the commercial strength Haskell. The [http://www.vimeo.com/6697688 Birth of the IHG] was presented at the &quot;[http://cufp.galois.com/ Commercial Users of Functional Programming]&quot; workshop.<br />
<br />
===CUFP===<br />
<br />
2009's [http://cufp.org Commercial Users of Functional Programming] workshop was held in Edinburgh, and included talks on:<br />
<br />
* [http://www.vimeo.com/6703480 Real World Haskell];<br />
* [http://www.vimeo.com/6701254 Teleconferencing on maps in Haskell];<br />
* [http://www.vimeo.com/6699769 Functional Programming at Facebook].<br />
<br />
Next year's CUFP will be held in Baltimore.<br />
<br />
===Industrial reports===<br />
<br />
A number of experience reports on the use of Haskell were presented in 2009:<br />
<br />
* As part of [http://galois.com Galois]' 10th birthday, Don Stewart presented a talk at the [http://www.londonhug.net/ LondonHUG] on [http://www.galois.com/blog/2009/04/27/engineering-large-projects-in-haskell-a-decade-of-fp-at-galois/ Engineering Large Projects in Haskell], celebrating a decade of use of Haskell by Galois.<br />
* [http://www.typlab.com/ TypLAB], a new startup [http://blog.typlab.com/2009/09/why-we-use-haskell/ talked about why they use Haskell].<br />
* Facebook released its [http://github.com/facebook/lex-pass/tree/master lex-pass tool to automate changes to a PHP codebase, by writing abstract-syntax-tree transformers in Haskell]; and <br />
* [http://www.starling-software.com/en/ Starling Software] described [http://www.starling-software.com/misc/icfp-2009-cjs.pdf building a real time financial trading system in Haskell] :: PDF.<br />
* Tom Hawkin's [http://hackage.haskell.org/package/atom/ Atom EDSL] for control systems [http://www.haskell.org/pipermail/haskell-cafe/2009-July/064775.html went into production use] in trucks and buses, and is [http://www.haskell.org/pipermail/haskell-cafe/2009-December/070558.html starting to be used] on a NASA runtime monitoring project.<br />
* The [http://www.cryptol.net Cryptol] release got [http://developers.slashdot.org/article.pl?sid=08/12/26/1725208 slashdotted].<br />
* [http://blog.tupil.com/building-commercial-haskell-applications/ Tupil.com] talked about their experiences building commercial web apps in Haskell.<br />
<br />
== Haskell in Industry ==<br />
<br />
Many companies have used Haskell for a range of projects, including:<br />
<br />
* [http://cufp.galois.com/2007/abstracts.html#CyrilSchmidt ABN AMRO] Amsterdam, The Netherlands<br />
<blockquote><br />
ABN AMRO is an international bank headquartered in Amsterdam. For its<br />
investment banking activities it needs to measure the counterparty risk<br />
on portfolios of financial derivatives. </blockquote><br />
::ABN AMRO's [http://cufp.galois.com/2007/abstracts.html#CyrilSchmidt CUFP talk].<br />
<br />
* [http://www.aetion.com/ Aetion Technologies LLC] Columbus, Ohio<br />
<blockquote><br />
Aetion is a defense contractor whose applications use artificial intelligence.<br />
Rapidly changing priorities make it important to minimize the code impact of<br />
changes, which suits Haskell well. Aetion has developed three main projects in<br />
Haskell, all successful. Haskell's concise code was perhaps most important for<br />
rewriting: it made it practicable to throw away old code occasionally. DSELs<br />
allowed the AI to be specified very declaratively. <br />
</blockquote><br />
::Aetion's [http://cufp.galois.com/2006/slides/GaryMorris.pdf CUFP talk].<br />
<br />
* [http://www.allstontrading.com/ Allston Trading]<br />
<blockquote><br />
Headquartered in Chicago, Illinois, Allston Trading, LLC is a premier high frequency market maker in over 40 financial exchanges, in 20 countries, and in nearly every conceivable product class. Allston makes some use of Haskell for their trading infrastructure.<br />
</blockquote><br />
<br />
* [http://www.amgen.com/ Amgen] Thousand Oaks, California<br />
<blockquote><br />
Amgen is a human therapeutics company in the biotechnology industry. Amgen pioneered the development of novel products based on advances in recombinant DNA and molecular biology and launched the biotechnology industry’s first blockbuster medicines.<br />
<br />
Amgen uses Haskell;<br />
<br />
* To rapidly build software to implement mathematical models and other complex, mathematically oriented applications<br />
* Provide a more mathematically rigorous validation of software<br />
* To break developers out of their software development rut by giving them a new way to think about software.<br />
</blockquote><br />
::Amgen's [http://cufp.galois.com/2008/abstracts.html#BalabanDavid CUFP talk].<br />
<br />
* [http://www.ansemond.com/ Ansemond LLC]<br />
<blockquote><br />
"Find It! Keep It! is a Mac Web Browser that lets you keep the pages you<br />
visit in a database. A list of these pages is shown in the 'database<br />
view'. "<br />
</blockquote><br />
<br />
* [http://antiope.com/ Antiope] Fair Haven, New Jersey<br />
<blockquote><br />
Antiope Associates provides custom solutions for wireless communication<br />
and networking problems. Our team has expertise in all aspects of<br />
wireless system design, from the physical and protocol layers to complex<br />
networked applications. Antiope Associates's relies on a number of<br />
advanced techniques to ensure that the communication systems we design<br />
are reliable and free from error. We use custom simulation tools<br />
developed in Haskell, to model our hardware designs..<br />
</blockquote><br />
::Antiope's [http://cufp.galois.com/2008/slides/WrightGregory.pdf CUFP talk].<br />
<br />
* [http://www.att.com AT&amp;T]<br />
<blockquote><br />
Haskell is being used in the Network Security division to automate processing of internet abuse complaints. Haskell has allowed us to easily meet very tight deadlines with reliable results.<br />
</blockquote><br />
<br />
* Anygma Antwerp, Belgium<br />
<blockquote><br />
Anygma is a startup company focusing on generating easy-to-use tools for<br />
creating audio-visual 2D/3D content, in the area of entertainment,<br />
media, corporate communication and the internet. The company is closely<br />
related to Nazooka, a niche player in the<br />
media industry, specialized in creating cross media concepts and<br />
communication solutions. Anygma is using Haskell to quickly build a<br />
prototype of its new content creation platform, targeted towards artists<br />
and designers. </blockquote><br />
<br />
* [http://www.baml.com/ Bank of America Merril Lynch]<br />
<blockquote>Haskell is being used for backend data transformation and loading.</blockquote><br />
<br />
* [http://www.haskell.org/communities/12-2007/html/report.html#sect7.1.2 Barclays Capital Quantitative Analytics Group]<br />
<blockquote><br />
Barclays Capital's Quantitative Analytics group is using Haskell to<br />
develop an embedded domain-specific functional language (called FPF)<br />
which is used to specify exotic equity derivatives. These derivatives,<br />
which are naturally best described in terms of mathematical functions,<br />
and constructed compositionally, map well to being expressed in an<br />
embedded functional language. This language is now regularly being used<br />
by people who had no previous functional language experience.<br />
</blockquote><br />
::[http://lambda-the-ultimate.org/node/3331 Simon Frankau et al's JFP paper on their use of Haskell]<br />
<br />
* [http://www.bcode.com/ bCODE Pty Ltd] Sydney Australia<br />
<blockquote><br />
bCode Pty Ltd is a small venture capital-funded startup using Ocaml and a bit of Haskell in Sydney Australia.<br />
</blockquote><br />
<br />
* [http://www.bluespec.com/ Bluespec, Inc.] Waltham, Massachusetts<br />
<br />
<blockquote><br />
Developing a modern integrated circuit (ASIC or FPGA) is an enormously<br />
expensive process involving specification, modeling (to choose and fix the<br />
architecture), design (to describe what will become silicon) and verification<br />
(to ensure that it meets the specs), all before actually committing anything to<br />
silicon (where the cost of a failure can be tens of millions of dollars).<br />
Bluespec, Inc. is a three year-old company that provides language facilities,<br />
methodologies, and tools for this purpose, within the framework of the IEEE<br />
standard languages SystemVerilog and SystemC, but borrowing ideas heavily from<br />
Term Rewriting Systems and functional programming languages like Haskell. In<br />
this talk, after a brief technical overview to set the context, we will<br />
describe our tactics and strategies, and the challenges we face, in introducing<br />
declarative programming ideas into this field, both externally (convincing<br />
customers about the value of these ideas) and internally (using Haskell for our<br />
tool implementation). <br />
</blockquote><br />
<br />
::Bluespec's [http://cufp.galois.com/2006/abstracts.html#RishiyurNikhil CUFP talk].<br />
<br />
* [http://bu.mp/ Bump]<br />
<blockquote><br />
Bump use a Haskell-based server, [http://github.com/jamwt/Angel Angel], for process supervisor for all their backend systems, and [http://devblog.bu.mp/haskell-at-bump for other infrastructure tasks].<br />
</blockquote><br />
<br />
* [http://www.circos.com Circos Brand Karma] Singapore<br />
<blockquote><br />
Brand Karma provides services to brand owners to measure online sentiments towards their brands.<br />
Haskell is used in building parts of the product, specifically for back-end job scheduling and brand matching.<br />
</blockquote><br />
<br />
* [http://www.credit-suisse.com/ Credit Suisse Global Modelling and Analytics Group] London, UK; New York City, New York<br />
<br />
<blockquote><br />
GMAG, the quantitative modelling group at Credit Suisse, has been using Haskell<br />
for various projects since the beginning of 2006, with the twin aims of<br />
improving the productivity of modellers and making it easier for other people<br />
within the bank to use GMAG models. Current projects include: Further work on<br />
tools for checking, manipulating and transforming spreadsheets; a<br />
domain-specific language embedded in Haskell for implementing reusable<br />
components that can be compiled into various target forms (see the video presentation: [http://www.londonhug.net/2008/08/11/video-paradise-a-dsel-for-derivatives-pricing/ Paradise, a DSEL for Derivatives Pricing]).<br />
</blockquote><br />
<br />
::Credit Suisse's [http://cufp.galois.com/2006/abstracts.html#HowardMansell CUFP talk].<br />
<br />
* [http://detexify.kirelabs.org/classify.html Detexify]<br />
<br />
<blockquote><br />
Detexify is an online handwriting recognition system, whose backend is written in Haskell. <br />
</blockquote><br />
<br />
* [http://www.db.com/ Deutsche Bank Equity Proprietary Trading, Directional Credit Trading]<br />
<br />
<blockquote><br />
The Directional Credit Trading group uses Haskell as the primary<br />
implementation language for all its software infrastructure.<br />
</blockquote><br />
<br />
::Deutsche Bank's [http://cufp.galois.com/2008/abstracts.html#PolakowJeff CUFP talk].<br />
<br />
* [http://article.gmane.org/gmane.comp.lang.haskell.cafe/37093 Eaton] Cleveland, Ohio<br />
<br />
<blockquote><br />
Design and verification of hydraulic hybrid vehicle systems<br />
</blockquote><br />
<br />
::Eaton's [http://cufp.galois.com/2008/abstracts.html#HawkinsTom CUFP talk]<br />
::Eaton's [http://www.haskell.org/pipermail/haskell-cafe/2009-April/060602.html experiences using a Haskell DSL]<br />
<br />
* [Ericsson AB]<br />
<blockquote><br />
Ericsson uses Haskell for the implementation of Feldspar, an EDSL for digital signal processing algorithms.<br />
</blockquote><br />
<br />
::Ericsson's [http://hackage.haskell.org/package/feldspar-compiler Feldspar compiler]<br />
<br />
* [http://facebook.com Facebook]<br />
<br />
<blockquote><br />
Facebook uses some Haskell internally for tools. [http://github.com/facebook/lex-pass/tree/master lex-pass] is a tool for programmatically manipulating a PHP code base via Haskell.<br />
</blockquote><br />
<br />
:: Facebook's [http://cufp.galois.com/2009/abstracts.html#ChristopherPiroEugeneLetuchy CUFP talk]<br />
<br />
* [http://www.factisresearch.com/ Factis Research]<br />
<blockquote><br />
Factis research, located in Freiburg, Germany, develops reliable and user-friendly mobile solutions. Our client software runs under J2ME, Symbian, iPhone OS, Android, and Blackberry. The server components are implemented in Python and Haskell. We are actively using Haskell for a number of projects, most of which are released under an open-source license.<br />
</blockquote><br />
<br />
:: Factis' [http://haskell.org/communities/05-2010/html/report.html#factisresearch HCAR submission]<br />
<br />
* [http://www.funktional.info/index.php?id=7&L=1 Funktionale Programmierung Dr. Heinrich Hördegen], Munich, Germany<br />
<blockquote><br />
We develop software prototypes according to the Pareto principle: After spending only 20 percent of budget, we aim to provide already 80 percent of the software's functionality. We can realize this by constructing a 2080-software-prototype that we can further develop into a full-fledged solution...<br />
</blockquote><br />
<br />
* [http://www.haskell.org/pipermail/haskell-cafe/2008-September/047168.html Gamr7] http://gamr7.com/ Lyon, France<br />
<br />
<blockquote><br />
Gamr7 is a startup focused on procedural city generation for the game<br />
and simulation market. <br />
</blockquote><br />
<br />
* [http://www.galois.com/ Galois, Inc] Portland, Oregon<br />
<br />
<blockquote><br />
Galois designs and develops high confidence software for critical applications.<br />
Our innovative approach to software development provides high levels of<br />
assurance, yet its scalability enables us to address the most complex problems.<br />
We have successfully engineered projects under contract for corporations and<br />
government clients in the demanding application areas of security, information<br />
assurance and cryptography. <br />
</blockquote><br />
<br />
::Galois' [http://cufp.galois.com/2007/abstracts.html#JohnLaunchbury CUFP talk]<br />
::Galois' [http://corp.galois.com/blog/2009/4/27/engineering-large-projects-in-haskell-a-decade-of-fp-at-galo.html retrospective on 10 years of industrial Haskell use]<br />
<br />
* [http://google.com Google]<br />
<br />
<blockquote><br />
Haskell is used on a small number of internal projects in Google, for internal IT infrastructure support. <br />
</blockquote><br />
<br />
::Google's [http://k1024.org/~iusty/papers/icfp10-haskell-reagent.pdf ICFP 2010 experience report on Haskell]<br />
<br />
* [http://glyde.com/ Glyde]<br />
<br />
<blockquote><br />
Glyde uses OCaml and Haskell for a few projects. Glyde uses Haskell for our client-side template source-to-source translator, which converts HAML-like view templates into JS code.<br />
</blockquote><br />
<br />
* [http://article.gmane.org/gmane.comp.lang.haskell.cafe/21951 HAppS LLC]<br />
<br />
<blockquote><br />
Open web development company. Now merged with [http://happstack.com/ happstack]<br />
</blockquote><br />
<br />
* [http://hustlerturf.com Hustler Turf Equipment] Hesston, Kansas<br />
<blockquote><br />
Designs, builds, and sells lawn mowers. We use quite a bit of Haskell, especially as a "glue language" for tying together data from different manufacturing-related systems. We also use it for some web apps that are deployed to our dealer network. There are also some uses for it doing sysadmin<br />
automation, such as adding/removing people from LDAP servers and the like<br />
</blockquote><br />
<br />
* [http://iba-cg.de/haskell.html iba Consulting Gesellschaft] - Intelligent business architecture for you. Leipzig, Germany<br />
<br />
<blockquote><br />
iba CG develops software for large companies: <br />
* risk analysis and reporting solution for power supply company; <br />
* contract management, assert management, booking and budgeting software for one of the worldwide leading accounting firm.<br />
</blockquote><br />
<br />
* [http://www.ics-ag.de/ Informatik Consulting Systems AG]<br />
<br />
<blockquote><br />
ICS AG developed a simulation and testing tool which based on a DSL (Domain Specific Language). The DSL is used for the description of architecture and behavior of distributed system components (event/message based, reactive). The compiler was written in Haskell (with target language Ada). The test system is used in some industrial projects.<br />
</blockquote><br />
<br />
* [http://ipwnstudios.com/ iPwn Studios]<br />
<blockquote><br />
ipwn studios is a video game studio founded in 2009 and based in the greater Boston area. They're developing a game engine in Haskell, and a number of games built on that engine, including an action-rpg for touchscreen devices called bloodknight.<br />
</blockquote><br />
<br />
* [http://www.ivu.de/uk/products/public-transport/ IVU Traffic Technologies AG]<br />
<blockquote><br />
The rostering group at IVU Traffic Technologies AG has been using Haskell to check rosters for compliance with EC regulations.<br />
<br />
Our implementation is based on an embedded DSL to combine the regulation’s single rules into a solver that not only decides on instances but, in the case of a faulty roster, finds an interpretation of the roster that is “favorable” in the sense that the error messages it entails are “helpful” in leading the dispatcher to the resolution of the issue at hand.<br />
<br />
The solver is both reliable (due to strong static typing and referential transparency — we have not experienced a failure in three years) and efficient (due to constraint propagation, a custom search strategy, and lazy evaluation).<br />
<br />
Our EC 561/2006 component is part of the IVU.crew software suite and as such is in wide-spread use all over Europe, both in planning and dispatch. So the next time you enter a regional bus, chances are that the driver’s roster was checked by Haskell.<br />
</blockquote><br />
<br />
* [http://www.janrain.com JanRain]<br />
<blockquote><br />
JanRain uses Haskell for network and web software. Read more about [http://www.janrain.com/blogs/haskell-janrain Haskell at JanRain] and in their [http://corp.galois.com/blog/2011/3/8/tech-talk-haskell-and-the-social-web.html tech talk at Galois]. JanRain's "[http://www.janrain.com/products/capture Capture]" user API product is built on Haskell's Snap webframework.<br />
</blockquote><br />
<br />
:: See Janrain's [http://corp.galois.com/blog/2011/4/22/tech-talk-video-haskell-and-the-social-web.html technical talk about their use of Snap]<br />
<br />
* [http://joyridelabs.de/game/ Joyride Laboratories]<br />
<br />
<blockquote><br />
Joyride Laboratories is an independent game development studio, founded in 2009 by Florian Hofer and Sönke Hahn. Their first game, "Nikki and the Robots" was released in 2011.<br />
</blockquote><br />
<br />
* [http://www.linspire.com/ Linspire]<br />
<br />
<blockquote><br />
Linspire, Inc. has used functional programming since its inception in 2001,<br />
beginning with extensive use of O'Caml, with a steady shift to Haskell as its<br />
implementations and libraries have matured. Hardware detection, software<br />
packaging and CGI web page generation are all areas where we have used<br />
functional programming extensively. Haskell's feature set lets us replace much<br />
of our use of little languages (e.g., bash or awk) and two-level languages (C<br />
or C++ bound to an interpreted language), allowing for faster development,<br />
better code sharing and ultimately faster implementations. Above all, we value<br />
static type checking for minimizing runtime errors in applications that run in<br />
unknown environments and for wrapping legacy programs in strongly typed<br />
functions to ensure that we pass valid arguments. <br />
</blockquote><br />
<br />
::Linspire's [http://cufp.galois.com/2006/abstracts.html#CliffordBeshers CUFP talk]<br />
::Linspire's experience report on using [http://portal.acm.org/citation.cfm?doid=1291151.1291184 functional programming to manage a Linux distribution]<br />
<br />
* [http://www.mitre.org/ MITRE]<br />
<blockquote><br />
MITRE uses Haskell for, amongst other things, the [http://hackage.haskell.org/package/cpsa analysis of cryptographic protocols].<br />
</blockquote><br />
<br />
* [http://ertos.nicta.com.au/research/sel4/ NICTA]<br />
<blockquote><br />
NICTA has used Haskell as part of a project to verify the L4 microkernel.<br />
</blockquote><br />
::[http://www.drdobbs.com/embedded/222400553 Read the Dr. Dobbs article on using Haskell and formal methods to verify a kernel]<br />
<br />
* [http://www.gb.nrao.edu NRAO]<br />
<blockquote><br />
NRAO has used Haskell to implement the core science algorithms for the Robert C. Byrd Green Bank Telescope (GBT) Dynamic Scheduling System ([http://www.gb.nrao.edu/dss DSS]).<br />
::Source code available on [https://github.com/nrao/antioch GitHub].<br />
</blockquote><br />
<br />
* [http://blog.openomy.com/2008/01/case-study-using-haskell-and-happs-for.html Openomy]<br />
<br />
<blockquote><br />
Openomy's API v2.0 is developed in Haskell, using the<br />
[http://www.happs.org/ HAppS] web platform.<br />
</blockquote><br />
<br />
* [http://www.oblomov.com Oblomov]<br />
<br />
<blockquote><br />
Oblomov Systems is a one-person software company based in Utrecht, The Netherlands. Founded in 2009, Oblomov has since then been working on a number of Haskell-related projects. The main focus lies on web-applications and (web-based) editors. Haskell has turned out to be extremely useful for implementing web servers that communicate with JavaScript clients or iPhone apps.<br />
</blockquote><br />
<br />
:: [http://haskell.org/communities/05-2010/html/report.html#oblomov Oblomov's HCAR submission].<br />
<br />
* [http://www.patch-tag.com Patch-Tag: hosting for darcs]<br />
<blockquote><br />
Need somewhere to put your darcs code? Try us.<br />
<br />
Patch-Tag is built with [http://happstack.com happstack], the continuation of the project formerly known as HAppS.<br />
</blockquote><br />
<br />
* [http://www.peerium.com Peerium, Inc] Cambridge, Massachusetts<br />
<blockquote><br />
At Peerium, we're striving to bring a new level of quality and efficiency to online communication and collaboration within virtual communities, social networks, and business environments. We believe that a new environment that supports the effortless sharing of both information and software will enable a level of online cooperation far beyond current Web-based technologies -- modern programming techniques will enable the creation of more robust and more powerful programs within these environments. To this end, we're building a new software platform for direct, real-time communication and collaboration within graphically rich environments. Peerium is located in the heart of Harvard Square in Cambridge, Massachusetts.<br />
</blockquote><br />
<br />
* [http://www.qualcomm.com/ Qualcomm, Inc]<br />
<br />
<blockquote><br />
Qualcomm uses Haskell to generate Lua bindings to the BREW platform <br />
</blockquote><br />
<br />
* [http://www.renci.org/ Renaissaince Computing Institute], Chapel Hill, North Carolina<br />
<blockquote><br />
The Renaissance Computing Institute (RENCI), a multi-institutional organization, brings together multidisciplinary experts and advanced technological capabilities to address pressing research issues and to find solutions to complex problems that affect the quality of life in North Carolina, our nation and the world.<br />
<br />
Research scientists at RENCI have used Haskell for a number of projects, including [http://vis.renci.org/jeff/2009/08/26/open-sourcing-the-big-board/ The Big Board].<br />
</blockquote><br />
<br />
::RENCI's [http://cufp.galois.com/2009/abstracts.html#JeffersonHeard CUFP talk].<br />
<br />
* [http://www.signalicorp.com/index.htm Signali] Portland, Oregon<br />
<br />
<blockquote><br />
Signali Corp is a new custom hardware design company. Our chief products<br />
are custom IP cores targeted for embedded DSP and cryptographic<br />
applications. Our specialty is the design and implementation of<br />
computationally intensive, complex algorithms. The interfaces to each<br />
core are modular and can be very efficiently modified for your specific<br />
application. System-level integration and validation is crucial and is<br />
the majority of investment in a product.<br />
</blockquote><br />
<br />
* [http://www.standardchartered.com/home/en/index.html Standard Chartered]<br />
<br />
<blockquote><br />
Standard Chartered has a large group using Haskell in finance.<br />
</blockquote><br />
<br />
* [http://www.starling-software.com/en/index.html Starling Software] Tokyo, Japan<br />
<blockquote><br />
Starling Software are developing a commercial automated options trading system <br />
in Haskell, and are migrating other parts of their software suite to<br />
Haskell.<br />
</blockquote><br />
<br />
::Starling Software's [http://www.starling-software.com/misc/icfp-2009-cjs.pdf experience building real time trading systems in Haskell] <br />
<br />
* [http://www.tabula.com/ Tabula.com]<br />
<blockquote><br />
Tabula is a privately held fabless semiconductor company developing 3-D Programmable Logic Devices. Haskell is used for internal compiler toolchains related to hardware design.<br />
</blockquote><br />
<br />
* [http://tsurucapital.com Tsuru Capital] Tokyo, Japan<br />
<blockquote><br />
Tsuru Capital is operating an automated options trading system written in Haskell.<br />
</blockquote><br />
<br />
::[http://haskell.org/communities/05-2010/html/report.html#sect7.6 Tsuru Capital's HCAR submission]<br />
<br />
* [http://tupil.com/ Tupil] Utrecht, The Netherlands<br />
<br />
<blockquote><br />
Tupil is a Dutch company that built software for clients, written in Haskell. Tupil used Haskell for the speed in development and resulting software quality. The company is founded by Chris Eidhof and Eelco Lempsink. Currently they build iPhone/iPad applications in Objective-C.<br />
</blockquote><br />
<br />
:: Tupil's experience building [http://blog.tupil.com/building-commercial-haskell-applications/ commercial web apps in Haskell]<br />
<br />
* [http://typlab.com TypLAB] Amsterdam, The Netherlands<br />
<br />
<blockquote><br />
TypLAB investigates and develops new ways of creating and consuming online content. Their [http://www.silkapp.com/ Silk] application makes it easy to filter and visualize large amounts of information.<br />
</blockquote><br />
<br />
:: TypLAB's blog on [http://blog.typlab.com/2009/09/why-we-use-haskell/ why they use Haskell]<br />
:: A [http://thenextweb.com/eu/2011/04/28/filter-and-visualize-data-in-seconds-with-silk/ review of Silk]<br />
<br />
* [http://www.sensor-sense.nl Sensor Sense] Nijmegen, The Netherlands<br />
<br />
<blockquote><br />
Sensor Sense is offering high technology systems for gas measurements in the ''ppbv'' down to ''pptv'' range. We use Haskell for the embedded control software of our trace gas detectors.<br />
</blockquote><br />
<br />
If you're using Haskell commercially, please add your details here.<br />
<br />
== The Industrial Haskell Group ==<br />
<br />
The [http://industry.haskell.org/ Industrial Haskell Group (IHG)] is an organisation to support the needs of commercial users of the Haskell programming language. <br />
<br />
== Jobs and recruitment ==<br />
<br />
[[Jobs|Haskell jobs]] on the HaskellWiki.<br />
<br />
[http://www.haskellers.com/jobs Jobs at Haskellers.com].<br />
<br />
== Consultants ==<br />
<br />
[[Consultants]]<br />
<br />
== Commercial Users of Functional Programming Workshop ==<br />
<br />
[http://www.galois.com/cufp/ Commercial Users of Functional Programming]<br />
<br />
The goal of [http://www.galois.com/cufp/ CUFP] is to build a community<br />
for users of functional programming languages and technology, be they<br />
using functional languages in their professional lives, in an open<br />
source project (other than implementation of functional languages), as a<br />
hobby, or any combination thereof. In short: anyone who uses functional<br />
programming as a means, but not an end.<br />
<br />
[[Category:Community]]</div>Jameshfisherhttps://wiki.haskell.org/index.php?title=The_Monad.Reader/Previous_issues&diff=41764The Monad.Reader/Previous issues2011-08-25T16:55:34Z<p>Jameshfisher: Authors and titles were swapped around for Issue 11 for some reason.</p>
<hr />
<div>[[Media:TMR-Issue1.pdf|The Monad.Reader Issue 1]] was released on March 1, 2005.<br />
;''<nowiki>Pseudocode: Natural Style</nowiki>''<br />
:Andrew J. Bromage<br />
;''Pugs Apocryphon 1 - Overview of the Pugs project''<br />
:Autrijus Tang<br />
;''An Introduction to Gtk2Hs, a Haskell GUI Library''<br />
:Kenneth Hoste<br />
;''Implementing Web-Services with the HAIFA Framework''<br />
:Simon D. Foster<br />
;''<nowiki>Code Probe - Issue one: Haskell XML-RPC, v.2004-06-17 [1]</nowiki>''<br />
:Sven Moritz Hallberg<br />
<br />
[[The Monad.Reader/Issue2| The Monad.Reader Issue 2]] was released May 2005.<br />
;''Impure Thoughts 1 - Thtatic Compilathionth (without a lisp)''<br />
:Philippa Cowderoy<br />
;''Eternal Compatibility In Theory''<br />
:Sven Moritz Hallberg<br />
;''Fun with Linear Implicit Parameters''<br />
:Thomas Jäger<br />
;''Haskore''<br />
:Bastiaan Zapf<br />
;''Bzlib2 Binding - An Introduction to the FFI''<br />
:Peter Eriksen<br />
<br />
[[The Monad.Reader/Issue3| The Monad.Reader Issue 3]] was released June 2005.<br />
;''Notes on Learning Haskell''<br />
:Graham Klyne <br />
;''Functional Programming vs Object Oriented Programming''<br />
:Alistair Bayley <br />
;''Concurrent and Distributed Programming with Join Hs''<br />
:Einar Karttunen <br />
;''"Haskell School Of Expression"<nowiki>:</nowiki> Review of The Haskell School of Expression''<br />
:Isaac Jones <br />
;''Review of "Purely Functional Data Structures"''<br />
:Andrew Cooke <br />
<br />
[[The Monad.Reader/Issue4 | The Monad.Reader Issue 4]] was released 5 July 2005.<br />
;''Impure Thoughts 2, B&D not S&M'' (off-wiki)<br />
:Philippa Cowderoy <br />
;''Why Attribute Grammars Matter''<br />
:Wouter Swierstra <br />
;''Solving Sudoku''<br />
:Dominic Fox <br />
;''On Treaps And Randomization''<br />
:Jesper Louis Andersen <br />
<br />
[[The Monad.Reader/Issue5 | The Monad.Reader Issue 5]] was released October 2005.<br />
;''<nowiki>Haskell: A Very Different Language</nowiki>''<br />
:John Goerzen<br />
;''Generating Polyominoes''<br />
:Dominic Fox<br />
;''<nowiki>HRay:A Haskell ray tracer</nowiki>''<br />
:Kenneth Hoste<br />
;''Number-parameterized types''<br />
:Oleg Kiselyov<br />
;''A Practical Approach to Graph Manipulation''<br />
:Jean Philippe Bernardy<br />
;''Software Testing With Haskell''<br />
:Shae Erisson<br />
<br />
[[Media:TMR-Issue6.pdf|The Monad.Reader Issue 6]] was released January 31, 2007.<br />
;''Getting a Fix from the Right Fold''<br />
:Bernie Pope<br />
;''Adventures in Classical-Land''<br />
:Dan Piponi<br />
;''Assembly: Circular Programming with Recursive do''<br />
:Russell O'Connor<br />
<br />
[[Media:TMR-Issue7.pdf|The Monad.Reader Issue 7]] was released April 30, 2007.<br />
;''A Recipe for controlling Lego using Lava''<br />
:Matthew Naylor<br />
;''<nowiki>Caml Trading: Experiences in Functional Programming on Wall Street</nowiki>''<br />
:Yaron Minsky<br />
;''<nowiki>Book Review: “Programming in Haskell” by Graham Hutton</nowiki>''<br />
:Duncan Coutts<br />
;''Yhc.Core – from Haskell to Core''<br />
:Dimitry Golubovsky, Neil Mitchell, Matthew Naylor<br />
<br />
[[Media:TMR-Issue8.pdf|The Monad.Reader Issue 8]] was released on September 10, 2007.<br />
;''Generating Multiset Partitions''<br />
:Brent Yorgey<br />
;''Type-Level Instant Insanity''<br />
:Conrad Parker<br />
<br />
[[Media:TMR-Issue9.pdf|The Monad.Reader Issue 9]], the [http://hackage.haskell.org/trac/summer-of-code/wiki Summer of Code] special, was released on November 19, 2007.<br />
;''Cabal Configurations''<br />
:Thomas Schilling<br />
;''Darcs Patch Theory''<br />
:Jason Dagit<br />
;''<nowiki>TaiChi: how to check your types with serenity</nowiki>''<br />
:Mathieu Boespflug<br />
<br />
[[Media:TMR-Issue10.pdf|The Monad.Reader Issue 10]] was released on April 8, 2008.<br />
;''Step inside the <nowiki>GHCi</nowiki> debugger''<br />
:Bernie Pope<br />
;''Evaluating Haskell in Haskell''<br />
:Matthew Naylor<br />
<br />
[[Media:TMR-Issue11.pdf|The Monad.Reader Issue 11]] was released on August 25, 2008.<br />
;''How to Refold a Map''<br />
:David F. Place<br />
;''First-Order Logic à la Carte''<br />
:Kenneth Knowles<br />
;''<nowiki>MonadPlus: What a Super Monad!</nowiki>'' <br />
:Douglas M. Auclair<br />
<br />
[[Media:TMR-Issue12.pdf|The Monad.Reader Issue 12]], the second Summer of Code special, was released on November 19, 2008.<br />
<br />
;''Compiler Development Made Easy''<br />
:Max Bolingbroke<br />
;''How to Build a Physics Engine''<br />
:Roman Cheplyaka<br />
;''Hoogle Overview''<br />
:Neil Mitchell<br />
<br />
[[Media:TMR-Issue13.pdf|The Monad.Reader Issue 13]] was released on March 12, 2009.<br />
<br />
;''Rapid Prototyping in TEX''<br />
:Stephen Hicks<br />
;''The Typeclassopedia''<br />
:Brent Yorgey<br />
;''<nowiki>Book Review: Real World Haskell</nowiki>''<br />
:Chris Eidhof and Eelco Lempsink<br />
;''Calculating Monads with Category Theory''<br />
:Derek Elkins</div>Jameshfisher