https://wiki.haskell.org/api.php?action=feedcontributions&user=JohannesAhlmann&feedformat=atomHaskellWiki - User contributions [en]2017-05-22T19:50:30ZUser contributionsMediaWiki 1.19.14+dfsg-1https://wiki.haskell.org/User:JohannesAhlmannUser:JohannesAhlmann2011-08-22T20:41:16Z<p>JohannesAhlmann: </p>
<hr />
<div>So far i've toyed around with many Haskell concepts, including the obligatory [http://haskell.org/tmrwiki/JohannesAhlmann Ray Tracer], some Genetic Algorithms and Neural Networks.<br />
<br />
I took part in the [http://www.icfpcontest.org/ 2007 ICFP contest] in the team [http://homes.esat.kuleuven.be/~cpoucet/icfp2007.html Lazy Bottoms] placing 56th of 859 teams and although I didn't contribute by far as much as I would have wanted, it still was a lot of fun and definitely worth the coding marathon.<br />
<br />
Pages I've written/contributed to:<br />
* [[BlowYourMindIdioms]]<br />
* [http://web.archive.org/web/20061011050035/http://www.haskell.org/hawiki/TemplateHaskellTutorial Template Haskell Tutorial], unfortunately I was too lazy to port the tutorial to the new wiki, so it's now [http://archive.org archive.org]'ed.<br />
<br />
<br />
<br />
I also like the format of the Ruby/[[Haskell_Quiz|Haskell Quiz]] and I try to contribute solutions to interesting problems whenever I find the time. Some of these might be educational and some just plain ugly, but I always find it quite fulfilling to tackle these:<br />
* [[Haskell_Quiz/Phone_Number_Words/Solution_Jethr0|Phone Number Words]]<br />
* [[Haskell_Quiz/Index_and_Query/Solution_Jethr0|Index and Query]]<br />
* [[Haskell_Quiz/Constraint_Processing/Solution_Jethr0|Constraint Processing]]<br />
* [[Haskell_Quiz/Animal_Quiz/Solution_Jethr0|Animal Quiz]]<br />
* [[Haskell_Quiz/DayRange/Solution_Jethr0|Day Range]]<br />
* [[Haskell_Quiz/Verbal_Arithmetic/Solution_Jethr0|Verbal Arithmetic]]<br />
* [[Haskell_Quiz/Chip_Eight/Solution_Jethr0|Chip Eight]]<br />
* [[Haskell_Quiz/Sokoban/Solution_Jethr0|Sokoban]]</div>JohannesAhlmannhttps://wiki.haskell.org/Talk:CookbookTalk:Cookbook2009-04-24T20:30:28Z<p>JohannesAhlmann: retracted pleac criticism ;)</p>
<hr />
<div>==Size and direction of page==<br />
Personally, it seems to me that this will be a very large and overwhelming page if it is filled out with all the items in the TOC. What about having it as a gathering page, pointing to other cookbook pages that are subs of this? [[User:BrettGiles|BrettGiles]] 17:44, 22 February 2007 (UTC)<br />
<br />
:I think we should definitely do this, but after the page has grown big. As long as it's not needed, we should stick with one page. The user can now still easily scroll the page. [[User:chriseidhof]].<br />
<br />
:As of now, the very short entries for the chapter give the page its very own charm. I like it very much and I think we should stick to that. It's more a cheatsheet than a cookbook, but who cares. -- [[User:Apfelmus|Apfelmus]] 19:19, 25 February 2007 (UTC)<br />
<br />
:: Makes sense. I like your thought of the page having "charm" :) [[User:BrettGiles|BrettGiles]] 22:27, 26 February 2007 (UTC)<br />
<br />
::: I've split up the page into subpages now, since saving and restructuring the content has become a pain. --[[User:Lenny222|Lenny222]] 10:54, 23 April 2009 (UTC)<br />
<br />
Do you guys know about this:<br />
http://pleac.sourceforge.net/<br />
It seems to be abandoned and it seems the Haskell part didn't go that far, but it does show up on a google search. [[User:Tanimoto|tanimoto]] 15:41, 24 April 2009 (UTC)<br />
<br />
:<strike>The haskell pleac part is a known disgrace and is not only old, but also uses horrible techniques like redefining the (.) function. It would likely be best if the pleac haskell entries be purged completely as they probably never have but certainly do not reflect current haskell best practices. --[[User:JohannesAhlmann|jethr0]] 20:30, 24 April 2009 (UTC)</strike><br />
<br />
::Seems I have to retract that as somebody went to the trouble of fixing the mess that was pleac_haskell. I wouldn't guarantee that it's the finest haskell code ever, but at least it's no longer a total disaster. Maybe we can "borrow" some ideas from the pleac set of tasks. --[[User:JohannesAhlmann|jethr0]] 20:30, 24 April 2009 (UTC)<br />
<br />
==Focus on Haskell concepts as well as general tasks==<br />
I like the idea of selecting typical cookbook tasks and providing haskell code snippets. Also it might be useful to provide examples of certain haskell concepts that may not be related to a specific task, like "how to use Control.Monad", "how to use list comprehensions", "how to use STM" etc,.<br />
[[User:b7j0c|b7j0c]]<br />
<br />
:As long as the focus is on practical use, yes. I think we should not provide abstract examples, but concrete examples of a practical problem. This is a bit more difficult, but way more interesting for the end-user.<br />
<br />
<br />
==Somehow use a literate Haskell Approach==<br />
to make sure that code examples actually do what they are supposed to do (i.e. with sth. like docTest)<br />
<br />
Also, I find separate pages for strings and lists superfluous. Let's have "Strings" link to "Lists" for the list functions and only describe character-specific cases for "Strings" (Unicode, upper/lowercasing, ...)<br />
--[[User:JohannesAhlmann|jethr0]] 13:17, 23 April 2009 (UTC)<br />
<br />
: You are right. We should "unify Strings and Lists", but in a way that people new to Haskell will find solutions to common programing problems. I am convinced that Strings := Lists don't come natural to most. So I am not yet sure how to do that. I also don't know how to mix literate Haskell with Wikimedia. --[[User:Lenny222|Lenny222]] 13:35, 23 April 2009 (UTC)<br />
--[[User:JohannesAhlmann|jethr0]] 20:08, 24 April 2009 (UTC)</div>JohannesAhlmannhttps://wiki.haskell.org/Talk:CookbookTalk:Cookbook2009-04-24T20:08:14Z<p>JohannesAhlmann: pleac criticism</p>
<hr />
<div>==Size and direction of page==<br />
Personally, it seems to me that this will be a very large and overwhelming page if it is filled out with all the items in the TOC. What about having it as a gathering page, pointing to other cookbook pages that are subs of this? [[User:BrettGiles|BrettGiles]] 17:44, 22 February 2007 (UTC)<br />
<br />
:I think we should definitely do this, but after the page has grown big. As long as it's not needed, we should stick with one page. The user can now still easily scroll the page. [[User:chriseidhof]].<br />
<br />
:As of now, the very short entries for the chapter give the page its very own charm. I like it very much and I think we should stick to that. It's more a cheatsheet than a cookbook, but who cares. -- [[User:Apfelmus|Apfelmus]] 19:19, 25 February 2007 (UTC)<br />
<br />
:: Makes sense. I like your thought of the page having "charm" :) [[User:BrettGiles|BrettGiles]] 22:27, 26 February 2007 (UTC)<br />
<br />
::: I've split up the page into subpages now, since saving and restructuring the content has become a pain. --[[User:Lenny222|Lenny222]] 10:54, 23 April 2009 (UTC)<br />
<br />
Do you guys know about this:<br />
http://pleac.sourceforge.net/<br />
It seems to be abandoned and it seems the Haskell part didn't go that far, but it does show up on a google search. [[User:Tanimoto|tanimoto]] 15:41, 24 April 2009 (UTC)<br />
<br />
:The haskell pleac part is a known disgrace and is not only old, but also uses horrible techniques like redefining the (.) function. It would likely be best if the pleac haskell entries be purged completely as they probably never have but certainly do not reflect current haskell best practices. <br />
<br />
==Focus on Haskell concepts as well as general tasks==<br />
I like the idea of selecting typical cookbook tasks and providing haskell code snippets. Also it might be useful to provide examples of certain haskell concepts that may not be related to a specific task, like "how to use Control.Monad", "how to use list comprehensions", "how to use STM" etc,.<br />
[[User:b7j0c|b7j0c]]<br />
<br />
:As long as the focus is on practical use, yes. I think we should not provide abstract examples, but concrete examples of a practical problem. This is a bit more difficult, but way more interesting for the end-user.<br />
<br />
<br />
==Somehow use a literate Haskell Approach==<br />
to make sure that code examples actually do what they are supposed to do (i.e. with sth. like docTest)<br />
<br />
Also, I find separate pages for strings and lists superfluous. Let's have "Strings" link to "Lists" for the list functions and only describe character-specific cases for "Strings" (Unicode, upper/lowercasing, ...)<br />
--[[User:JohannesAhlmann|jethr0]] 13:17, 23 April 2009 (UTC)<br />
<br />
: You are right. We should "unify Strings and Lists", but in a way that people new to Haskell will find solutions to common programing problems. I am convinced that Strings := Lists don't come natural to most. So I am not yet sure how to do that. I also don't know how to mix literate Haskell with Wikimedia. --[[User:Lenny222|Lenny222]] 13:35, 23 April 2009 (UTC)<br />
--[[User:JohannesAhlmann|jethr0]] 20:08, 24 April 2009 (UTC)</div>JohannesAhlmannhttps://wiki.haskell.org/Talk:CookbookTalk:Cookbook2009-04-23T13:17:58Z<p>JohannesAhlmann: literate haskell, string vs. list</p>
<hr />
<div>==Size and direction of page==<br />
Personally, it seems to me that this will be a very large and overwhelming page if it is filled out with all the items in the TOC. What about having it as a gathering page, pointing to other cookbook pages that are subs of this? [[User:BrettGiles|BrettGiles]] 17:44, 22 February 2007 (UTC)<br />
<br />
:I think we should definitely do this, but after the page has grown big. As long as it's not needed, we should stick with one page. The user can now still easily scroll the page. [[User:chriseidhof]].<br />
<br />
:As of now, the very short entries for the chapter give the page its very own charm. I like it very much and I think we should stick to that. It's more a cheatsheet than a cookbook, but who cares. -- [[User:Apfelmus|Apfelmus]] 19:19, 25 February 2007 (UTC)<br />
<br />
:: Makes sense. I like your thought of the page having "charm" :) [[User:BrettGiles|BrettGiles]] 22:27, 26 February 2007 (UTC)<br />
<br />
::: I've split up the page into subpages now, since saving and restructuring the content has become a pain. --[[User:Lenny222|Lenny222]] 10:54, 23 April 2009 (UTC)<br />
<br />
==Focus on Haskell concepts as well as general tasks==<br />
I like the idea of selecting typical cookbook tasks and providing haskell code snippets. Also it might be useful to provide examples of certain haskell concepts that may not be related to a specific task, like "how to use Control.Monad", "how to use list comprehensions", "how to use STM" etc,.<br />
[[User:b7j0c|b7j0c]]<br />
<br />
:As long as the focus is on practical use, yes. I think we should not provide abstract examples, but concrete examples of a practical problem. This is a bit more difficult, but way more interesting for the end-user.<br />
<br />
<br />
==Somehow use a literate Haskell Approach==<br />
to make sure that code examples actually do what they are supposed to do (i.e. with sth. like docTest)<br />
<br />
Also, I find separate pages for strings and lists superfluous. Let's have "Strings" link to "Lists" for the list functions and only describe character-specific cases for "Strings" (Unicode, upper/lowercasing, ...)<br />
--[[User:JohannesAhlmann|jethr0]] 13:17, 23 April 2009 (UTC)</div>JohannesAhlmannhttps://wiki.haskell.org/Cookbook/Lists_and_stringsCookbook/Lists and strings2009-04-23T12:10:39Z<p>JohannesAhlmann: reverse . take . reverse</p>
<hr />
<div>Since strings are lists of characters, you can use any available list function.<br />
<br />
= Combining strings =<br />
<br />
{| class="wikitable"<br />
|-<br />
! Problem<br />
! Solution<br />
! Examples<br />
|-<br />
| combining two strings<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v%3A%2B%2B (++)]<br />
|<haskell><br />
"foo" ++ "bar" --> "foobar"<br />
</haskell><br />
|-<br />
| combining many strings<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:concat concat]<br />
| <haskell><br />
concat ["foo", "bar", "baz"] --> "foobarbaz"<br />
</haskell><br />
|}<br />
<br />
= Accessing substrings =<br />
<br />
{| class="wikitable"<br />
|-<br />
! Problem<br />
! Solution<br />
! Examples<br />
|-<br />
| accessing the first character<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:head head]<br />
|<haskell><br />
head "foo bar baz" --> 'f'<br />
</haskell><br />
|-<br />
| accessing the last character<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v%3Alast last]<br />
|<haskell><br />
last "foo bar baz" --> 'z'<br />
</haskell><br />
|-<br />
| accessing the character at a given index<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v%3A!! (!!)]<br />
|<haskell><br />
"foo bar baz" !! 4 --> 'b'<br />
</haskell><br />
|-<br />
| accessing the first <code>n</code> characters<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:take take]<br />
| <haskell><br />
take 3 "foo bar baz" --> "foo"<br />
</haskell><br />
|-<br />
| accessing the last <code>n</code> characters<br />
| TODO<br />
| reverse . take 3 . reverse $ "foobar" --> "bar"<br />
|-<br />
| accessing the <code>n</code> characters starting from index <code>m</code><br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:drop drop], [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:take take]<br />
| <haskell><br />
take 4 $ drop 2 "foo bar baz" --> "o ba"<br />
</haskell><br />
|}<br />
<br />
= Splitting strings =<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! Problem<br />
! Solution<br />
! Examples<br />
|-<br />
| splitting a string into a list of words<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:words words]<br />
| <haskell>words "foo bar\t baz\n" --> ["foo","bar","baz"]<br />
</haskell><br />
|-<br />
| splitting a string into two parts<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v%3AsplitAt splitAt]<br />
| <haskell>splitAt 3 "foo bar baz" --> ("foo"," bar baz")<br />
</haskell><br />
|}<br />
<br />
= Multiline strings =<br />
<haskell><br />
"foo\<br />
\bar" --> "foobar"<br />
</haskell><br />
<br />
= Converting between characters and values =<br />
<br />
{| class="wikitable"<br />
|-<br />
! Problem<br />
! Solution<br />
! Examples<br />
|-<br />
| converting a character to a numeric value<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Data-Char.html#v:ord ord]<br />
|<haskell><br />
import Char<br />
ord 'A' --> 65<br />
</haskell><br />
|-<br />
| converting a numeric value to a character<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Data-Char.html#v%3Achr chr]<br />
| <haskell><br />
import Char<br />
chr 99 --> 'c'<br />
</haskell><br />
|}<br />
<br />
= Reversing a string by words or characters =<br />
<br />
{| class="wikitable"<br />
|-<br />
! Problem<br />
! Solution<br />
! Examples<br />
|-<br />
| reversing a string by characters<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:reverse reverse]<br />
|<haskell><br />
reverse "foo bar baz" --> "zab rab oof"<br />
</haskell><br />
|-<br />
| reversing a string by words<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v%3Awords words], [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:reverse reverse], [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v%3Aunwords unwords]<br />
| <haskell><br />
unwords $ reverse $ words "foo bar baz" --> "baz bar foo"<br />
</haskell><br />
|-<br />
| reversing a string by characters by words<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v%3Awords words], [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:reverse reverse], [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:map map], [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v%3Aunwords unwords]<br />
| <haskell><br />
unwords $ map reverse $ words "foo bar baz" --> "oof rab zab"<br />
</haskell><br />
|}<br />
<br />
= Converting case =<br />
<br />
{| class="wikitable"<br />
|-<br />
! Problem<br />
! Solution<br />
! Examples<br />
|-<br />
| converting a character to upper-case<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Data-Char.html#v%3AtoUpper toUpper]<br />
|<haskell><br />
import Char<br />
toUpper 'a' --> "A"<br />
</haskell><br />
|-<br />
| converting a character to lower-case<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Data-Char.html#v%3AtoLower toLower]<br />
| <haskell><br />
import Char<br />
toLower 'A' --> "a"<br />
</haskell><br />
|-<br />
| converting a string to upper-case<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Data-Char.html#v%3AtoUpper toUpper], [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:map map]<br />
|<haskell><br />
import Char<br />
map toUpper "Foo Bar" --> "FOO BAR"<br />
</haskell><br />
|-<br />
| converting a string to lower-case<br />
| [http://haskell.org/ghc/docs/latest/html/libraries/base/Data-Char.html#v%3AtoLower toLower], [http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:map map]<br />
| <haskell><br />
import Char<br />
map toLower "Foo Bar" --> "foo bar"<br />
</haskell><br />
|}<br />
<br />
=Interpolation =<br />
<br />
TODO<br />
<br />
= Performance =<br />
<br />
For high performance requirements (where you would typically consider<br />
C), consider using [http://hackage.haskell.org/packages/archive/bytestring/latest/doc/html/Data-ByteString.html Data.ByteString].<br />
<br />
= Unicode =<br />
<br />
TODO</div>JohannesAhlmannhttps://wiki.haskell.org/Talk:Blow_your_mindTalk:Blow your mind2009-03-04T17:02:40Z<p>JohannesAhlmann: </p>
<hr />
<div><br />
==Name?==<br />
<br />
Is there a better name for this page? &mdash;[[User:Ashley Y|Ashley Y]] 00:55, 2 March 2006 (UTC)<br />
<br />
i completely agree, the name pretty much sucks. but what i really wanted, was to compile a collection of "idioms" that would enlarge the readers perception of what is possible in Haskell and how to go about it. so, i'll have to find a name that reflects this plan. &mdash;--[[User:JohannesAhlmann|J. Ahlmann]] 14:13, 2 March 2006 (UTC)</div>JohannesAhlmannhttps://wiki.haskell.org/User:JohannesAhlmannUser:JohannesAhlmann2009-03-04T16:57:50Z<p>JohannesAhlmann: </p>
<hr />
<div>In the IRC channel I go by the nick of "jethr0".<br />
<br />
So far i've toyed around with many Haskell concepts, including the obligatory [http://haskell.org/tmrwiki/JohannesAhlmann Ray Tracer], some Genetic Algorithms and Neural Networks.<br />
<br />
I took part in the [http://www.icfpcontest.org/ 2007 ICFP contest] in the team [http://homes.esat.kuleuven.be/~cpoucet/icfp2007.html Lazy Bottoms] placing 56th of 859 teams and although I didn't contribute by far as much as I would have wanted, it still was a lot of fun and definitely worth the coding marathon.<br />
<br />
Pages I've written/contributed to:<br />
* [[BlowYourMindIdioms]]<br />
* [http://web.archive.org/web/20061011050035/http://www.haskell.org/hawiki/TemplateHaskellTutorial Template Haskell Tutorial], unfortunately I was too lazy to port the tutorial to the new wiki, so it's now [http://archive.org archive.org]'ed.<br />
<br />
<br />
<br />
I also like the format of the Ruby/[[Haskell_Quiz|Haskell Quiz]] and I try to contribute solutions to interesting problems whenever I find the time. Some of these might be educational and some just plain ugly, but I always find it quite fulfilling to tackle these:<br />
* [[Haskell_Quiz/Phone_Number_Words/Solution_Jethr0|Phone Number Words]]<br />
* [[Haskell_Quiz/Index_and_Query/Solution_Jethr0|Index and Query]]<br />
* [[Haskell_Quiz/Constraint_Processing/Solution_Jethr0|Constraint Processing]]<br />
* [[Haskell_Quiz/Animal_Quiz/Solution_Jethr0|Animal Quiz]]<br />
* [[Haskell_Quiz/DayRange/Solution_Jethr0|Day Range]]<br />
* [[Haskell_Quiz/Verbal_Arithmetic/Solution_Jethr0|Verbal Arithmetic]]<br />
* [[Haskell_Quiz/Chip_Eight/Solution_Jethr0|Chip Eight]]<br />
* [[Haskell_Quiz/Sokoban/Solution_Jethr0|Sokoban]]</div>JohannesAhlmannhttps://wiki.haskell.org/Talk:IRC_channel/Phase_2Talk:IRC channel/Phase 22009-02-02T09:51:42Z<p>JohannesAhlmann: </p>
<hr />
<div>I completely agree with the perception that the channel has become less newbie-friendly during the last two years simply due to higher attendance. <br />
<br />
I am not sure how well people will be able to participate in two or more channels at the same time, but it's definitely worth trying out in order to keep the barrier of entry to haskell as low as possible. We should just try not to upset the delicate current state of helpfullness, sillyness and creativity of the channel by making overly drastic changes.<br />
<br />
As for lambdabot, I would propose a restricted instruction set for the #haskell channel in order to eliminate noisy (yet fun) commands and have a platform for straight-to-the-point answers. I.e. a restriction of commands to @eval @source @index @hoogle and a few more.<br />
<br />
Alternatively, the use of other commands could be limited to 1 per 5 minutes or so. OR, we rely on the #haskell users to to take their overly silly/verbose lambdabot requests to one of the other channels...<br />
<br />
What do you think?<br />
<br />
--[[User:JohannesAhlmann|Johannes Ahlmann]] 09:51, 2 February 2009 (UTC)</div>JohannesAhlmannhttps://wiki.haskell.org/Template_HaskellTemplate Haskell2008-08-08T08:26:22Z<p>JohannesAhlmann: updated haskell tutorial link</p>
<hr />
<div>'''[http://www.haskell.org/th/ Template Haskell]''' is a [[GHC]] extension to Haskell that adds compile-time metaprogramming facilities. The original design can be found here: http://research.microsoft.com/~simonpj/papers/meta-haskell/ . It is [http://haskell.cs.yale.edu/ghc/docs/6.2/html/users_guide/template-haskell.html included] in GHC version 6. If you start working with Template Haskell you'll probably want to join the [http://haskell.org/mailman/listinfo/template-haskell Template Haskell mailing list].<br />
<br />
This page hopes to be a more central and organized repository of TH related things. However, at this point most things should probably go to/through the mailing list first.<br />
<br />
----<br />
=What is Template Haskell?=<br />
Template Haskell is an extension to Haskell 98 that allows you to do type-safe compile-time meta-programming, with Haskell both as the manipulating language and the language being manipulated. <br />
<br />
Intuitively Template Haskell provides new language features that allow us to convert back and forth between concrete syntax, i.e. what you would type when you write normal Haskell code, and abstract syntax trees. These abstract syntax trees are represented using Haskell datatypes and, at compile time, they can be manipulated by Haskell code. This allows you to reify (convert from concrete syntax to an abstract syntax tree) some code, transform it and splice it back in (convert back again), or even to produce completely new code and splice that in, while the compiler is compiling your module. <br />
<br />
There is a [http://haskell.org/mailman/listinfo/template-haskell mailing list specifically for Template Haskell]. It's worth joining if you start to use TH.<br />
<br />
= Template Haskell specification =<br />
<br />
Template Haskell is only documented rather informally at the moment. Here are the main resources:<br />
<br />
* [http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html The user manual section]<br />
* [http://research.microsoft.com/~simonpj/papers/meta-haskell/ The original Template Haskell paper]<br />
* [http://research.microsoft.com/~simonpj/tmp/notes2.ps Notes on Template Haskell version 2], which describes changes since the original paper.<br />
* [http://www.haskell.org/ghc/docs/latest/html/libraries/template-haskell/Language-Haskell-TH.html The Template Haskell API]<br />
<br />
= Template Haskell tutorials and papers =<br />
<br />
* Bulat's tutorials:<br />
** http://www.haskell.org/bz/thdoc.htm<br />
** http://www.haskell.org/bz/th3.htm<br />
: One reader said "These docs are *brilliant* ! Exactly what I need to get an understanding of TH."<br />
<br />
* Mark Snyder's Template Haskell chapter on the Software Generation and Configuration Report<br />
** http://nix.cs.uu.nl/dist/courses/sgc-report-unstable-latest/manual/chunk-chapter/templatehaskell.html<br />
<br />
* jethr0's Template Haskell tutorial: ** http://www.haskell.org/tmrwiki/TemplateHaskell<br />
<br />
* Papers about Template Haskell<br />
** Template metaprogramming for Haskell, by Tim Sheard and Simon Peyton Jones, May 2002. [http://haskell.org/th/papers/meta-haskell.ps [A4 ps]] [http://haskell.org/th/papers/meta-haskell.bib [bib]]<br />
** Template Haskell: A Report From The Field, by Ian Lynagh, May 2003.[http://haskell.org/th/papers/Template_Haskell-A_Report_From_The_Field.ps [A4 ps]] [http://haskell.org/th/papers/Template_Haskell-A_Report_From_The_Field.bib [bib]]<br />
** Unrolling and Simplifying Expressions with Template Haskell, by Ian Lynagh, May 2003.[http://haskell.org/th/papers/Unrolling_and_Simplifying_Expressions_with_Template_Haskell.ps [A4 ps]][http://haskell.org/th/papers/Unrolling_and_Simplifying_Expressions_with_Template_Haskell.bib [bib]]<br />
** Automatic skeletons in Template Haskell, by Kevin Hammond, Jost Berthold and Rita Loogen, June 2003. [http://haskell.org/th/papers/hlpp.ps [A4 ps]][http://haskell.org/th/papers/hlpp.bib [bib]]<br />
** Optimising Embedded DSLs using Template Haskell, by Sean Seefried, Manuel Chakravarty, Gabriele Keller, March 2004. [http://haskell.org/th/papers/th-pan.ps [A4 ps]] [http://haskell.org/th/papers/th-pan.bib [bib]]<br />
** Typing Template Haskell: Soft Types, by Ian Lynagh, August 2004.[http://haskell.org/th/papers/Typing_Template_Haskell__Soft_Types.ps [A4 ps]][http://haskell.org/th/papers/Typing_Template_Haskell__Soft_Types.bib [bib]]<br />
<br />
<br />
<br />
= Other useful resources =<br />
<br />
* [http://www.haskell.org/th/ The old Template Haskell web page]. Would someone feel like moving this material into the HaskellWiki?<br />
* Old and probably not too useful for most but maybe... http://www.cse.unsw.edu.au/~chak/haskell/ghc/comm/exts/th.html<br />
*[http://web.comlab.ox.ac.uk/oucl/work/ian.lynagh/Fraskell/ Fraskell documentation] & explanation of how Template Haskell is used to vastly speed it up.<br />
Feel free to update our Wikipedia entry<br />
http://en.wikipedia.org/wiki/Template_Haskell<br />
<br />
= Projects =<br />
<br />
What are you doing/planning to do/have done with Template Haskell?<br />
<br />
* I have written a primitive (untyped) binding to the Objective-C runtime system on Mac OS X. It needs just TH, no "stub files" are created, no seperate utilities are required. Initial snapshot is at http://www.kfunigraz.ac.at/imawww/thaller/wolfgang/HOC020103.tar.bz2 -- WolfgangThaller<br />
<br />
* I am writing Template Greencard - a reimplementation of GreenCard using TH. Many bits work out really nicely. A few bits didn't work so nicely - once I get some time to think, I'll try to persuade the TH folk to make some changes to fix some of these. -- AlastairReid<br />
<br />
* I'm writing Hacanon - a framework for automatic generation of C++ bindings. Read "automated Template Greencard for C++" (-: Darcs repo: http://www.ScannedInAvian.org/repos/hacanon - You'll need gccxml (http://www.gccxml.org/) to compile the exmples. - 27 Dec Lemmih.<br />
<br />
* Following other FFI tools developers, I see some future for Template HSFFIG, especially when it comes to autogenerate peek and poke methods for structures defined in C; may be useful for implementation of certain network protocols such as X11 where layout of messages is provided as C structure/union declaration. - 16 Dec 2005 DimitryGolubovsky<br />
<br />
* I am using Template Haskell as a mechanism to get parsed, typechecked code into an Ajax based Haskell Equational Reasoning tool [[Haskell Equational Reasoning Assistant]], as well as simplify the specification of equational relationships between pieces of code. There was a quicktime movie of the tool being used on http://www.gill-warbington.com/home/andy/share/hera1.html - AndyGill <br />
<br />
* I am working on functional metaprogramming techniques to enhance programming reliability and productivity, by reusing much of the existing compiler technology. Template Haskell is especially interesting for me because it permits to check size information of structures by the compiler, provided this information is available at compile time. This approach is especially appropriate for hardware designs, where the structures are fixed before the circuit starts operating. See our metaprogramming web page at http://www.infosun.fmi.uni-passau.de/cl/metaprog/ -- ChristophHerrmann(http://www.cs.st-and.ac.uk/~ch)<br />
<br />
* I am using Template Haskell to do type safe database access. I initially [http://www.nabble.com/Using-Template-Haskell-to-make-type-safe-database-access-td17027286.html proposed this on haskell-cafe]. I connect to the database at compile-time and let the database do SQL parsing and type inference. The result from parsing and type inference is used to build a type safe database query which can executed at run-time. [[MetaHDBC | You can find the project page here]] -- [mailto:mads_lindstroem@yahoo.dk Mads LindstrÃ¸m]<br />
<br />
= Utilities =<br />
<br />
Helper functions, debugging functions, or more involved code e.g. a monadic fold algebra for THSyntax.<br />
<br />
* http://www.haskell.org/pipermail/template-haskell/2003-September/000176.html<br />
<br />
= Known Bugs =<br />
<br />
Take a look at the [http://cvs.haskell.org/trac/ghc/query?status=new&status=assigned&status=reopened&component=Template+Haskell&order=priority open bugs against Template Haskell] on the GHC bug tracker.<br />
<br />
The bug you're most likely to run into is [http://cvs.haskell.org/trac/ghc/ticket/651 Template Haskell does not work with profiling].<br />
<br />
= Wish list =<br />
<br />
Things that Ian Lynagh (Igloo) mentioned in his paper ''Template Haskell: A Report From The Field'' in May 2003 (available [http://www.haskell.org/th/papers.html here]), by section:<br />
<br />
* Section 2 (curses)<br />
** The ability to splice names (into "foreign import" declarations, in particular)<br />
** The ability to add things to the export list from a splice(?)<br />
** The ability to use things defined at the toplevel of a module from splices in that same module (would require multi-stage compilation, as opposed to the current approach of expanding splices during typechecking)<br />
<br />
* Section 3 (deriving instances of classes)<br />
** <strike>First-class reification</strike> (the <hask>reify</hask> function)<br />
** A way to discover whether a data constructor was defined infix or prefix (which is necessary to derive instances for <hask>Read</hask> and <hask>Show</hask> as outlined in [http://www.haskell.org/onlinereport/derived.html The Haskell 98 Report: Specification of Derived Instances]) (if there is a way, [http://www-users.cs.york.ac.uk/~ndm/derive/ Derive] seems ignorant of it)<br />
** Type/context splicing (in <hask>instance</hask> headers in particular)<br />
<br />
* Section 4 (printf)<br />
** He says something to the effect that a pattern-matching form of the quotation brackets would be cool if it was expressive enough to be useful, but that this would be hard. (Don't expect this anytime soon.)<br />
<br />
* Section 5 (fraskell)<br />
** Type information for quoted code (so that simplification can be done safely even with overloaded operations, like, oh, <hask>(+)</hask>)<br />
<br />
* Section 6 (pan)<br />
** Type info again, and strictnes info too (this one seems a bit pie-in-the-sky...)<br />
<br />
(Please leave the implemented ones here, but crossed off.)<br />
<br />
Any other features that may be nice, and TH projects you'd want to see.<br />
<br />
* A TH tutorial (mainly a distillation and update of ''Template Meta-programming in Haskell'' at this point)<br />
* Write Haddock documentation for the Template Haskell library.<br />
* Make `reify` on a class return a list of the instances of that class (http://www.haskell.org/pipermail/template-haskell/2005-December/000503.html). (See also [http://hackage.haskell.org/trac/ghc/ticket/1577 GHC ticket #1577].)<br />
* A set of simple examples on this wiki page<br />
* A TH T-shirt with new logo to wear at conferences<br />
* (Long-term) Unify Language.Haskell.Syntax with Language.Haskell.TH.Syntax so there's just one way to do things<br />
<br />
---------------<br />
<br />
= Tips and Tricks =<br />
<br />
== What to do when you can't splice that there ==<br />
<br />
When you try to splice something into the middle of a template and find that you just can't, instead of getting frustrated about it, why not use the template to see what it would look like in longhand? <br />
<br />
First, an excerpt from a module of my own. I, by the way, am SamB.<br />
<haskell><br />
{-# OPTIONS_GHC -fglasgow-exts -fth #-}<br />
<br />
module MMixMemory where<br />
<br />
import Data.Int<br />
import Data.Word<br />
<br />
class (Integral int, Integral word)<br />
=> SignConversion int word | int -> word, word -> int where<br />
<br />
toSigned :: word -> int<br />
toSigned = fromIntegral<br />
toUnsigned :: int -> word<br />
toUnsigned = fromIntegral<br />
<br />
</haskell><br />
<br />
Say I want to find out what I need to do to splice in the types for an instance declaration for the SignConversion class, so that I can declare instances for Int8 with Word8 through Int64 with Word64. So, I start up good-ol' GHCi and do the following:<br />
<br />
<haskell><br />
$ ghci -fth -fglasgow-exts<br />
Prelude> :l MMixMemory<br />
*MMixMemory> :m +Language.Haskell.TH.Syntax<br />
*MMixMemory Language.Haskell.TH.Syntax> runQ [d| instance SignConversion Int Word where |] >>= print<br />
[InstanceD [] (AppT (AppT (ConT MMixMemory.SignConversion) (ConT GHC.Base.Int)) (ConT GHC.Word.Word)) []]<br />
</haskell><br />
<br />
== Why does <tt>runQ</tt> crash if I try to reify something? ==<br />
<br />
This program will fail with an error message when you run it:<br />
<haskell><br />
main = do info <- runQ (reify (mkName "Bool"))<br />
putStrLn (pprint info)<br />
</haskell><br />
Reason: <tt>reify</tt> consults the type environment, and that is not available at run-time. The type of <tt>reify</tt> is <br />
<haskell><br />
reify :: Quasi m => Q a -> m a<br />
</haskell><br />
The IO monad is a poor-man's instance of <tt>Quasi</tt>; it can allocate unique names and gather error messages, but it can't do <tt>reify</tt>. This error should really be caught statically.<br />
<br />
Here's an [http://www.haskell.org/pipermail/glasgow-haskell-users/2006-August/010844.html email thread with more details].<br />
<br />
-----------------<br />
= Examples =<br />
== Select from a tuple ==<br />
<br />
An example to select an element from a tuple of arbitrary size. Taken from [http://www.haskell.org/th/papers/meta-haskell.ps this paper].<br />
<br />
Use like so:<br />
<br />
> $(sel 2 3) ('a','b','c')<br />
'b'<br />
> $(sel 3 4) ('a','b','c','d')<br />
'c'<br />
<br />
<br />
<haskell><br />
sel :: Int -> Int -> ExpQ<br />
sel i n = [| \x -> $(caseE [| x |] [alt]) |]<br />
where alt :: MatchQ<br />
alt = match pat (normalB rhs) []<br />
<br />
pat :: Pat<br />
pat = tupP (map varP as)<br />
<br />
rhs :: ExpQ<br />
rhs = varE(as !! (i -1)) -- !! is 0 based<br />
<br />
as :: [String]<br />
as = ["a" ++ show i | i <- [1..n] ]<br />
</haskell><br />
<br />
Alternately:<br />
<br />
<haskell><br />
sel' i n = lamE [pat] rhs<br />
where pat = tupP (map varP as)<br />
rhs = varE (as !! (i - 1))<br />
as = [ "a" ++ show j | j <- [1..n] ]<br />
</haskell><br />
<br />
== Convert the first n elements of a list to a tuple ==<br />
<br />
This example creates a tuple by extracting elemnts from a list. Taken from<br />
[http://www.xoltar.org/2003/aug/13/templateHaskellTupleSample.html www.xoltar.org]<br />
<br />
Use like so:<br />
<br />
> $(tuple 3) [1,2,3,4,5]<br />
(1,2,3)<br />
> $(tuple 2) [1,2]<br />
(1,2)<br />
<br />
<haskell><br />
tuple :: Int -> ExpQ<br />
tuple n = [|\list -> $(tupE (exprs [|list|])) |]<br />
where<br />
exprs list = [infixE (Just (list))<br />
(varE "!!")<br />
(Just (litE $ integerL (toInteger num)))<br />
| num <- [0..(n - 1)]]<br />
</haskell><br />
<br />
== Printf ==<br />
This example taken from: http://haskell.cs.yale.edu/ghc/docs/6.0/html/users_guide/template-haskell.html<br />
<br />
Build it using a command similar to one of the following (depending on your environment):<br />
<br />
ghc/compiler/stage3/ghc-inplace --make -fglasgow-exts -package haskell-src main.hs -o main.exe<br />
ghc --make -fth Main.hs -o printfTest<br />
<br />
Main.hs:<br />
<br />
<haskell><br />
module Main where<br />
<br />
-- Import our template "pr"<br />
import Printf ( pr )<br />
<br />
-- The splice operator $ takes the Haskell source code<br />
-- generated at compile time by "pr" and splices it into<br />
-- the argument of "putStrLn".<br />
main = putStrLn ( $(pr "Hello") )<br />
</haskell><br />
<br />
Printf.hs:<br />
<br />
<haskell><br />
module Printf where<br />
<br />
-- Skeletal printf from the paper.<br />
-- It needs to be in a separate module to the one where<br />
-- you intend to use it.<br />
<br />
-- Import some Template Haskell syntax<br />
import Language.Haskell.THSyntax<br />
<br />
-- Describe a format string<br />
data Format = D | S | L String<br />
<br />
-- Parse a format string. This is left largely to you<br />
-- as we are here interested in building our first ever<br />
-- Template Haskell program and not in building printf.<br />
parse :: String -> [Format]<br />
parse s = [ L s ]<br />
<br />
-- Generate Haskell source code from a parsed representation<br />
-- of the format string. This code will be spliced into<br />
-- the module which calls "pr", at compile time.<br />
gen :: [Format] -> ExpQ<br />
gen [D] = [| \n -> show n |]<br />
gen [S] = [| \s -> s |]<br />
gen [L s] = stringE s<br />
<br />
-- Here we generate the Haskell code for the splice<br />
-- from an input format string.<br />
pr :: String -> ExpQ<br />
pr s = gen (parse s)<br />
</haskell><br />
<br />
== Handling Options with Templates ==<br />
A common idiom for treating a set of options, e.g. from GetOpt, is to define a datatype with all the flags and using a list over this datatype:<br />
<br />
<haskell><br />
data Options = B1 | B2 | V Integer<br />
<br />
options = [B1, V 3]<br />
</haskell><br />
<br />
While it's simple testing if a Boolean flag is set (simply use "elem"), it's harder to check if an option with an argument is set. It's even more tedious writing helper-functions to obtain the value from such an option since you have to explicitely "un-V" each. Here, Template Haskell can be (ab)used to reduce this a bit. The following example provides the module "OptionsTH" which can be reused regardless of the constructors in "Options". Let's start with showing how we'd like to be able to program. Notice that the resulting lists need some more treatment e.g. through "foldl".<br />
<br />
Options.hs:<br />
<br />
<haskell><br />
module Main where<br />
<br />
import OptionsTH<br />
import Language.Haskell.THSyntax<br />
<br />
data Options = B1 | B2 | V Int | S String deriving (Eq, Read, Show)<br />
<br />
options = [B1, V 3]<br />
<br />
main = do<br />
print foo -- test if B1 set: [True,False]<br />
print bar -- test if V present, w/o value: [False,True]<br />
print baz -- get value of V if available: [Nothing,Just 3]<br />
<br />
foo :: [Bool]<br />
-- Query constructor B1 which takes no arguments<br />
foo = map $(getopt (THNoArg (mkArg "B1" 0))) options<br />
<br />
bar :: [Bool]<br />
-- V is a unary constructor. Let mkArg generate the required<br />
-- wildcard-pattern "V _".<br />
bar = map $(getopt (THNoArg (mkArg "V" 1))) options<br />
<br />
-- Can't use a wildcard here!<br />
baz :: [(Maybe Int)]<br />
baz = map $(getopt (THArg (conP "V" [varP "x"]))) options<br />
</haskell><br />
<br />
OptionsTH.hs<br />
<br />
<haskell><br />
module OptionsTH where<br />
<br />
import Language.Haskell.THSyntax<br />
<br />
-- datatype for querying options:<br />
-- NoArg: Not interested in value (also applies to Boolean flags)<br />
-- Arg: Grep value of unary(!) constructor<br />
data Args = THNoArg Pat | THArg Pat<br />
<br />
getopt :: Args -> ExpQ<br />
getopt (THNoArg pat) = lamE [varP "y"] (caseE (varE "y") [cons0, cons1])<br />
where<br />
cons0 = match pat (normalB [| True |]) []<br />
cons1 = match wildP (normalB [| False |]) []<br />
<br />
-- bind "var" for later use!<br />
getopt (THArg pat@(ConP _ [VarP var])) = lamE [varP "y"] (caseE (varE "y") [cons0, cons1])<br />
where<br />
cons0 = match pat (normalB (appE [|Just|] (varE var))) []<br />
cons1 = match wildP (normalB [|Nothing|]) []<br />
<br />
mkArg :: String -> Int -> Pat<br />
mkArg k c = conP k (replicate c wildP)<br />
</haskell><br />
<br />
While the example might look contrived for the Boolean options which could have been tested much easier, it shows how both types of arguments can be treated in a similar way.<br />
<br />
=== Limitations ===<br />
<tt>getopt (THArg pat)</tt> is only able to treat unary constructors. See the pattern-binding: It matches exactly a single VarP.<br />
<br />
=== Improvements ===<br />
The following reduces things even a bit more, though I still don't know if I like it. It only works since <tt>c</tt> is either 0 or 1.<br />
<br />
<haskell><br />
mkArg k c = conP k (replicate c (varP "x"))<br />
<br />
baz = map $(getopt (THArg (mkArg "V" 1)))<br />
</haskell><br />
-- VolkerStolz<br />
<br />
== Generic constructor for records ==<br />
<br />
I have a large number of record types like this, of different length:<br />
<br />
<haskell><br />
data PGD = PGD {<br />
pgdXUnitBase :: !Word8,<br />
pgdYUnitBase :: !Word8,<br />
pgdXLUnitsperUnitBase :: !Word16<br />
}<br />
</haskell><br />
<br />
Currently I use GHC's Binary module to read them from files; it can handle<br />
types like <tt>(Word8, (Word8, Word16))</tt>, but there was no easy way to generate<br />
the correct amount of "uncurry" calls for automatically grabbing each element.<br />
<br />
With Template Haskell, the instance declarations are now written as such:<br />
<br />
<haskell><br />
instance Binary PGD where<br />
get bh = do a <- get bh ; return $ $(constrRecord PGD) a<br />
</haskell><br />
<br />
Here the trick lies in constrRecord, which is defined as:<br />
<br />
<haskell><br />
constrRecord x = reify exp where<br />
reify = \(Just r) -> appE r $ conE $ last args<br />
exp = foldl (dot) uncur $ replicate terms uncur<br />
terms = ((length args) `div` 2) - 2<br />
dot x y = (Just $ infixE x (varE ".") y)<br />
uncur = (Just [|uncurry|])<br />
args = words . show $ typeOf x<br />
</haskell><br />
<br />
-- AutrijusTang<br />
<br />
==[[Template haskell/Instance deriving example|Instance deriving example]]==<br />
An example using a 'deriving function' to generate a method instance <br />
per constructor of a type. The deriving function provides the body of the<br />
method.<br />
<br />
Note that this example assumes that the functions of the class take a parameter that is the same type as instance is parameterized with. <br />
<br />
The message [http://www.haskell.org/pipermail/template-haskell/2006-August/000581.html email message] contains the full source ([http://www.iist.unu.edu/~vs/haskell/TH_render.hs extracted file]).<br />
<br />
[[Category:Language extensions]]</div>JohannesAhlmannhttps://wiki.haskell.org/Template_HaskellTemplate Haskell2008-08-08T08:24:36Z<p>JohannesAhlmann: updated haskell tutorial link</p>
<hr />
<div>'''[http://www.haskell.org/th/ Template Haskell]''' is a [[GHC]] extension to Haskell that adds compile-time metaprogramming facilities. The original design can be found here: http://research.microsoft.com/~simonpj/papers/meta-haskell/ . It is [http://haskell.cs.yale.edu/ghc/docs/6.2/html/users_guide/template-haskell.html included] in GHC version 6. If you start working with Template Haskell you'll probably want to join the [http://haskell.org/mailman/listinfo/template-haskell Template Haskell mailing list].<br />
<br />
This page hopes to be a more central and organized repository of TH related things. However, at this point most things should probably go to/through the mailing list first.<br />
<br />
----<br />
=What is Template Haskell?=<br />
Template Haskell is an extension to Haskell 98 that allows you to do type-safe compile-time meta-programming, with Haskell both as the manipulating language and the language being manipulated. <br />
<br />
Intuitively Template Haskell provides new language features that allow us to convert back and forth between concrete syntax, i.e. what you would type when you write normal Haskell code, and abstract syntax trees. These abstract syntax trees are represented using Haskell datatypes and, at compile time, they can be manipulated by Haskell code. This allows you to reify (convert from concrete syntax to an abstract syntax tree) some code, transform it and splice it back in (convert back again), or even to produce completely new code and splice that in, while the compiler is compiling your module. <br />
<br />
There is a [http://haskell.org/mailman/listinfo/template-haskell mailing list specifically for Template Haskell]. It's worth joining if you start to use TH.<br />
<br />
= Template Haskell specification =<br />
<br />
Template Haskell is only documented rather informally at the moment. Here are the main resources:<br />
<br />
* [http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html The user manual section]<br />
* [http://research.microsoft.com/~simonpj/papers/meta-haskell/ The original Template Haskell paper]<br />
* [http://research.microsoft.com/~simonpj/tmp/notes2.ps Notes on Template Haskell version 2], which describes changes since the original paper.<br />
* [http://www.haskell.org/ghc/docs/latest/html/libraries/template-haskell/Language-Haskell-TH.html The Template Haskell API]<br />
<br />
= Template Haskell tutorials and papers =<br />
<br />
* Bulat's tutorials:<br />
** http://www.haskell.org/bz/thdoc.htm<br />
** http://www.haskell.org/bz/th3.htm<br />
: One reader said "These docs are *brilliant* ! Exactly what I need to get an understanding of TH."<br />
<br />
* Mark Snyder's Template Haskell chapter on the Software Generation and Configuration Report<br />
** http://nix.cs.uu.nl/dist/courses/sgc-report-unstable-latest/manual/chunk-chapter/templatehaskell.html<br />
<br />
* jethr0's Template Haskell tutorial: [http://www.haskell.org/tmrwiki/TemplateHaskell]<br />
<br />
* Papers about Template Haskell<br />
** Template metaprogramming for Haskell, by Tim Sheard and Simon Peyton Jones, May 2002. [http://haskell.org/th/papers/meta-haskell.ps [A4 ps]] [http://haskell.org/th/papers/meta-haskell.bib [bib]]<br />
** Template Haskell: A Report From The Field, by Ian Lynagh, May 2003.[http://haskell.org/th/papers/Template_Haskell-A_Report_From_The_Field.ps [A4 ps]] [http://haskell.org/th/papers/Template_Haskell-A_Report_From_The_Field.bib [bib]]<br />
** Unrolling and Simplifying Expressions with Template Haskell, by Ian Lynagh, May 2003.[http://haskell.org/th/papers/Unrolling_and_Simplifying_Expressions_with_Template_Haskell.ps [A4 ps]][http://haskell.org/th/papers/Unrolling_and_Simplifying_Expressions_with_Template_Haskell.bib [bib]]<br />
** Automatic skeletons in Template Haskell, by Kevin Hammond, Jost Berthold and Rita Loogen, June 2003. [http://haskell.org/th/papers/hlpp.ps [A4 ps]][http://haskell.org/th/papers/hlpp.bib [bib]]<br />
** Optimising Embedded DSLs using Template Haskell, by Sean Seefried, Manuel Chakravarty, Gabriele Keller, March 2004. [http://haskell.org/th/papers/th-pan.ps [A4 ps]] [http://haskell.org/th/papers/th-pan.bib [bib]]<br />
** Typing Template Haskell: Soft Types, by Ian Lynagh, August 2004.[http://haskell.org/th/papers/Typing_Template_Haskell__Soft_Types.ps [A4 ps]][http://haskell.org/th/papers/Typing_Template_Haskell__Soft_Types.bib [bib]]<br />
<br />
<br />
<br />
= Other useful resources =<br />
<br />
* [http://www.haskell.org/th/ The old Template Haskell web page]. Would someone feel like moving this material into the HaskellWiki?<br />
* Old and probably not too useful for most but maybe... http://www.cse.unsw.edu.au/~chak/haskell/ghc/comm/exts/th.html<br />
*[http://web.comlab.ox.ac.uk/oucl/work/ian.lynagh/Fraskell/ Fraskell documentation] & explanation of how Template Haskell is used to vastly speed it up.<br />
Feel free to update our Wikipedia entry<br />
http://en.wikipedia.org/wiki/Template_Haskell<br />
<br />
= Projects =<br />
<br />
What are you doing/planning to do/have done with Template Haskell?<br />
<br />
* I have written a primitive (untyped) binding to the Objective-C runtime system on Mac OS X. It needs just TH, no "stub files" are created, no seperate utilities are required. Initial snapshot is at http://www.kfunigraz.ac.at/imawww/thaller/wolfgang/HOC020103.tar.bz2 -- WolfgangThaller<br />
<br />
* I am writing Template Greencard - a reimplementation of GreenCard using TH. Many bits work out really nicely. A few bits didn't work so nicely - once I get some time to think, I'll try to persuade the TH folk to make some changes to fix some of these. -- AlastairReid<br />
<br />
* I'm writing Hacanon - a framework for automatic generation of C++ bindings. Read "automated Template Greencard for C++" (-: Darcs repo: http://www.ScannedInAvian.org/repos/hacanon - You'll need gccxml (http://www.gccxml.org/) to compile the exmples. - 27 Dec Lemmih.<br />
<br />
* Following other FFI tools developers, I see some future for Template HSFFIG, especially when it comes to autogenerate peek and poke methods for structures defined in C; may be useful for implementation of certain network protocols such as X11 where layout of messages is provided as C structure/union declaration. - 16 Dec 2005 DimitryGolubovsky<br />
<br />
* I am using Template Haskell as a mechanism to get parsed, typechecked code into an Ajax based Haskell Equational Reasoning tool [[Haskell Equational Reasoning Assistant]], as well as simplify the specification of equational relationships between pieces of code. There was a quicktime movie of the tool being used on http://www.gill-warbington.com/home/andy/share/hera1.html - AndyGill <br />
<br />
* I am working on functional metaprogramming techniques to enhance programming reliability and productivity, by reusing much of the existing compiler technology. Template Haskell is especially interesting for me because it permits to check size information of structures by the compiler, provided this information is available at compile time. This approach is especially appropriate for hardware designs, where the structures are fixed before the circuit starts operating. See our metaprogramming web page at http://www.infosun.fmi.uni-passau.de/cl/metaprog/ -- ChristophHerrmann(http://www.cs.st-and.ac.uk/~ch)<br />
<br />
* I am using Template Haskell to do type safe database access. I initially [http://www.nabble.com/Using-Template-Haskell-to-make-type-safe-database-access-td17027286.html proposed this on haskell-cafe]. I connect to the database at compile-time and let the database do SQL parsing and type inference. The result from parsing and type inference is used to build a type safe database query which can executed at run-time. [[MetaHDBC | You can find the project page here]] -- [mailto:mads_lindstroem@yahoo.dk Mads LindstrÃ¸m]<br />
<br />
= Utilities =<br />
<br />
Helper functions, debugging functions, or more involved code e.g. a monadic fold algebra for THSyntax.<br />
<br />
* http://www.haskell.org/pipermail/template-haskell/2003-September/000176.html<br />
<br />
= Known Bugs =<br />
<br />
Take a look at the [http://cvs.haskell.org/trac/ghc/query?status=new&status=assigned&status=reopened&component=Template+Haskell&order=priority open bugs against Template Haskell] on the GHC bug tracker.<br />
<br />
The bug you're most likely to run into is [http://cvs.haskell.org/trac/ghc/ticket/651 Template Haskell does not work with profiling].<br />
<br />
= Wish list =<br />
<br />
Things that Ian Lynagh (Igloo) mentioned in his paper ''Template Haskell: A Report From The Field'' in May 2003 (available [http://www.haskell.org/th/papers.html here]), by section:<br />
<br />
* Section 2 (curses)<br />
** The ability to splice names (into "foreign import" declarations, in particular)<br />
** The ability to add things to the export list from a splice(?)<br />
** The ability to use things defined at the toplevel of a module from splices in that same module (would require multi-stage compilation, as opposed to the current approach of expanding splices during typechecking)<br />
<br />
* Section 3 (deriving instances of classes)<br />
** <strike>First-class reification</strike> (the <hask>reify</hask> function)<br />
** A way to discover whether a data constructor was defined infix or prefix (which is necessary to derive instances for <hask>Read</hask> and <hask>Show</hask> as outlined in [http://www.haskell.org/onlinereport/derived.html The Haskell 98 Report: Specification of Derived Instances]) (if there is a way, [http://www-users.cs.york.ac.uk/~ndm/derive/ Derive] seems ignorant of it)<br />
** Type/context splicing (in <hask>instance</hask> headers in particular)<br />
<br />
* Section 4 (printf)<br />
** He says something to the effect that a pattern-matching form of the quotation brackets would be cool if it was expressive enough to be useful, but that this would be hard. (Don't expect this anytime soon.)<br />
<br />
* Section 5 (fraskell)<br />
** Type information for quoted code (so that simplification can be done safely even with overloaded operations, like, oh, <hask>(+)</hask>)<br />
<br />
* Section 6 (pan)<br />
** Type info again, and strictnes info too (this one seems a bit pie-in-the-sky...)<br />
<br />
(Please leave the implemented ones here, but crossed off.)<br />
<br />
Any other features that may be nice, and TH projects you'd want to see.<br />
<br />
* A TH tutorial (mainly a distillation and update of ''Template Meta-programming in Haskell'' at this point)<br />
* Write Haddock documentation for the Template Haskell library.<br />
* Make `reify` on a class return a list of the instances of that class (http://www.haskell.org/pipermail/template-haskell/2005-December/000503.html). (See also [http://hackage.haskell.org/trac/ghc/ticket/1577 GHC ticket #1577].)<br />
* A set of simple examples on this wiki page<br />
* A TH T-shirt with new logo to wear at conferences<br />
* (Long-term) Unify Language.Haskell.Syntax with Language.Haskell.TH.Syntax so there's just one way to do things<br />
<br />
---------------<br />
<br />
= Tips and Tricks =<br />
<br />
== What to do when you can't splice that there ==<br />
<br />
When you try to splice something into the middle of a template and find that you just can't, instead of getting frustrated about it, why not use the template to see what it would look like in longhand? <br />
<br />
First, an excerpt from a module of my own. I, by the way, am SamB.<br />
<haskell><br />
{-# OPTIONS_GHC -fglasgow-exts -fth #-}<br />
<br />
module MMixMemory where<br />
<br />
import Data.Int<br />
import Data.Word<br />
<br />
class (Integral int, Integral word)<br />
=> SignConversion int word | int -> word, word -> int where<br />
<br />
toSigned :: word -> int<br />
toSigned = fromIntegral<br />
toUnsigned :: int -> word<br />
toUnsigned = fromIntegral<br />
<br />
</haskell><br />
<br />
Say I want to find out what I need to do to splice in the types for an instance declaration for the SignConversion class, so that I can declare instances for Int8 with Word8 through Int64 with Word64. So, I start up good-ol' GHCi and do the following:<br />
<br />
<haskell><br />
$ ghci -fth -fglasgow-exts<br />
Prelude> :l MMixMemory<br />
*MMixMemory> :m +Language.Haskell.TH.Syntax<br />
*MMixMemory Language.Haskell.TH.Syntax> runQ [d| instance SignConversion Int Word where |] >>= print<br />
[InstanceD [] (AppT (AppT (ConT MMixMemory.SignConversion) (ConT GHC.Base.Int)) (ConT GHC.Word.Word)) []]<br />
</haskell><br />
<br />
== Why does <tt>runQ</tt> crash if I try to reify something? ==<br />
<br />
This program will fail with an error message when you run it:<br />
<haskell><br />
main = do info <- runQ (reify (mkName "Bool"))<br />
putStrLn (pprint info)<br />
</haskell><br />
Reason: <tt>reify</tt> consults the type environment, and that is not available at run-time. The type of <tt>reify</tt> is <br />
<haskell><br />
reify :: Quasi m => Q a -> m a<br />
</haskell><br />
The IO monad is a poor-man's instance of <tt>Quasi</tt>; it can allocate unique names and gather error messages, but it can't do <tt>reify</tt>. This error should really be caught statically.<br />
<br />
Here's an [http://www.haskell.org/pipermail/glasgow-haskell-users/2006-August/010844.html email thread with more details].<br />
<br />
-----------------<br />
= Examples =<br />
== Select from a tuple ==<br />
<br />
An example to select an element from a tuple of arbitrary size. Taken from [http://www.haskell.org/th/papers/meta-haskell.ps this paper].<br />
<br />
Use like so:<br />
<br />
> $(sel 2 3) ('a','b','c')<br />
'b'<br />
> $(sel 3 4) ('a','b','c','d')<br />
'c'<br />
<br />
<br />
<haskell><br />
sel :: Int -> Int -> ExpQ<br />
sel i n = [| \x -> $(caseE [| x |] [alt]) |]<br />
where alt :: MatchQ<br />
alt = match pat (normalB rhs) []<br />
<br />
pat :: Pat<br />
pat = tupP (map varP as)<br />
<br />
rhs :: ExpQ<br />
rhs = varE(as !! (i -1)) -- !! is 0 based<br />
<br />
as :: [String]<br />
as = ["a" ++ show i | i <- [1..n] ]<br />
</haskell><br />
<br />
Alternately:<br />
<br />
<haskell><br />
sel' i n = lamE [pat] rhs<br />
where pat = tupP (map varP as)<br />
rhs = varE (as !! (i - 1))<br />
as = [ "a" ++ show j | j <- [1..n] ]<br />
</haskell><br />
<br />
== Convert the first n elements of a list to a tuple ==<br />
<br />
This example creates a tuple by extracting elemnts from a list. Taken from<br />
[http://www.xoltar.org/2003/aug/13/templateHaskellTupleSample.html www.xoltar.org]<br />
<br />
Use like so:<br />
<br />
> $(tuple 3) [1,2,3,4,5]<br />
(1,2,3)<br />
> $(tuple 2) [1,2]<br />
(1,2)<br />
<br />
<haskell><br />
tuple :: Int -> ExpQ<br />
tuple n = [|\list -> $(tupE (exprs [|list|])) |]<br />
where<br />
exprs list = [infixE (Just (list))<br />
(varE "!!")<br />
(Just (litE $ integerL (toInteger num)))<br />
| num <- [0..(n - 1)]]<br />
</haskell><br />
<br />
== Printf ==<br />
This example taken from: http://haskell.cs.yale.edu/ghc/docs/6.0/html/users_guide/template-haskell.html<br />
<br />
Build it using a command similar to one of the following (depending on your environment):<br />
<br />
ghc/compiler/stage3/ghc-inplace --make -fglasgow-exts -package haskell-src main.hs -o main.exe<br />
ghc --make -fth Main.hs -o printfTest<br />
<br />
Main.hs:<br />
<br />
<haskell><br />
module Main where<br />
<br />
-- Import our template "pr"<br />
import Printf ( pr )<br />
<br />
-- The splice operator $ takes the Haskell source code<br />
-- generated at compile time by "pr" and splices it into<br />
-- the argument of "putStrLn".<br />
main = putStrLn ( $(pr "Hello") )<br />
</haskell><br />
<br />
Printf.hs:<br />
<br />
<haskell><br />
module Printf where<br />
<br />
-- Skeletal printf from the paper.<br />
-- It needs to be in a separate module to the one where<br />
-- you intend to use it.<br />
<br />
-- Import some Template Haskell syntax<br />
import Language.Haskell.THSyntax<br />
<br />
-- Describe a format string<br />
data Format = D | S | L String<br />
<br />
-- Parse a format string. This is left largely to you<br />
-- as we are here interested in building our first ever<br />
-- Template Haskell program and not in building printf.<br />
parse :: String -> [Format]<br />
parse s = [ L s ]<br />
<br />
-- Generate Haskell source code from a parsed representation<br />
-- of the format string. This code will be spliced into<br />
-- the module which calls "pr", at compile time.<br />
gen :: [Format] -> ExpQ<br />
gen [D] = [| \n -> show n |]<br />
gen [S] = [| \s -> s |]<br />
gen [L s] = stringE s<br />
<br />
-- Here we generate the Haskell code for the splice<br />
-- from an input format string.<br />
pr :: String -> ExpQ<br />
pr s = gen (parse s)<br />
</haskell><br />
<br />
== Handling Options with Templates ==<br />
A common idiom for treating a set of options, e.g. from GetOpt, is to define a datatype with all the flags and using a list over this datatype:<br />
<br />
<haskell><br />
data Options = B1 | B2 | V Integer<br />
<br />
options = [B1, V 3]<br />
</haskell><br />
<br />
While it's simple testing if a Boolean flag is set (simply use "elem"), it's harder to check if an option with an argument is set. It's even more tedious writing helper-functions to obtain the value from such an option since you have to explicitely "un-V" each. Here, Template Haskell can be (ab)used to reduce this a bit. The following example provides the module "OptionsTH" which can be reused regardless of the constructors in "Options". Let's start with showing how we'd like to be able to program. Notice that the resulting lists need some more treatment e.g. through "foldl".<br />
<br />
Options.hs:<br />
<br />
<haskell><br />
module Main where<br />
<br />
import OptionsTH<br />
import Language.Haskell.THSyntax<br />
<br />
data Options = B1 | B2 | V Int | S String deriving (Eq, Read, Show)<br />
<br />
options = [B1, V 3]<br />
<br />
main = do<br />
print foo -- test if B1 set: [True,False]<br />
print bar -- test if V present, w/o value: [False,True]<br />
print baz -- get value of V if available: [Nothing,Just 3]<br />
<br />
foo :: [Bool]<br />
-- Query constructor B1 which takes no arguments<br />
foo = map $(getopt (THNoArg (mkArg "B1" 0))) options<br />
<br />
bar :: [Bool]<br />
-- V is a unary constructor. Let mkArg generate the required<br />
-- wildcard-pattern "V _".<br />
bar = map $(getopt (THNoArg (mkArg "V" 1))) options<br />
<br />
-- Can't use a wildcard here!<br />
baz :: [(Maybe Int)]<br />
baz = map $(getopt (THArg (conP "V" [varP "x"]))) options<br />
</haskell><br />
<br />
OptionsTH.hs<br />
<br />
<haskell><br />
module OptionsTH where<br />
<br />
import Language.Haskell.THSyntax<br />
<br />
-- datatype for querying options:<br />
-- NoArg: Not interested in value (also applies to Boolean flags)<br />
-- Arg: Grep value of unary(!) constructor<br />
data Args = THNoArg Pat | THArg Pat<br />
<br />
getopt :: Args -> ExpQ<br />
getopt (THNoArg pat) = lamE [varP "y"] (caseE (varE "y") [cons0, cons1])<br />
where<br />
cons0 = match pat (normalB [| True |]) []<br />
cons1 = match wildP (normalB [| False |]) []<br />
<br />
-- bind "var" for later use!<br />
getopt (THArg pat@(ConP _ [VarP var])) = lamE [varP "y"] (caseE (varE "y") [cons0, cons1])<br />
where<br />
cons0 = match pat (normalB (appE [|Just|] (varE var))) []<br />
cons1 = match wildP (normalB [|Nothing|]) []<br />
<br />
mkArg :: String -> Int -> Pat<br />
mkArg k c = conP k (replicate c wildP)<br />
</haskell><br />
<br />
While the example might look contrived for the Boolean options which could have been tested much easier, it shows how both types of arguments can be treated in a similar way.<br />
<br />
=== Limitations ===<br />
<tt>getopt (THArg pat)</tt> is only able to treat unary constructors. See the pattern-binding: It matches exactly a single VarP.<br />
<br />
=== Improvements ===<br />
The following reduces things even a bit more, though I still don't know if I like it. It only works since <tt>c</tt> is either 0 or 1.<br />
<br />
<haskell><br />
mkArg k c = conP k (replicate c (varP "x"))<br />
<br />
baz = map $(getopt (THArg (mkArg "V" 1)))<br />
</haskell><br />
-- VolkerStolz<br />
<br />
== Generic constructor for records ==<br />
<br />
I have a large number of record types like this, of different length:<br />
<br />
<haskell><br />
data PGD = PGD {<br />
pgdXUnitBase :: !Word8,<br />
pgdYUnitBase :: !Word8,<br />
pgdXLUnitsperUnitBase :: !Word16<br />
}<br />
</haskell><br />
<br />
Currently I use GHC's Binary module to read them from files; it can handle<br />
types like <tt>(Word8, (Word8, Word16))</tt>, but there was no easy way to generate<br />
the correct amount of "uncurry" calls for automatically grabbing each element.<br />
<br />
With Template Haskell, the instance declarations are now written as such:<br />
<br />
<haskell><br />
instance Binary PGD where<br />
get bh = do a <- get bh ; return $ $(constrRecord PGD) a<br />
</haskell><br />
<br />
Here the trick lies in constrRecord, which is defined as:<br />
<br />
<haskell><br />
constrRecord x = reify exp where<br />
reify = \(Just r) -> appE r $ conE $ last args<br />
exp = foldl (dot) uncur $ replicate terms uncur<br />
terms = ((length args) `div` 2) - 2<br />
dot x y = (Just $ infixE x (varE ".") y)<br />
uncur = (Just [|uncurry|])<br />
args = words . show $ typeOf x<br />
</haskell><br />
<br />
-- AutrijusTang<br />
<br />
==[[Template haskell/Instance deriving example|Instance deriving example]]==<br />
An example using a 'deriving function' to generate a method instance <br />
per constructor of a type. The deriving function provides the body of the<br />
method.<br />
<br />
Note that this example assumes that the functions of the class take a parameter that is the same type as instance is parameterized with. <br />
<br />
The message [http://www.haskell.org/pipermail/template-haskell/2006-August/000581.html email message] contains the full source ([http://www.iist.unu.edu/~vs/haskell/TH_render.hs extracted file]).<br />
<br />
[[Category:Language extensions]]</div>JohannesAhlmannhttps://wiki.haskell.org/Template_HaskellTemplate Haskell2008-02-23T10:14:38Z<p>JohannesAhlmann: added archive.org link to the TH tutorial on the old wiki</p>
<hr />
<div>'''[http://www.haskell.org/th/ Template Haskell]''' is a [[GHC]] extension to Haskell that adds compile-time metaprogramming facilities. The original design can be found here: http://research.microsoft.com/~simonpj/papers/meta-haskell/ . It is [http://haskell.cs.yale.edu/ghc/docs/6.2/html/users_guide/template-haskell.html included] in GHC version 6. If you start working with Template Haskell you'll probably want to join the [http://haskell.org/mailman/listinfo/template-haskell Template Haskell mailing list].<br />
<br />
This page hopes to be a more central and organized repository of TH related things. However, at this point most things should probably go to/through the mailing list first.<br />
<br />
----<br />
=What is Template Haskell?=<br />
Template Haskell is an extension to Haskell 98 that allows you to do type-safe compile-time meta-programming, with Haskell both as the manipulating language and the language being manipulated. <br />
<br />
Intuitively Template Haskell provides new language features that allow us to convert back and forth between concrete syntax, i.e. what you would type when you write normal Haskell code, and abstract syntax trees. These abstract syntax trees are represented using Haskell datatypes and, at compile time, they can be manipulated by Haskell code. This allows you to reify (convert from concrete syntax to an abstract syntax tree) some code, transform it and splice it back in (convert back again), or even to produce completely new code and splice that in, while the compiler is compiling your module. <br />
<br />
There is a [http://haskell.org/mailman/listinfo/template-haskell mailing list specifically for Template Haskell]. It's worth joining if you start to use TH.<br />
<br />
= Template Haskell specification =<br />
<br />
Template Haskell is only documented rather informally at the moment. Here are the main resources:<br />
<br />
* [http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html The user manual section]<br />
* [http://research.microsoft.com/~simonpj/papers/meta-haskell/ The original Template Haskell paper]<br />
* [http://research.microsoft.com/~simonpj/tmp/notes2.ps Notes on Template Haskell version 2], which describes changes since the original paper.<br />
* [http://www.haskell.org/ghc/docs/latest/html/libraries/haskell-src/Language.Haskell.THSyntax.html The Template Haskell API]<br />
<br />
= Template Haskell tutorials and papers =<br />
<br />
* Bulat's tutorials:<br />
** http://www.haskell.org/bz/thdoc.htm<br />
** http://www.haskell.org/bz/th3.htm<br />
: One reader said "These docs are *brilliant* ! Exactly what I need to get an understanding of TH."<br />
<br />
* Mark Snyder's Template Haskell chapter on the Software Generation and Configuration Report<br />
** http://nix.cs.uu.nl/dist/courses/sgc-report-unstable-latest/manual/chunk-chapter/templatehaskell.html<br />
<br />
* Papers about Template Haskell<br />
** Template metaprogramming for Haskell, by Tim Sheard and Simon Peyton Jones, May 2002. [http://haskell.org/th/papers/meta-haskell.ps [A4 ps]] [http://haskell.org/th/papers/meta-haskell.bib [bib]]<br />
** Template Haskell: A Report From The Field, by Ian Lynagh, May 2003.[http://haskell.org/th/papers/Template_Haskell-A_Report_From_The_Field.ps [A4 ps]] [http://haskell.org/th/papers/Template_Haskell-A_Report_From_The_Field.bib [bib]]<br />
** Unrolling and Simplifying Expressions with Template Haskell, by Ian Lynagh, May 2003.[http://haskell.org/th/papers/Unrolling_and_Simplifying_Expressions_with_Template_Haskell.ps [A4 ps]][http://haskell.org/th/papers/Unrolling_and_Simplifying_Expressions_with_Template_Haskell.bib [bib]]<br />
** Automatic skeletons in Template Haskell, by Kevin Hammond, Jost Berthold and Rita Loogen, June 2003. [http://haskell.org/th/papers/hlpp.ps [A4 ps]][http://haskell.org/th/papers/hlpp.bib [bib]]<br />
** Optimising Embedded DSLs using Template Haskell, by Sean Seefried, Manuel Chakravarty, Gabriele Keller, March 2004. [http://haskell.org/th/papers/th-pan.ps [A4 ps]] [http://haskell.org/th/papers/th-pan.bib [bib]]<br />
** Typing Template Haskell: Soft Types, by Ian Lynagh, August 2004.[http://haskell.org/th/papers/Typing_Template_Haskell__Soft_Types.ps [A4 ps]][http://haskell.org/th/papers/Typing_Template_Haskell__Soft_Types.bib [bib]]<br />
<br />
* A Template Haskell tutorial: [http://web.archive.org/web/20070609061352/http://www.haskell.org/hawiki/TemplateHaskellTutorial TemplateHaskellTutorial] (archive.org link to the page on the old wiki)<br />
<br />
= Other useful resources =<br />
<br />
* [http://www.haskell.org/th/ The old Template Haskell web page]. Would someone feel like moving this material into the HaskellWiki?<br />
* Old and probably not too useful for most but maybe... http://www.cse.unsw.edu.au/~chak/haskell/ghc/comm/exts/th.html<br />
*[http://web.comlab.ox.ac.uk/oucl/work/ian.lynagh/Fraskell/ Fraskell documentation] & explanation of how Template Haskell is used to vastly speed it up.<br />
Feel free to update our Wikipedia entry<br />
http://en.wikipedia.org/wiki/Template_Haskell<br />
<br />
= Projects =<br />
<br />
What are you doing/planning to do/have done with Template Haskell?<br />
<br />
* I have written a primitive (untyped) binding to the Objective-C runtime system on Mac OS X. It needs just TH, no "stub files" are created, no seperate utilities are required. Initial snapshot is at http://www.kfunigraz.ac.at/imawww/thaller/wolfgang/HOC020103.tar.bz2 -- WolfgangThaller<br />
<br />
* I am writing Template Greencard - a reimplementation of GreenCard using TH. Many bits work out really nicely. A few bits didn't work so nicely - once I get some time to think, I'll try to persuade the TH folk to make some changes to fix some of these. -- AlastairReid<br />
<br />
* I'm writing Hacanon - a framework for automatic generation of C++ bindings. Read "automated Template Greencard for C++" (-: Darcs repo: http://www.ScannedInAvian.org/repos/hacanon - You'll need gccxml (http://www.gccxml.org/) to compile the exmples. - 27 Dec Lemmih.<br />
<br />
* Following other FFI tools developers, I see some future for Template HSFFIG, especially when it comes to autogenerate peek and poke methods for structures defined in C; may be useful for implementation of certain network protocols such as X11 where layout of messages is provided as C structure/union declaration. - 16 Dec 2005 DimitryGolubovsky<br />
<br />
* I am using Template Haskell as a mechanism to get parsed, typechecked code into an Ajax based Haskell Equational Reasoning tool [[Haskell Equational Reasoning Assistant]], as well as simplify the specification of equational relationships between pieces of code. There was a quicktime movie of the tool being used on http://www.gill-warbington.com/home/andy/share/hera1.html - AndyGill <br />
<br />
* I am working on functional metaprogramming techniques to enhance programming reliability and productivity, by reusing much of the existing compiler technology. Template Haskell is especially interesting for me because it permits to check size information of structures by the compiler, provided this information is available at compile time. This approach is especially appropriate for hardware designs, where the structures are fixed before the circuit starts operating. See our metaprogramming web page at http://www.infosun.fmi.uni-passau.de/cl/metaprog/ -- ChristophHerrmann(http://www.cs.st-and.ac.uk/~ch)<br />
<br />
= Utilities =<br />
<br />
Helper functions, debugging functions, or more involved code e.g. a monadic fold algebra for THSyntax.<br />
<br />
* http://www.haskell.org/pipermail/template-haskell/2003-September/000176.html<br />
<br />
= Known Bugs =<br />
<br />
Take a look at the [http://cvs.haskell.org/trac/ghc/query?status=new&status=assigned&status=reopened&component=Template+Haskell&order=priority open bugs against Template Haskell] on the GHC bug tracker.<br />
<br />
The bug you're most likely to run into is [http://cvs.haskell.org/trac/ghc/ticket/651 Template Haskell does not work with profiling].<br />
<br />
= Wish list =<br />
<br />
Things that Ian Lynagh (Igloo) mentioned in his paper ''Template Haskell: A Report From The Field'' in May 2003 (available [http://www.haskell.org/th/papers.html here]), by section:<br />
<br />
* Section 2 (curses)<br />
** The ability to splice names (into "foreign import" declarations, in particular)<br />
** The ability to add things to the export list from a splice(?)<br />
** The ability to use things defined at the toplevel of a module from splices in that same module (would require multi-stage compilation, as opposed to the current approach of expanding splices during typechecking)<br />
<br />
* Section 3 (deriving instances of classes)<br />
** <strike>First-class reification</strike> (the <hask>reify</hask> function)<br />
** A way to discover whether a data constructor was defined infix or prefix (which is necessary to derive instances for <hask>Read</hask> and <hask>Show</hask> as outlined in [http://www.haskell.org/onlinereport/derived.html The Haskell 98 Report: Specification of Derived Instances]) (if there is a way, [http://www-users.cs.york.ac.uk/~ndm/derive/ Derive] seems ignorant of it)<br />
** Type/context splicing (in <hask>instance</hask> headers in particular)<br />
<br />
* Section 4 (printf)<br />
** He says something to the effect that a pattern-matching form of the quotation brackets would be cool if it was expressive enough to be useful, but that this would be hard. (Don't expect this anytime soon.)<br />
<br />
* Section 5 (fraskell)<br />
** Type information for quoted code (so that simplification can be done safely even with overloaded operations, like, oh, <hask>(+)</hask>)<br />
<br />
* Section 6 (pan)<br />
** Type info again, and strictnes info too (this one seems a bit pie-in-the-sky...)<br />
<br />
(Please leave the implemented ones here, but crossed off.)<br />
<br />
Any other features that may be nice, and TH projects you'd want to see.<br />
<br />
* A TH tutorial (mainly a distillation and update of ''Template Meta-programming in Haskell'' at this point)<br />
* Write Haddock documentation for the Template Haskell library.<br />
* Make `reify` on a class return a list of the instances of that class (http://www.haskell.org/pipermail/template-haskell/2005-December/000503.html). (See also [http://hackage.haskell.org/trac/ghc/ticket/1577 GHC ticket #1577].)<br />
* A set of simple examples on this wiki page<br />
* A TH T-shirt with new logo to wear at conferences<br />
* (Long-term) Unify Language.Haskell.Syntax with Language.Haskell.TH.Syntax so there's just one way to do things<br />
<br />
---------------<br />
<br />
= Tips and Tricks =<br />
<br />
== What to do when you can't splice that there ==<br />
<br />
When you try to splice something into the middle of a template and find that you just can't, instead of getting frustrated about it, why not use the template to see what it would look like in longhand? <br />
<br />
First, an excerpt from a module of my own. I, by the way, am SamB.<br />
<haskell><br />
{-# OPTIONS_GHC -fglasgow-exts -fth #-}<br />
<br />
module MMixMemory where<br />
<br />
import Data.Int<br />
import Data.Word<br />
<br />
class (Integral int, Integral word)<br />
=> SignConversion int word | int -> word, word -> int where<br />
<br />
toSigned :: word -> int<br />
toSigned = fromIntegral<br />
toUnsigned :: int -> word<br />
toUnsigned = fromIntegral<br />
<br />
</haskell><br />
<br />
Say I want to find out what I need to do to splice in the types for an instance declaration for the SignConversion class, so that I can declare instances for Int8 with Word8 through Int64 with Word64. So, I start up good-ol' GHCi and do the following:<br />
<br />
<haskell><br />
$ ghci -fth -fglasgow-exts<br />
Prelude> :l MMixMemory<br />
*MMixMemory> :m +Language.Haskell.TH.Syntax<br />
*MMixMemory Language.Haskell.TH.Syntax> runQ [d| instance SignConversion Int Word where |] >>= print<br />
[InstanceD [] (AppT (AppT (ConT MMixMemory.SignConversion) (ConT GHC.Base.Int)) (ConT GHC.Word.Word)) []]<br />
</haskell><br />
<br />
== Why does <tt>runQ</tt> crash if I try to reify something? ==<br />
<br />
This program will fail with an error message when you run it:<br />
<haskell><br />
main = do info <- runQ (reify (mkName "Bool"))<br />
putStrLn (pprint info)<br />
</haskell><br />
Reason: <tt>reify</tt> consults the type environment, and that is not available at run-time. The type of <tt>reify</tt> is <br />
<haskell><br />
reify :: Quasi m => Q a -> m a<br />
</haskell><br />
The IO monad is a poor-man's instance of <tt>Quasi</tt>; it can allocate unique names and gather error messages, but it can't do <tt>reify</tt>. This error should really be caught statically.<br />
<br />
Here's an [http://www.haskell.org/pipermail/glasgow-haskell-users/2006-August/010844.html email thread with more details].<br />
<br />
-----------------<br />
= Examples =<br />
== Select from a tuple ==<br />
<br />
An example to select an element from a tuple of arbitrary size. Taken from [http://www.haskell.org/th/papers/meta-haskell.ps this paper].<br />
<br />
Use like so:<br />
<br />
> $(sel 2 3) ('a','b','c')<br />
'b'<br />
> $(sel 3 4) ('a','b','c','d')<br />
'c'<br />
<br />
<br />
<haskell><br />
sel :: Int -> Int -> ExpQ<br />
sel i n = [| \x -> $(caseE [| x |] [alt]) |]<br />
where alt :: MatchQ<br />
alt = match pat (normalB rhs) []<br />
<br />
pat :: Pat<br />
pat = tupP (map varP as)<br />
<br />
rhs :: ExpQ<br />
rhs = varE(as !! (i -1)) -- !! is 0 based<br />
<br />
as :: [String]<br />
as = ["a" ++ show i | i <- [1..n] ]<br />
</haskell><br />
<br />
Alternately:<br />
<br />
<haskell><br />
sel' i n = lamE [pat] rhs<br />
where pat = tupP (map varP as)<br />
rhs = varE (as !! (i - 1))<br />
as = [ "a" ++ show j | j <- [1..n] ]<br />
</haskell><br />
<br />
== Convert the first n elements of a list to a tuple ==<br />
<br />
This example creates a tuple by extracting elemnts from a list. Taken from<br />
[http://www.xoltar.org/2003/aug/13/templateHaskellTupleSample.html www.xoltar.org]<br />
<br />
Use like so:<br />
<br />
> $(tuple 3) [1,2,3,4,5]<br />
(1,2,3)<br />
> $(tuple 2) [1,2]<br />
(1,2)<br />
<br />
<haskell><br />
tuple :: Int -> ExpQ<br />
tuple n = [|\list -> $(tupE (exprs [|list|])) |]<br />
where<br />
exprs list = [infixE (Just (list))<br />
(varE "!!")<br />
(Just (litE $ integerL (toInteger num)))<br />
| num <- [0..(n - 1)]]<br />
</haskell><br />
<br />
== Printf ==<br />
This example taken from: http://haskell.cs.yale.edu/ghc/docs/6.0/html/users_guide/template-haskell.html<br />
<br />
Build it using a command similar to one of the following (depending on your environment):<br />
<br />
ghc/compiler/stage3/ghc-inplace --make -fglasgow-exts -package haskell-src main.hs -o main.exe<br />
ghc --make -fth Main.hs -o printfTest<br />
<br />
Main.hs:<br />
<br />
<haskell><br />
module Main where<br />
<br />
-- Import our template "pr"<br />
import Printf ( pr )<br />
<br />
-- The splice operator $ takes the Haskell source code<br />
-- generated at compile time by "pr" and splices it into<br />
-- the argument of "putStrLn".<br />
main = putStrLn ( $(pr "Hello") )<br />
</haskell><br />
<br />
Printf.hs:<br />
<br />
<haskell><br />
module Printf where<br />
<br />
-- Skeletal printf from the paper.<br />
-- It needs to be in a separate module to the one where<br />
-- you intend to use it.<br />
<br />
-- Import some Template Haskell syntax<br />
import Language.Haskell.THSyntax<br />
<br />
-- Describe a format string<br />
data Format = D | S | L String<br />
<br />
-- Parse a format string. This is left largely to you<br />
-- as we are here interested in building our first ever<br />
-- Template Haskell program and not in building printf.<br />
parse :: String -> [Format]<br />
parse s = [ L s ]<br />
<br />
-- Generate Haskell source code from a parsed representation<br />
-- of the format string. This code will be spliced into<br />
-- the module which calls "pr", at compile time.<br />
gen :: [Format] -> ExpQ<br />
gen [D] = [| \n -> show n |]<br />
gen [S] = [| \s -> s |]<br />
gen [L s] = stringE s<br />
<br />
-- Here we generate the Haskell code for the splice<br />
-- from an input format string.<br />
pr :: String -> ExpQ<br />
pr s = gen (parse s)<br />
</haskell><br />
<br />
== Handling Options with Templates ==<br />
A common idiom for treating a set of options, e.g. from GetOpt, is to define a datatype with all the flags and using a list over this datatype:<br />
<br />
<haskell><br />
data Options = B1 | B2 | V Integer<br />
<br />
options = [B1, V 3]<br />
</haskell><br />
<br />
While it's simple testing if a Boolean flag is set (simply use "elem"), it's harder to check if an option with an argument is set. It's even more tedious writing helper-functions to obtain the value from such an option since you have to explicitely "un-V" each. Here, Template Haskell can be (ab)used to reduce this a bit. The following example provides the module "OptionsTH" which can be reused regardless of the constructors in "Options". Let's start with showing how we'd like to be able to program. Notice that the resulting lists need some more treatment e.g. through "foldl".<br />
<br />
Options.hs:<br />
<br />
<haskell><br />
module Main where<br />
<br />
import OptionsTH<br />
import Language.Haskell.THSyntax<br />
<br />
data Options = B1 | B2 | V Int | S String deriving (Eq, Read, Show)<br />
<br />
options = [B1, V 3]<br />
<br />
main = do<br />
print foo -- test if B1 set: [True,False]<br />
print bar -- test if V present, w/o value: [False,True]<br />
print baz -- get value of V if available: [Nothing,Just 3]<br />
<br />
foo :: [Bool]<br />
-- Query constructor B1 which takes no arguments<br />
foo = map $(getopt (THNoArg (mkArg "B1" 0))) options<br />
<br />
bar :: [Bool]<br />
-- V is a unary constructor. Let mkArg generate the required<br />
-- wildcard-pattern "V _".<br />
bar = map $(getopt (THNoArg (mkArg "V" 1))) options<br />
<br />
-- Can't use a wildcard here!<br />
baz :: [(Maybe Int)]<br />
baz = map $(getopt (THArg (conP "V" [varP "x"]))) options<br />
</haskell><br />
<br />
OptionsTH.hs<br />
<br />
<haskell><br />
module OptionsTH where<br />
<br />
import Language.Haskell.THSyntax<br />
<br />
-- datatype for querying options:<br />
-- NoArg: Not interested in value (also applies to Boolean flags)<br />
-- Arg: Grep value of unary(!) constructor<br />
data Args = THNoArg Pat | THArg Pat<br />
<br />
getopt :: Args -> ExpQ<br />
getopt (THNoArg pat) = lamE [varP "y"] (caseE (varE "y") [cons0, cons1])<br />
where<br />
cons0 = match pat (normalB [| True |]) []<br />
cons1 = match wildP (normalB [| False |]) []<br />
<br />
-- bind "var" for later use!<br />
getopt (THArg pat@(ConP _ [VarP var])) = lamE [varP "y"] (caseE (varE "y") [cons0, cons1])<br />
where<br />
cons0 = match pat (normalB (appE [|Just|] (varE var))) []<br />
cons1 = match wildP (normalB [|Nothing|]) []<br />
<br />
mkArg :: String -> Int -> Pat<br />
mkArg k c = conP k (replicate c wildP)<br />
</haskell><br />
<br />
While the example might look contrived for the Boolean options which could have been tested much easier, it shows how both types of arguments can be treated in a similar way.<br />
<br />
=== Limitations ===<br />
<tt>getopt (THArg pat)</tt> is only able to treat unary constructors. See the pattern-binding: It matches exactly a single VarP.<br />
<br />
=== Improvements ===<br />
The following reduces things even a bit more, though I still don't know if I like it. It only works since <tt>c</tt> is either 0 or 1.<br />
<br />
<haskell><br />
mkArg k c = conP k (replicate c (varP "x"))<br />
<br />
baz = map $(getopt (THArg (mkArg "V" 1)))<br />
</haskell><br />
-- VolkerStolz<br />
<br />
== Generic constructor for records ==<br />
<br />
I have a large number of record types like this, of different length:<br />
<br />
<haskell><br />
data PGD = PGD {<br />
pgdXUnitBase :: !Word8,<br />
pgdYUnitBase :: !Word8,<br />
pgdXLUnitsperUnitBase :: !Word16<br />
}<br />
</haskell><br />
<br />
Currently I use GHC's Binary module to read them from files; it can handle<br />
types like <tt>(Word8, (Word8, Word16))</tt>, but there was no easy way to generate<br />
the correct amount of "uncurry" calls for automatically grabbing each element.<br />
<br />
With Template Haskell, the instance declarations are now written as such:<br />
<br />
<haskell><br />
instance Binary PGD where<br />
get bh = do a <- get bh ; return $ $(constrRecord PGD) a<br />
</haskell><br />
<br />
Here the trick lies in constrRecord, which is defined as:<br />
<br />
<haskell><br />
constrRecord x = reify exp where<br />
reify = \(Just r) -> appE r $ conE $ last args<br />
exp = foldl (dot) uncur $ replicate terms uncur<br />
terms = ((length args) `div` 2) - 2<br />
dot x y = (Just $ infixE x (varE ".") y)<br />
uncur = (Just [|uncurry|])<br />
args = words . show $ typeOf x<br />
</haskell><br />
<br />
-- AutrijusTang<br />
<br />
==[[Template haskell/Instance deriving example|Instance deriving example]]==<br />
An example using a 'deriving function' to generate a method instance <br />
per constructor of a type. The deriving function provides the body of the<br />
method.<br />
<br />
Note that this example assumes that the functions of the class take a parameter that is the same type as instance is parameterized with. <br />
<br />
The message [http://www.haskell.org/pipermail/template-haskell/2006-August/000581.html email message] contains the full source ([http://www.iist.unu.edu/~vs/haskell/TH_render.hs extracted file]).<br />
<br />
[[Category:Language extensions]]</div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_QuizHaskell Quiz2008-01-16T14:45:22Z<p>JohannesAhlmann: </p>
<hr />
<div>A collection of solutions to the [http://www.rubyquiz.com Ruby quiz] puzzles in simple, elegant Haskell.<br />
<br />
As you solve the puzzles, please contribute your code, and create a page<br />
for the puzzle entries. When creating a new page for your source, be<br />
sure to categorise it as code, with a [ [ Category:Code ] ] tag.<br />
<br />
== The Puzzles ==<br />
<br />
1. [[Haskell Quiz/The Solitaire Cipher|The Solitaire Cipher]]<br />
<br />
2. [[Haskell Quiz/Secret Santas|Secret Santas]]<br />
<br />
5. [[Haskell Quiz/Sokoban|Sokoban]]<br />
<br />
7. [[Haskell Quiz/Countdown|Countdown]]<br />
<br />
15. [[Haskell Quiz/Animal Quiz|Animal Quiz]]<br />
<br />
19. [[Haskell Quiz/Yahtzee|Yahtzee]]<br />
<br />
20. [[Haskell Quiz/Phone Number Words|Phone Number Words]]<br />
<br />
22. [[Haskell Quiz/Roman Numerals|Roman Numerals]]<br />
<br />
25. [[Haskell Quiz/English Numerals|English Numerals]]<br />
<br />
27. [[Haskell Quiz/Knight's Travails|Knight's Travails]]<br />
<br />
31. [[Haskell Quiz/Amazing Mazes|Amazing Mazes]]<br />
<br />
33. [[Haskell Quiz/Tiling Turmoil|Tiling Turmoil]]<br />
<br />
39. [[Haskell Quiz/Sampling|Sampling]]<br />
<br />
43. [[Haskell Quiz/Sodoku Solver|Sodoku Solver]]<br />
<br />
54. [[Haskell Quiz/Index and Query|Text Index and Query]]<br />
<br />
57. [[Haskell Quiz/Weird Numbers|Weird Numbers]]<br />
<br />
60. [[Haskell Quiz/Numeric Maze|Numeric Maze]]<br />
<br />
63. [[Haskell Quiz/Grid Folding|Grid Folding]]<br />
<br />
65. [[Haskell Quiz/Splitting the Loot|Splitting the Loot]]<br />
<br />
70. [[Haskell Quiz/Constraint Processing|Constraint Processing]] <br />
<br />
76. [[Haskell Quiz/Text Munger|Text Munger]]<br />
<br />
77. [[Haskell Quiz/Cat2Rafb|cat2rafb]]<br />
<br />
84. [[Haskell Quiz/PP Pascal|PP Pascal]]<br />
<br />
88. [[Haskell Quiz/Chip Eight|Chip Eight]]<br />
<br />
92. [[Haskell Quiz/DayRange|DayRange]]<br />
<br />
93. [[Haskell Quiz/Happy Numbers|Happy Numbers]]<br />
<br />
97. [[Haskell Quiz/Posix Pangrams|Posix Pangrams]]<br />
<br />
98. [[Haskell Quiz/Astar|A*]]<br />
<br />
99. [[Haskell Quiz/Fuzzy Time|Fuzzy Time]]<br />
<br />
100. [[Haskell Quiz/Bytecode Compiler|Bytecode Compiler]]<br />
<br />
106. [[Haskell Quiz/Chess960|Chess960]]<br />
<br />
107. [[Haskell Quiz/Word Search|Word Search]]<br />
<br />
108. [[Haskell Quiz/Word Blender|Word Blender]]<br />
<br />
114. [[Haskell Quiz/Housie|Housie]]<br />
<br />
117. [[Haskell Quiz/SimFrost|SimFrost]]<br />
<br />
121. [[Haskell Quiz/Morse Code|Morse Code]]<br />
<br />
122. [[Haskell Quiz/Credit Cards|Checking Credit Cards]]<br />
<br />
128. [[Haskell Quiz/Verbal Arithmetic|Verbal Arithmetic]]<br />
<br />
131. [[Haskell Quiz/Maximum Sub-Array|Maximum Sub-Array]]<br />
<br />
138. [[Haskell Quiz/Count and Say|Count and Say]]<br />
<br />
139. [[Haskell Quiz/IP to Country|IP to Country]]<br />
<br />
141. [[Haskell Quiz/Probable Iterations|Probable Iterations]]<br />
<br />
==Possibly fun ones not yet done in haskell==<br />
<br />
3. Geodesic Dome Faces http://www.rubyquiz.com/quiz3.html<br />
<br />
11. Learning Tic-Tac-Toe http://www.rubyquiz.com/quiz11.html<br />
<br />
37. Inference Engine http://www.rubyquiz.com/quiz37.html<br />
<br />
48. Math Captcha http://www.rubyquiz.com/quiz48.html<br />
<br />
49. Text Image http://www.rubyquiz.com/quiz50.html (Not sure how image loading will work)<br />
<br />
85. C-Style Ints http://www.rubyquiz.com/quiz85.html<br />
<br />
87. Negative Sleep http://www.rubyquiz.com/quiz87.html (As a Monad!!!)<br />
<br />
Many weren't included because of either clumsy ASCII output, or requiring a dictionary. Perhaps a dictionary module could be created and those problems attacked in a unified fashion.<br />
<br />
[[Category:Code]]<br />
[[Category:Haskell Quiz|*]]</div>JohannesAhlmannhttps://wiki.haskell.org/User:JohannesAhlmannUser:JohannesAhlmann2007-09-20T22:36:04Z<p>JohannesAhlmann: contributions</p>
<hr />
<div>My name is Johannes Ahlmann, and I go by the nick of "jethr0" in the IRC channel.<br />
<br />
So far i've toyed around with many Haskell concepts, including the obligatory [http://haskell.org/tmrwiki/JohannesAhlmann Ray Tracer], some Genetic Algorithms and Neural Networks.<br />
<br />
I took part in the [http://www.icfpcontest.org/ 2007 ICFP contest] in the team [http://homes.esat.kuleuven.be/~cpoucet/icfp2007.html Lazy Bottoms] placing 56th of 859 teams and although I didn't contribute by far as much as I would have wanted, it still was a lot of fun and definitely worth the coding marathon.<br />
<br />
Pages I've written/contributed to:<br />
* [[BlowYourMindIdioms]]<br />
* [http://web.archive.org/web/20061011050035/http://www.haskell.org/hawiki/TemplateHaskellTutorial Template Haskell Tutorial], unfortunately I was too lazy to port the tutorial to the new wiki, so it's now [http://archive.org archive.org]'ed.<br />
<br />
<br />
<br />
I also like the format of the Ruby/[[Haskell_Quiz|Haskell Quiz]] and I try to contribute solutions to interesting problems whenever I find the time. Some of these might be educational and some just plain ugly, but I always find it quite fulfilling to tackle these:<br />
* [[Haskell_Quiz/Phone_Number_Words/Solution_Jethr0|Phone Number Words]]<br />
* [[Haskell_Quiz/Index_and_Query/Solution_Jethr0|Index and Query]]<br />
* [[Haskell_Quiz/Constraint_Processing/Solution_Jethr0|Constraint Processing]]<br />
* [[Haskell_Quiz/Animal_Quiz/Solution_Jethr0|Animal Quiz]]<br />
* [[Haskell_Quiz/DayRange/Solution_Jethr0|Day Range]]<br />
* [[Haskell_Quiz/Verbal_Arithmetic/Solution_Jethr0|Verbal Arithmetic]]<br />
* [[Haskell_Quiz/Chip_Eight/Solution_Jethr0|Chip Eight]]<br />
* [[Haskell_Quiz/Sokoban/Solution_Jethr0|Sokoban]]</div>JohannesAhlmannhttps://wiki.haskell.org/Blog_articles/EDSLsBlog articles/EDSLs2007-08-09T13:37:53Z<p>JohannesAhlmann: added scheme in 48 hours to interpreters</p>
<hr />
<div>'''E'''mbedded '''D'''omain '''S'''pecific '''L'''anguages<br />
<br />
== Domain specific languages ==<br />
<br />
* [http://augustss.blogspot.com/2007/06/representing-dsl-expressions-in-haskell.html Representing DSL expressions in Haskell]<br />
* [http://augustss.blogspot.com/2007/06/massive-overload-in-my-last-post-i-had.html Embedding a larger language into Haskell with overloading]<br />
<br />
== Interpreters ==<br />
<br />
* [http://blog.moertel.com/articles/2005/03/25/writing-a-simple-ruby-evaluator-in-haskell Writing a simple Ruby evaluator in Haskell]<br />
* [http://lstephen.wordpress.com/2007/07/23/completing-the-spike/ Implementing SmallTalk in Haskell]<br />
* [http://halogen.note.amherst.edu/~jdtang/scheme_in_48/tutorial/overview.html Write Yourself a Scheme in 48 hours]<br />
<br />
== Code generation ==<br />
<br />
* Writing x86 code generators with Harpy:<br />
** [http://augustss.blogspot.com/2007/06/playing-with-harpy-recently-there-was.html Generating x86 assembly]<br />
** [http://augustss.blogspot.com/2007/06/simple-compiler-in-my-last-post-i.html Compiling a DSL to x86 assembly]<br />
** [http://augustss.blogspot.com/2007/06/disassembly-harpy-package-also-contains.html Disassembling x86]<br />
** [http://augustss.blogspot.com/2007/06/generating-more-code-with-harpy-after.html Generating more code with Harpy]<br />
<br />
== Further reading ==<br />
<br />
* [http://haskell.org/haskellwiki/Research_papers/Domain_specific_languages#Domain_specific_languages Research papers on domain specific languages in Haskell]<br />
<br />
[[Category:Tutorials]]</div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Cafe_migrationHaskell Cafe migration2007-08-03T11:39:38Z<p>JohannesAhlmann: </p>
<hr />
<div>Often people post wonderful material to the mailing lists, hpaste.org or<br />
on #haskell. This can later be hard to find. The goal of this page is to<br />
collect a list of people who are happy for their contributions to the<br />
Haskell community, in any media, to be added directly to the Haskell wiki.<br />
<br />
If you are happy for your contributions (both new and old posts) on <br />
''any media that are part of the Haskell community'', including:<br />
<br />
* [[Mailing_lists|The mailing lists]] (haskell-cafe@, libraries@ and others)<br />
* [[IRC_channel|The IRC channel]]<br />
* [http://hpaste.org/ The Haskell Paste Bin]: hpaste.org<br />
* [[HaWiki_migration|The Old Haskell Wiki]]<br />
* And the new wiki.<br />
<br />
that ''are not specifically licensed'' to be treated as having been<br />
released under a [[HaskellWiki:Copyrights|Simple Permissive License]].<br />
please add your name to this list, so that others may move your<br />
contributions around haskell.org without fear.<br />
<br />
''Contributions will be licensed specifically under a<br />
[[HaskellWiki:Copyrights|Simple Permissive License]]''.<br />
<br />
* Albert Y. C. Lai (monochrom)<br />
* Andrew Bromage (aka Pseudonym)<br />
* Arthur van Leeuwen (aka earthy)<br />
* Bernie Pope<br />
* [[User:b7j0c | Brad Clawsie]]<br />
* Brandon Allbery<br />
* [[User:BrettGiles | Brett Giles]]<br />
* Bulat Ziganshin<br />
* Cale Gibbard<br />
* Chris Smith (cdsmith; blog also fair game)<br />
* Conor McBride<br />
* Conrad Parker<br />
* Dan Doel<br />
* Dan Piponi (aka sigfpe)<br />
* Derek Elkins<br />
* Dominic Steinitz<br />
* Don Stewart<br />
* Eric Kow (kowey; blog too)<br />
* Eric Mertens (glguy)<br />
* Henk-Jan van Tuyl<br />
* Ian Lynagh (Igloo)<br />
* Jan-Willem Maessen<br />
* Jonathan Cast<br />
* Neil Mitchell (ndm)<br />
* Richard Kelsall<br />
* Richard O'Keefe<br />
* Samuel Bronson (SamB)<br />
* ShaeErisson<br />
* Stefan O'Rear<br />
* Thorkil Naur<br />
* Tim Chevalier (aka Kirsten)<br />
* Tom Conway<br />
* Twan van Laarhoven (twanvl)<br />
* Simon Peyton Jones<br />
* Johannes Ahlmann (jethr0)<br />
<br />
[[Category:Community]]</div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Cafe_migrationHaskell Cafe migration2007-08-03T11:39:23Z<p>JohannesAhlmann: </p>
<hr />
<div>Often people post wonderful material to the mailing lists, hpaste.org or<br />
on #haskell. This can later be hard to find. The goal of this page is to<br />
collect a list of people who are happy for their contributions to the<br />
Haskell community, in any media, to be added directly to the Haskell wiki.<br />
<br />
If you are happy for your contributions (both new and old posts) on <br />
''any media that are part of the Haskell community'', including:<br />
<br />
* [[Mailing_lists|The mailing lists]] (haskell-cafe@, libraries@ and others)<br />
* [[IRC_channel|The IRC channel]]<br />
* [http://hpaste.org/ The Haskell Paste Bin]: hpaste.org<br />
* [[HaWiki_migration|The Old Haskell Wiki]]<br />
* And the new wiki.<br />
<br />
that ''are not specifically licensed'' to be treated as having been<br />
released under a [[HaskellWiki:Copyrights|Simple Permissive License]].<br />
please add your name to this list, so that others may move your<br />
contributions around haskell.org without fear.<br />
<br />
''Contributions will be licensed specifically under a<br />
[[HaskellWiki:Copyrights|Simple Permissive License]]''.<br />
<br />
* Albert Y. C. Lai (monochrom)<br />
* Andrew Bromage (aka Pseudonym)<br />
* Arthur van Leeuwen (aka earthy)<br />
* Bernie Pope<br />
* [[User:b7j0c | Brad Clawsie]]<br />
* Brandon Allbery<br />
* [[User:BrettGiles | Brett Giles]]<br />
* Bulat Ziganshin<br />
* Cale Gibbard<br />
* Chris Smith (cdsmith; blog also fair game)<br />
* Conor McBride<br />
* Conrad Parker<br />
* Dan Doel<br />
* Dan Piponi (aka sigfpe)<br />
* Derek Elkins<br />
* Dominic Steinitz<br />
* Don Stewart<br />
* Eric Kow (kowey; blog too)<br />
* Eric Mertens (glguy)<br />
* Henk-Jan van Tuyl<br />
* Ian Lynagh (Igloo)<br />
* Jan-Willem Maessen<br />
* Jonathan Cast<br />
* Neil Mitchell (ndm)<br />
* Richard Kelsall<br />
* Richard O'Keefe<br />
* Samuel Bronson (SamB)<br />
* ShaeErisson<br />
* Stefan O'Rear<br />
* Thorkil Naur<br />
* Tim Chevalier (aka Kirsten)<br />
* Tom Conway<br />
* Twan van Laarhoven (twanvl)<br />
* Simon Peyton Jones<br />
* Johannes Ahlmann<br />
<br />
[[Category:Community]]</div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Quiz/Sokoban/Solution_Jethr0Haskell Quiz/Sokoban/Solution Jethr02007-07-19T11:08:16Z<p>JohannesAhlmann: </p>
<hr />
<div>[[Category:Haskell Quiz solutions|Countdown]]<br />
<br />
Obviously the most uncool kind of interface you could imagine. No readline, no clearscreen, you name it. But I was kinda reminded of the "good ole' days" when writing/playing this ;)<br />
<br />
<haskell><br />
module Main where<br />
<br />
import Prelude hiding (Either(..))<br />
import qualified Data.List as L<br />
import qualified Data.Char as C<br />
import Control.Monad<br />
import System.IO (getChar, hSetEcho, stdin)<br />
<br />
type Coord = (Int,Int)<br />
<br />
(|+|) :: Coord -> Coord -> Coord<br />
(a,b) |+| (c,d) = (a+c, b+d)<br />
<br />
data Move = Up | Down | Left | Right deriving (Show,Eq)<br />
<br />
data SokoState = SokoState {sWalls, sCrates, sStorages :: [Coord]<br />
,sWorker :: Coord<br />
,sSteps :: Int} <br />
deriving (Eq)<br />
<br />
modifyWalls f st = st{sWalls = f . sWalls $ st}<br />
modifyCrates f st = st{sCrates = f . sCrates $ st}<br />
modifyStorages f st = st{sStorages = f . sStorages $ st}<br />
modifyWorker f st = st{sWorker = f . sWorker $ st}<br />
modifySteps f st = st{sSteps = f . sSteps $ st}<br />
<br />
moveToCoord :: Move -> Coord<br />
moveToCoord Up = ( 0,-1)<br />
moveToCoord Down = ( 0, 1)<br />
moveToCoord Left = (-1, 0)<br />
moveToCoord Right = ( 1, 0)<br />
<br />
<br />
-- given a move and a state, compute the next state<br />
step :: Move -> SokoState -> SokoState<br />
step move state <br />
| isWall next1 = state<br />
| isCrate next1 =<br />
if isWall next2 || isCrate next2<br />
then state<br />
else modifyCrates ((next2:) . (filter (next1/=))) moveWorker<br />
| otherwise = moveWorker<br />
where SokoState{sWalls = walls, sCrates = crates, sWorker = worker} = state<br />
moveCoord = moveToCoord move<br />
next1 = worker |+| moveCoord<br />
next2 = next1 |+| moveCoord<br />
isCrate = (`elem` crates)<br />
isWall = (`elem` walls)<br />
moveWorker = modifySteps (+1) state{sWorker = next1}<br />
<br />
<br />
-- check if a level is solved by comparing crate and storage locations<br />
finished :: SokoState -> Bool<br />
finished SokoState{sCrates = cs, sStorages = ss} =<br />
L.sort cs == L.sort ss<br />
<br />
<br />
---<br />
<br />
<br />
drawState :: SokoState -> [String]<br />
drawState state@SokoState{sWalls = ws, sCrates = cs, sStorages = ss<br />
,sWorker = wrk, sSteps = steps} =<br />
show steps : [[charRep (x,y) | x <- [0..maxX]] | y <- [0..maxY]]<br />
where <br />
maxX = maximum $ map fst ws<br />
maxY = maximum $ map snd ws<br />
<br />
charRep coord<br />
| isWorker && isStorage = '+'<br />
| isCrate && isStorage = '*'<br />
| isWorker = '@'<br />
| isCrate = 'o'<br />
| isStorage = '.'<br />
| isWall = '#'<br />
| otherwise = ' '<br />
where isWorker = coord == wrk<br />
isCrate = coord `elem` cs<br />
isStorage = coord `elem` ss<br />
isWall = coord `elem` ws<br />
<br />
instance Show SokoState where<br />
show = unlines . drawState<br />
<br />
<br />
-- recreate a level from its ascii representation<br />
fromLevel :: [String] -> SokoState<br />
fromLevel level = foldl newCell emptyState $ (concat cells)<br />
where cells = map (\(y,xs) -> zipWith (\x c -> ((x,y),c)) [0..] xs) <br />
(zip [0..] level)<br />
newCell st (coord,char) = <br />
case char of<br />
'#' -> modifyWalls (coord:) st<br />
'o' -> modifyCrates (coord:) st<br />
'.' -> modifyStorages (coord:) st<br />
'*' -> modifyStorages (coord:) . modifyCrates (coord:) $ st<br />
'+' -> modifyStorages (coord:) . modifyWorker (const coord) $ st<br />
'@' -> modifyWorker (const coord) st<br />
otherwise -> st<br />
<br />
<br />
emptyState = SokoState {sWalls = []<br />
,sStorages = []<br />
,sCrates = []<br />
,sWorker = (0,0) -- *brr*<br />
,sSteps = 0<br />
}<br />
<br />
<br />
---<br />
<br />
<br />
-- ask for input until the level is solved<br />
-- TODO: add key to quit<br />
loop st = do<br />
print st<br />
c <- getChar<br />
let move = case c of <br />
'j' -> step Left<br />
'k' -> step Down<br />
'l' -> step Right<br />
'i' -> step Up<br />
otherwise -> id<br />
st' = move st<br />
if finished st' <br />
then print st' >> print "you won"<br />
else loop st' <br />
<br />
<br />
main = do<br />
hSetEcho stdin False<br />
loop $ fromLevel level_1<br />
hSetEcho stdin True<br />
<br />
<br />
---<br />
<br />
<br />
level_1 = [<br />
"#########",<br />
"# #",<br />
"# oo #",<br />
"# #. @#",<br />
"# . #",<br />
"#########"<br />
]<br />
<br />
</haskell></div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Quiz/SokobanHaskell Quiz/Sokoban2007-07-19T11:04:57Z<p>JohannesAhlmann: </p>
<hr />
<div>This week's quiz is to implement the game of Sokoban with the interface of your choosing and any extra features you would like to have.<br />
<br />
==The Problem==<br />
<br />
* http://www.rubyquiz.com/quiz5.html<br />
<br />
==Solutions==<br />
<br />
* [[Haskell Quiz/Sokoban/Solution Jethr0|Jethr0]]<br />
<br />
[[Category:Haskell Quiz|Sokoban]]</div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_QuizHaskell Quiz2007-07-19T11:02:19Z<p>JohannesAhlmann: added #5 sokoban</p>
<hr />
<div>A collection of solutions to the [http://www.rubyquiz.com Ruby quiz] puzzles in simple, elegant Haskell.<br />
<br />
As you solve the puzzles, please contribute your code, and create a page<br />
for the puzzle entries. When creating a new page for your source, be<br />
sure to categorise it as code, with a [ [ Category:Code ] ] tag.<br />
<br />
== The Puzzles ==<br />
<br />
1. [[Haskell Quiz/The Solitaire Cipher|The Solitaire Cipher]]<br />
<br />
2. [[Haskell Quiz/Secret Santas|Secret Santas]]<br />
<br />
5. [[Haskell Quiz/Sokoban|Sokoban]]<br />
<br />
7. [[Haskell Quiz/Countdown|Countdown]]<br />
<br />
15. [[Haskell Quiz/Animal Quiz|Animal Quiz]]<br />
<br />
19. [[Haskell Quiz/Yahtzee|Yahtzee]]<br />
<br />
20. [[Haskell Quiz/Phone Number Words|Phone Number Words]]<br />
<br />
22. [[Haskell Quiz/Roman Numerals|Roman Numerals]]<br />
<br />
25. [[Haskell Quiz/English Numerals|English Numerals]]<br />
<br />
27. [[Haskell Quiz/Knight's Travails|Knight's Travails]]<br />
<br />
31. [[Haskell Quiz/Amazing Mazes|Amazing Mazes]]<br />
<br />
33. [[Haskell Quiz/Tiling Turmoil|Tiling Turmoil]]<br />
<br />
39. [[Haskell Quiz/Sampling|Sampling]]<br />
<br />
43. [[Haskell Quiz/Sodoku Solver|Sodoku Solver]]<br />
<br />
54. [[Haskell Quiz/Index and Query|Text Index and Query]]<br />
<br />
57. [[Haskell Quiz/Weird Numbers|Weird Numbers]]<br />
<br />
60. [[Haskell Quiz/Numeric Maze|Numeric Maze]]<br />
<br />
63. [[Haskell Quiz/Grid Folding|Grid Folding]]<br />
<br />
65. [[Haskell Quiz/Splitting the Loot|Splitting the Loot]]<br />
<br />
70. [[Haskell Quiz/Constraint Processing|Constraint Processing]] <br />
<br />
76. [[Haskell Quiz/Text Munger|Text Munger]]<br />
<br />
77. [[Haskell Quiz/Cat2Rafb|cat2rafb]]<br />
<br />
84. [[Haskell Quiz/PP Pascal|PP Pascal]]<br />
<br />
88. [[Haskell Quiz/Chip Eight|Chip Eight]]<br />
<br />
92. [[Haskell Quiz/DayRange|DayRange]]<br />
<br />
93. [[Haskell Quiz/Happy Numbers|Happy Numbers]]<br />
<br />
97. [[Haskell Quiz/Posix Pangrams|Posix Pangrams]]<br />
<br />
98. [[Haskell Quiz/Astar|A*]]<br />
<br />
99. [[Haskell Quiz/Fuzzy Time|Fuzzy Time]]<br />
<br />
100. [[Haskell Quiz/Bytecode Compiler|Bytecode Compiler]]<br />
<br />
106. [[Haskell Quiz/Chess960|Chess960]]<br />
<br />
107. [[Haskell Quiz/Word Search|Word Search]]<br />
<br />
108. [[Haskell Quiz/Word Blender|Word Blender]]<br />
<br />
114. [[Haskell Quiz/Housie|Housie]]<br />
<br />
117. [[Haskell Quiz/SimFrost|SimFrost]]<br />
<br />
121. [[Haskell Quiz/Morse Code|Morse Code]]<br />
<br />
122. [[Haskell Quiz/Credit Cards|Checking Credit Cards]]<br />
<br />
128. [[Haskell Quiz/Verbal Arithmetic|Verbal Arithmetic]]<br />
<br />
==Possibly fun ones not yet done in haskell==<br />
<br />
3. Geodesic Dome Faces http://www.rubyquiz.com/quiz3.html<br />
<br />
11. Learning Tic-Tac-Toe http://www.rubyquiz.com/quiz11.html<br />
<br />
37. Inference Engine http://www.rubyquiz.com/quiz37.html<br />
<br />
48. Math Captcha http://www.rubyquiz.com/quiz48.html<br />
<br />
49. Text Image http://www.rubyquiz.com/quiz50.html (Not sure how image loading will work)<br />
<br />
85. C-Style Ints http://www.rubyquiz.com/quiz85.html<br />
<br />
87. Negative Sleep http://www.rubyquiz.com/quiz87.html (As a Monad!!!)<br />
<br />
88. Chip-8 http://www.rubyquiz.com/quiz88.html<br />
<br />
Many weren't included because of either clumsy ASCII output, or requiring a dictionary. Perhaps a dictionary module could be created and those problems attacked in a unified fashion.<br />
<br />
[[Category:Code]]<br />
[[Category:Haskell Quiz|*]]</div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Quiz/Verbal_Arithmetic/Solution_Jethr0Haskell Quiz/Verbal Arithmetic/Solution Jethr02007-07-15T21:54:44Z<p>JohannesAhlmann: </p>
<hr />
<div>[[Category:Haskell Quiz solutions|Verbal Arithmetic]]<br />
<br />
I'm using a StateT monad inside a list monad for backtracking. The State monad keeps track of the digits associated with characters and also a carry state, that remembers the carried number from prior additions.<br />
<br />
Several constraints are already implemented (like leading digits not being zero, all associations being unique), but of course there could be lot added (checking for zero, even/odd-ness, ...)<br />
<br />
Solution should be far quicker than generic brute-force/backtracking since it tries to fail as early as possible and with more elaborate constraints it should become even faster!<br />
<br />
I couldn't be bothered to write yet another regexp/parser, as that didn't really interest me.<br />
<br />
<haskell><br />
module Main where<br />
<br />
import qualified Data.Map as Map<br />
import qualified Data.List as List<br />
import Data.Char (intToDigit)<br />
import Control.Monad<br />
import Control.Monad.State<br />
import Data.Maybe (fromJust)<br />
<br />
type Carry = Integer<br />
type Assocs = Map.Map Char Integer<br />
type St = (Assocs, Carry)<br />
<br />
parts = ["forty", "ten", "ten"]<br />
result = "sixty"<br />
<br />
<br />
solve :: [String] -> String -> StateT St [] ()<br />
solve parts' res' = do<br />
let constraints = makeConstraints parts' res'<br />
mapM_ (setDigitPairs constraints) digitPairs<br />
<br />
(_, carry) <- get<br />
guard $ carry == 0<br />
<br />
where digitPairs = zip ps' (reverse res')<br />
ps' = (List.transpose . map reverse $ parts) ++ repeat ""<br />
<br />
<br />
{- construct constraints from actual data<br />
TODO: a+b=a => b=0<br />
a+a=c => c even<br />
-}<br />
makeConstraints :: [String] -> String -> [StateT St [] ()]<br />
makeConstraints parts' res' =<br />
-- leading digits shouldn't be zero<br />
map (constraintCheck (guard . (0/=))) firsts<br />
where firsts = map head (res' : parts)<br />
constraintCheck cstr c = do<br />
(s,_) <- get<br />
case Map.lookup c s of <br />
Nothing -> return ()<br />
Just i -> cstr i<br />
<br />
<br />
-- set digits, make per-digit check with carry and apply constraints<br />
setDigitPairs cstrs (ds,res) = do<br />
ls <- mapM placer ds<br />
r <- placer res<br />
<br />
(_,carry) <- get<br />
let r' = sum ls + carry<br />
guard $ r' `mod` 10 == r<br />
<br />
let carry' = r' `div` 10<br />
modify (\(a,_) -> (a,carry'))<br />
<br />
sequence cstrs<br />
<br />
<br />
-- place number if not yet set and check for uniqueness,<br />
-- otherwise return already set value<br />
placer :: Char -> StateT St [] Integer<br />
placer l = do<br />
(assoc,_) <- get<br />
case Map.lookup l assoc of<br />
Just i -> return i<br />
Nothing -> do<br />
a <- lift [0..9]<br />
guard $ a `notElem` (Map.elems assoc)<br />
modify (\(ass,c) -> (Map.insert l a ass, c))<br />
return a<br />
<br />
<br />
main = mapM_ print . Map.toList . fst . head $ <br />
execStateT (solve parts result) (Map.empty :: Assocs, 0)<br />
<br />
<br />
</haskell></div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Quiz/Chip_Eight/Solution_Jethr0Haskell Quiz/Chip Eight/Solution Jethr02007-07-15T21:51:00Z<p>JohannesAhlmann: added a few comments</p>
<hr />
<div>[[Category:Haskell Quiz solutions|Chip Eight]]<br />
<br />
Interpreter isn't fully tested, but the sample program seems to be "running" correctly.<br />
<br />
<haskell><br />
module Main where<br />
<br />
import qualified Data.Array as Array<br />
import qualified Data.Bits as Bits<br />
import qualified Data.Char as Char<br />
import Data.Word (Word8, Word16)<br />
import Data.Bits ((.&.), (.|.), shiftL, shiftR)<br />
import Data.Array ((!), (//), Array, listArray, accumArray)<br />
import Control.Monad (when)<br />
import Control.Monad.State (get, put, modify, liftIO, execStateT, StateT)<br />
import Control.Monad.Identity<br />
import Numeric (showHex, showIntAtBase)<br />
import Text.Printf (printf)<br />
import System.Random (randomR, mkStdGen, StdGen, newStdGen)<br />
<br />
numRegisters = 16<br />
sizeMemory = 2^12<br />
<br />
data MachineState = MachineState {<br />
rv :: Array Int Word8,<br />
rip :: Word16,<br />
rmemory :: Array Int Word8,<br />
rand :: StdGen<br />
}<br />
<br />
instance Show MachineState where<br />
show MachineState {rv = regs, rmemory = mem, rip = ip} =<br />
unlines showRegs ++ "IP: " ++ (printf "%08x" (fromIntegral ip :: Integer))<br />
where showRegs = zipWith (\r v -> r ++ ": " ++ v) regNames regValues<br />
regNames = [printf "V%x" (fromIntegral x :: Integer) | x <- [0..]]<br />
--regValues = [printf "%04x" (fromIntegral x :: Integer) | x <- Array.elems regs]<br />
regValues = [showIntAtBase 2 Char.intToDigit x "" | x <- Array.elems regs]<br />
<br />
type StT = StateT MachineState<br />
type St = StT Identity<br />
type Offset = Int<br />
<br />
<br />
---<br />
<br />
modify_rv func st = st{rv = func . rv $ st}<br />
modify_rip func st = st{rip = func . rip $ st}<br />
modify_rmemory func st = st{rmemory = func . rmemory $ st}<br />
getReg x st = let MachineState{rv = regs} = st in regs!x<br />
setReg x val st = modify_rv (// [(fromIntegral x, val)]) st<br />
<br />
<br />
eval :: Word16 -> MachineState -> MachineState<br />
eval instr st = case firstDigit instr of<br />
-- 0x1NNN<br />
0x1 -> <br />
modify_rip (const nnn) st<br />
where nnn = instr .&. 0x0FFF<br />
<br />
-- 0x3XKK<br />
0x3 -><br />
if vx == kk <br />
then modify_rip (2+) st <br />
else st<br />
<br />
-- 0x6XKK<br />
0x6 -> <br />
setReg x kk st<br />
<br />
-- 0x7XKK<br />
0x7 -> <br />
rPlus x vx kk st<br />
<br />
-- 0x8XY_<br />
0x8 -> <br />
(case instr .&. 0x000F of <br />
0x0 -> setReg x vy <br />
0x1 -> setReg x (vx .|. vy)<br />
0x2 -> setReg x (vx .&. vy)<br />
0x3 -> setReg x (vx `Bits.xor` vy)<br />
0x4 -> rPlus x vx vy<br />
0x5 -> rMinus x vx vy<br />
0x6 -> rShiftR x vx 1 <br />
0x7 -> rMinus x vy vx<br />
0xE -> rShiftL x vx 1<br />
) st<br />
where y = fromIntegral $ shiftR (instr .&. 0x00F0) 4<br />
vy = getReg y st<br />
<br />
-- 0xCXKK<br />
0xC -> <br />
setReg x (r .&. kk) st'<br />
where (r, st') = rRandom st<br />
<br />
otherwise -> <br />
error $ "opcode not implemented " ++ showHex instr ""<br />
<br />
where x = fromIntegral $ shiftR (instr .&. 0x0F00) 8<br />
vx = getReg x st<br />
kk = fromIntegral $ instr .&. 0x00FF<br />
(>.>) = flip ($)<br />
<br />
firstDigit w = fromIntegral $ shiftR w 12<br />
<br />
rRandom s = (fromIntegral r, s{rand = gen})<br />
where MachineState{rand = gen} = s<br />
(r, gen') = randomR (0, 2^8-1) gen<br />
<br />
rPlus target a b s =<br />
s<br />
>.> setReg 0xF (if sum >= 2^8 then 1 else 0)<br />
>.> setReg target ((fromIntegral sum) .&. 0x00FF)<br />
where sum = (fromIntegral a) + (fromIntegral b) :: Integer<br />
<br />
rMinus target a b s =<br />
s<br />
>.> setReg 0xF (if (sum < 0) then 0 else 1)<br />
>.> setReg target (fromIntegral (if (sum < 0) then (sum + 2^8) <br />
else sum))<br />
where sum = (fromIntegral a) - (fromIntegral b) :: Integer<br />
<br />
rShiftR target vx n s = <br />
s <br />
>.> setReg 0xF (vx .&. 0x01)<br />
>.> setReg target (shiftR vx n)<br />
<br />
rShiftL target vx n s =<br />
s<br />
>.> setReg 0xF (shiftR (vx .&. 0x80) 7) -- FIXME: is this correct<br />
>.> setReg target (shiftL vx n)<br />
<br />
---<br />
<br />
<br />
initialState :: StdGen -> MachineState<br />
initialState gen = MachineState {<br />
rv = accumArray const 0 (0, numRegisters-1) [],<br />
rmemory = accumArray const 0 (0, sizeMemory-1) [],<br />
rip = 0,<br />
rand = gen<br />
}<br />
<br />
<br />
modifyMemory :: Offset -> [Word8] -> MachineState -> MachineState<br />
modifyMemory offset words state = <br />
state{rmemory = rmemory state // zip [offset..] words}<br />
<br />
modifyRegisters :: [(Int, Word8)] -> MachineState -> MachineState<br />
modifyRegisters pairs state = <br />
state{rv = rv state // pairs}<br />
<br />
<br />
step :: St ()<br />
step = do<br />
MachineState{rip = ip, rmemory = mem} <- get<br />
let (i1,i2) = (fromIntegral $ mem ! (fromIntegral ip)<br />
,fromIntegral $ mem ! (fromIntegral $ ip+1))<br />
instr = (shiftL i1 8) + i2 :: Word16<br />
case instr of<br />
0x0000 -> return ()<br />
otherwise -> do<br />
modify $ eval instr<br />
modify $ modify_rip (+2)<br />
step<br />
<br />
<br />
main = do<br />
g <- newStdGen<br />
file <- readFile "Chip8Test"<br />
let program = map (fromIntegral . Char.ord) file<br />
start = initialState g<br />
new = modifyMemory 0 program<br />
. modifyRegisters []<br />
$ start<br />
let res = runIdentity $ execStateT step new<br />
print res<br />
<br />
</haskell></div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Quiz/Chip_Eight/Solution_Jethr0Haskell Quiz/Chip Eight/Solution Jethr02007-07-15T19:36:11Z<p>JohannesAhlmann: more pure version</p>
<hr />
<div>[[Category:Haskell Quiz solutions|Chip Eight]]<br />
<br />
Interpreter isn't fully tested, but the sample program seems to be "running" correctly.<br />
<br />
<haskell><br />
module Main where<br />
<br />
import qualified Data.Array as Array<br />
import qualified Data.Bits as Bits<br />
import qualified Data.Char as Char<br />
import Data.Word (Word8, Word16)<br />
import Data.Bits ((.&.), (.|.), shiftL, shiftR)<br />
import Data.Array ((!), (//), Array, listArray, accumArray)<br />
import Control.Monad (when)<br />
import Control.Monad.State (get, put, modify, liftIO, execStateT, StateT)<br />
import Control.Monad.Identity<br />
import Numeric (showHex, showIntAtBase)<br />
import Text.Printf (printf)<br />
import System.Random (randomR, mkStdGen, StdGen, newStdGen)<br />
<br />
numRegisters = 16<br />
sizeMemory = 2^12<br />
<br />
data MachineState = MachineState {<br />
rv :: Array Int Word8,<br />
rip :: Word16,<br />
rmemory :: Array Int Word8,<br />
rand :: StdGen<br />
}<br />
<br />
instance Show MachineState where<br />
show MachineState {rv = regs, rmemory = mem, rip = ip} =<br />
unlines showRegs ++ "IP: " ++ (printf "%08x" (fromIntegral ip :: Integer))<br />
where showRegs = zipWith (\r v -> r ++ ": " ++ v) regNames regValues<br />
regNames = [printf "V%x" (fromIntegral x :: Integer) | x <- [0..]]<br />
--regValues = [printf "%04x" (fromIntegral x :: Integer) | x <- Array.elems regs]<br />
regValues = [showIntAtBase 2 Char.intToDigit x "" | x <- Array.elems regs]<br />
<br />
type StT = StateT MachineState<br />
type St = StT Identity<br />
type Offset = Int<br />
<br />
<br />
---<br />
<br />
modify_rv func st = st{rv = func . rv $ st}<br />
modify_rip func st = st{rip = func . rip $ st}<br />
modify_rmemory func st = st{rmemory = func . rmemory $ st}<br />
getReg x st = let MachineState{rv = regs} = st in regs!x<br />
setReg x val st = modify_rv (// [(fromIntegral x, val)]) st<br />
<br />
<br />
eval :: Word16 -> MachineState -> MachineState<br />
eval instr st = case firstDigit instr of<br />
0x1 -> <br />
modify_rip (const nnn) st<br />
where nnn = instr .&. 0x0FFF<br />
<br />
0x3 -><br />
if vx == kk <br />
then modify_rip (2+) st <br />
else st<br />
<br />
0x6 -> <br />
setReg x kk st<br />
<br />
0x7 -> <br />
rPlus x vx kk st<br />
<br />
0x8 -> <br />
(case instr .&. 0x000F of <br />
0x0 -> setReg x vy <br />
0x1 -> setReg x (vx .|. vy)<br />
0x2 -> setReg x (vx .&. vy)<br />
0x3 -> setReg x (vx `Bits.xor` vy)<br />
0x4 -> rPlus x vx vy<br />
0x5 -> rMinus x vx vy<br />
0x6 -> rShiftR x vx 1 <br />
0x7 -> rMinus x vy vx<br />
0xE -> rShiftL x vx 1<br />
) st<br />
where y = fromIntegral $ shiftR (instr .&. 0x00F0) 4<br />
vy = getReg y st<br />
<br />
0xC -> <br />
setReg x (r .&. kk) st'<br />
where (r, st') = rRandom st<br />
<br />
otherwise -> <br />
error $ "opcode not implemented " ++ showHex instr ""<br />
<br />
where x = fromIntegral $ shiftR (instr .&. 0x0F00) 8<br />
vx = getReg x st<br />
kk = fromIntegral $ instr .&. 0x00FF<br />
(>.>) = flip ($)<br />
<br />
firstDigit w = fromIntegral $ shiftR w 12<br />
<br />
rRandom s = (fromIntegral r, s{rand = gen})<br />
where MachineState{rand = gen} = s<br />
(r, gen') = randomR (0, 2^8-1) gen<br />
<br />
rPlus target a b s =<br />
s<br />
>.> setReg 0xF (if sum >= 2^8 then 1 else 0)<br />
>.> setReg target ((fromIntegral sum) .&. 0x00FF)<br />
where sum = (fromIntegral a) + (fromIntegral b) :: Integer<br />
<br />
rMinus target a b s =<br />
s<br />
>.> setReg 0xF (if (sum < 0) then 0 else 1)<br />
>.> setReg target (fromIntegral (if (sum < 0) then (sum + 2^8) <br />
else sum))<br />
where sum = (fromIntegral a) - (fromIntegral b) :: Integer<br />
<br />
rShiftR target vx n s = <br />
s <br />
>.> setReg 0xF (vx .&. 0x01)<br />
>.> setReg target (shiftR vx n)<br />
<br />
rShiftL target vx n s =<br />
s<br />
>.> setReg 0xF (shiftR (vx .&. 0x80) 7) -- FIXME: is this correct<br />
>.> setReg target (shiftL vx n)<br />
<br />
---<br />
<br />
<br />
initialState :: StdGen -> MachineState<br />
initialState gen = MachineState {<br />
rv = accumArray const 0 (0, numRegisters-1) [],<br />
rmemory = accumArray const 0 (0, sizeMemory-1) [],<br />
rip = 0,<br />
rand = gen<br />
}<br />
<br />
<br />
modifyMemory :: Offset -> [Word8] -> MachineState -> MachineState<br />
modifyMemory offset words state = <br />
state{rmemory = rmemory state // zip [offset..] words}<br />
<br />
modifyRegisters :: [(Int, Word8)] -> MachineState -> MachineState<br />
modifyRegisters pairs state = <br />
state{rv = rv state // pairs}<br />
<br />
<br />
step :: St ()<br />
step = do<br />
MachineState{rip = ip, rmemory = mem} <- get<br />
let (i1,i2) = (fromIntegral $ mem ! (fromIntegral ip)<br />
,fromIntegral $ mem ! (fromIntegral $ ip+1))<br />
instr = (shiftL i1 8) + i2 :: Word16<br />
case instr of<br />
0x0000 -> return ()<br />
otherwise -> do<br />
modify $ eval instr<br />
modify $ modify_rip (+2)<br />
step<br />
<br />
<br />
main = do<br />
g <- newStdGen<br />
file <- readFile "Chip8Test"<br />
let program = map (fromIntegral . Char.ord) file<br />
start = initialState g<br />
new = modifyMemory 0 program<br />
. modifyRegisters []<br />
$ start<br />
let res = runIdentity $ execStateT step new<br />
print res<br />
<br />
</haskell></div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Quiz/Chip_Eight/Solution_Jethr0Haskell Quiz/Chip Eight/Solution Jethr02007-07-13T13:49:22Z<p>JohannesAhlmann: </p>
<hr />
<div>[[Category:Haskell Quiz solutions|Chip Eight]]<br />
<br />
As vincenz pointed out in one of my other solutions, I'm probably using State too heavily now that I've (hopefully) figured out how to use it ;)<br />
<br />
At the moment the <hask>eval</hask> function could be written in pure fashion and maybe I'll do that refactoring some time. Interpreter isn't fully tested, but the sample program seems to be "running" correctly<br />
<br />
<haskell><br />
module Main where<br />
<br />
import qualified Data.Array as Array<br />
import qualified Data.Bits as Bits<br />
import qualified Data.Char as Char<br />
import Data.Word (Word8, Word16)<br />
import Data.Bits ((.&.), (.|.), shiftL, shiftR)<br />
import Data.Array ((!), (//), Array, listArray, accumArray)<br />
import Control.Monad (when)<br />
import Control.Monad.State (get, put, modify, liftIO, execStateT, StateT)<br />
import Control.Monad.Identity<br />
import Numeric (showHex, showIntAtBase)<br />
import Text.Printf (printf)<br />
import System.Random (randomR, mkStdGen, StdGen, newStdGen)<br />
<br />
numRegisters = 16<br />
sizeMemory = 2^12<br />
<br />
data MachineState = MachineState {<br />
rv :: Array Int Word8,<br />
rip :: Word16,<br />
rmemory :: Array Int Word8,<br />
rand :: StdGen<br />
}<br />
<br />
instance Show MachineState where<br />
show MachineState {rv = regs, rmemory = mem, rip = ip} =<br />
unlines showRegs ++ "IP: " ++ (printf "%08x" (fromIntegral ip :: Integer))<br />
where showRegs = zipWith (\r v -> r ++ ": " ++ v) regNames regValues<br />
regNames = [printf "V%x" (fromIntegral x :: Integer) | x <- [0..]]<br />
--regValues = [printf "%04x" (fromIntegral x :: Integer) | x <- Array.elems regs]<br />
regValues = [showIntAtBase 2 Char.intToDigit x "" | x <- Array.elems regs]<br />
<br />
type StT = StateT MachineState<br />
type St = StT Identity<br />
type Offset = Int<br />
<br />
<br />
---<br />
<br />
modify_rv func = modify (\st -> st{rv = func . rv $ st})<br />
modify_rip func = modify (\st -> st{rip = func . rip $ st})<br />
modify_rmemory func = modify (\st -> st{rmemory = func . rmemory $ st})<br />
getReg x = do {MachineState{rv = regs} <- get; return $ regs!x}<br />
setReg x val = modify_rv (// [(fromIntegral x, val)])<br />
<br />
<br />
step :: St ()<br />
step = do<br />
MachineState{rip = ip, rmemory = mem} <- get<br />
let (i1,i2) = (fromIntegral $ mem ! (fromIntegral ip)<br />
,fromIntegral $ mem ! (fromIntegral $ ip+1))<br />
instr = (shiftL i1 8) + i2 :: Word16<br />
case instr of<br />
0x0000 -> return ()<br />
otherwise -> eval instr >> modify_rip (2+) >> step<br />
<br />
<br />
eval :: Word16 -> St ()<br />
eval instr = case firstDigit instr of<br />
0x1 -> do<br />
let nnn = instr .&. 0x0FFF<br />
modify_rip (const nnn)<br />
<br />
0x3 -> do<br />
let (x, kk) = (bitX, bitKK)<br />
vx <- getReg x<br />
when (vx == kk) (modify_rip (2+))<br />
<br />
0x6 -> do<br />
let (x, kk) = (bitX, bitKK)<br />
setReg x kk<br />
<br />
0x7 -> do<br />
let (x, kk) = (bitX, bitKK)<br />
vx <- getReg x<br />
rPlus x vx kk<br />
<br />
0x8 -> do<br />
let x = bitX<br />
y = fromIntegral $ shiftR (instr .&. 0x00F0) 4<br />
vx <- getReg x<br />
vy <- getReg y<br />
case (instr .&. 0x000F) of <br />
0x0 -> setReg x $ vy<br />
0x1 -> setReg x $ vx .|. vy<br />
0x2 -> setReg x $ vx .&. vy<br />
0x3 -> setReg x $ vx `Bits.xor` vy<br />
0x4 -> rPlus x vx vy<br />
0x5 -> rMinus x vx vy<br />
0x6 -> rShiftR x vx 1<br />
0x7 -> rMinus x vy vx<br />
0xE -> rShiftL x vx 1<br />
where rShiftR target vx n = do<br />
setReg 0xF $ vx .&. 0x01<br />
setReg target $ shiftR vx n<br />
rShiftL target vx n = do<br />
setReg 0xF $ shiftR (vx .&. 0x80) 7 -- FIXME: is this correct<br />
setReg target $ shiftL vx n<br />
<br />
0xC -> do<br />
let (x, kk) = (bitX, bitKK)<br />
r <- rRandom<br />
setReg x $ r .&. kk<br />
<br />
otherwise -> <br />
error $ "opcode not implemented " ++ showHex instr ""<br />
<br />
where bitX = fromIntegral $ shiftR (instr .&. 0x0F00) 8<br />
bitKK = fromIntegral $ instr .&. 0x00FF<br />
<br />
firstDigit w = fromIntegral $ shiftR w 12<br />
<br />
rRandom = do<br />
state@MachineState{rand = gen} <- get<br />
let (r, gen') = randomR (0, 2^8-1) gen<br />
put state{rand = gen'}<br />
return $ fromIntegral r<br />
<br />
rPlus :: Integral i => i -> Word8 -> Word8 -> St ()<br />
rPlus target a b = do<br />
let sum = (fromIntegral a) + (fromIntegral b) :: Integer<br />
setReg 0xF $ if sum >= 2^8 then 1 else 0<br />
setReg target $ (fromIntegral sum) .&. 0x00FF<br />
<br />
rMinus :: Integral i => i -> Word8 -> Word8 -> St ()<br />
rMinus target a b = do<br />
let sum = (fromIntegral a) - (fromIntegral b) :: Integer<br />
setReg 0xF $ if (sum < 0) then 0 else 1<br />
setReg target . fromIntegral $ if (sum < 0) then (sum + 2^8) else sum<br />
<br />
<br />
---<br />
<br />
<br />
initialState :: StdGen -> MachineState<br />
initialState gen = MachineState {<br />
rv = accumArray const 0 (0, numRegisters-1) [],<br />
rmemory = accumArray const 0 (0, sizeMemory-1) [],<br />
rip = 0,<br />
rand = gen<br />
}<br />
<br />
<br />
modifyMemory :: Offset -> [Word8] -> MachineState -> MachineState<br />
modifyMemory offset words state = <br />
state{rmemory = rmemory state // zip [offset..] words}<br />
<br />
modifyRegisters :: [(Int, Word8)] -> MachineState -> MachineState<br />
modifyRegisters pairs state = <br />
state{rv = rv state // pairs}<br />
<br />
main = do<br />
g <- newStdGen<br />
file <- readFile "Chip8Test"<br />
let program = map (fromIntegral . Char.ord) file<br />
start = initialState g<br />
new = modifyMemory 0 program<br />
. modifyRegisters []<br />
$ start<br />
let res = runIdentity $ execStateT step new<br />
print res<br />
<br />
</haskell></div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Quiz/Chip_EightHaskell Quiz/Chip Eight2007-07-13T13:44:17Z<p>JohannesAhlmann: </p>
<hr />
<div>Chip 8 (#88)<br />
<br />
CHIP-8 was an interpreted language used in the 1970's for basic games like Pong.<br />
<br />
Your job is to make an emulator. It will only cover some basic parts of it, but all emulators have to start somewhere.<br />
<br />
==The Problem==<br />
<br />
http://www.rubyquiz.com/quiz88.html<br />
<br />
==Solutions==<br />
<br />
* [[Haskell Quiz/Chip Eight/Solution Jethr0|Jethr0]]<br />
<br />
[[Category:Haskell Quiz|Chip Eight]]</div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_QuizHaskell Quiz2007-07-13T13:42:01Z<p>JohannesAhlmann: added 88 - Chip Eight</p>
<hr />
<div>A collection of solutions to the [http://www.rubyquiz.com Ruby quiz] puzzles in simple, elegant Haskell.<br />
<br />
As you solve the puzzles, please contribute your code, and create a page<br />
for the puzzle entries. When creating a new page for your source, be<br />
sure to categorise it as code, with a [ [ Category:Code ] ] tag.<br />
<br />
== The Puzzles ==<br />
<br />
1. [[Haskell Quiz/The Solitaire Cipher|The Solitaire Cipher]]<br />
<br />
2. [[Haskell Quiz/Secret Santas|Secret Santas]]<br />
<br />
7. [[Haskell Quiz/Countdown|Countdown]]<br />
<br />
15. [[Haskell Quiz/Animal Quiz|Animal Quiz]]<br />
<br />
19. [[Haskell Quiz/Yahtzee|Yahtzee]]<br />
<br />
20. [[Haskell Quiz/Phone Number Words|Phone Number Words]]<br />
<br />
22. [[Haskell Quiz/Roman Numerals|Roman Numerals]]<br />
<br />
25. [[Haskell Quiz/English Numerals|English Numerals]]<br />
<br />
27. [[Haskell Quiz/Knight's Travails|Knight's Travails]]<br />
<br />
31. [[Haskell Quiz/Amazing Mazes|Amazing Mazes]]<br />
<br />
33. [[Haskell Quiz/Tiling Turmoil|Tiling Turmoil]]<br />
<br />
39. [[Haskell Quiz/Sampling|Sampling]]<br />
<br />
43. [[Haskell Quiz/Sodoku Solver|Sodoku Solver]]<br />
<br />
54. [[Haskell Quiz/Index and Query|Text Index and Query]]<br />
<br />
57. [[Haskell Quiz/Weird Numbers|Weird Numbers]]<br />
<br />
60. [[Haskell Quiz/Numeric Maze|Numeric Maze]]<br />
<br />
63. [[Haskell Quiz/Grid Folding|Grid Folding]]<br />
<br />
65. [[Haskell Quiz/Splitting the Loot|Splitting the Loot]]<br />
<br />
70. [[Haskell Quiz/Constraint Processing|Constraint Processing]] <br />
<br />
76. [[Haskell Quiz/Text Munger|Text Munger]]<br />
<br />
77. [[Haskell Quiz/Cat2Rafb|cat2rafb]]<br />
<br />
84. [[Haskell Quiz/PP Pascal|PP Pascal]]<br />
<br />
88. [[Haskell Quiz/Chip Eight|Chip Eight]]<br />
<br />
92. [[Haskell Quiz/DayRange|DayRange]]<br />
<br />
93. [[Haskell Quiz/Happy Numbers|Happy Numbers]]<br />
<br />
97. [[Haskell Quiz/Posix Pangrams|Posix Pangrams]]<br />
<br />
98. [[Haskell Quiz/Astar|A*]]<br />
<br />
99. [[Haskell Quiz/Fuzzy Time|Fuzzy Time]]<br />
<br />
100. [[Haskell Quiz/Bytecode Compiler|Bytecode Compiler]]<br />
<br />
106. [[Haskell Quiz/Chess960|Chess960]]<br />
<br />
107. [[Haskell Quiz/Word Search|Word Search]]<br />
<br />
108. [[Haskell Quiz/Word Blender|Word Blender]]<br />
<br />
114. [[Haskell Quiz/Housie|Housie]]<br />
<br />
117. [[Haskell Quiz/SimFrost|SimFrost]]<br />
<br />
121. [[Haskell Quiz/Morse Code|Morse Code]]<br />
<br />
122. [[Haskell Quiz/Credit Cards|Checking Credit Cards]]<br />
<br />
128. [[Haskell Quiz/Verbal Arithmetic|Verbal Arithmetic]]<br />
<br />
==Possibly fun ones not yet done in haskell==<br />
<br />
3. Geodesic Dome Faces http://www.rubyquiz.com/quiz3.html<br />
<br />
11. Learning Tic-Tac-Toe http://www.rubyquiz.com/quiz11.html<br />
<br />
37. Inference Engine http://www.rubyquiz.com/quiz37.html<br />
<br />
48. Math Captcha http://www.rubyquiz.com/quiz48.html<br />
<br />
49. Text Image http://www.rubyquiz.com/quiz50.html (Not sure how image loading will work)<br />
<br />
85. C-Style Ints http://www.rubyquiz.com/quiz85.html<br />
<br />
87. Negative Sleep http://www.rubyquiz.com/quiz87.html (As a Monad!!!)<br />
<br />
88. Chip-8 http://www.rubyquiz.com/quiz88.html<br />
<br />
Many weren't included because of either clumsy ASCII output, or requiring a dictionary. Perhaps a dictionary module could be created and those problems attacked in a unified fashion.<br />
<br />
[[Category:Code]]<br />
[[Category:Haskell Quiz|*]]</div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Quiz/Verbal_Arithmetic/Solution_Jethr0Haskell Quiz/Verbal Arithmetic/Solution Jethr02007-07-12T13:09:09Z<p>JohannesAhlmann: minor changes (using mapM instead of sequence, checking for zero final carry)</p>
<hr />
<div>[[Category:Haskell Quiz solutions|Verbal Arithmetic]]<br />
<br />
I'm using a StateT monad inside a list monad for backtracking. The State monad keeps track of the digits associated with characters and also a carry state, that remembers the carried number from prior additions.<br />
<br />
Several constraints are already implemented (like leading digits not being zero, all associations being unique), but of course there could be lot added (checking for zero, even/odd-ness, ...)<br />
<br />
Solution should be far quicker than generic brute-force/backtracking since it tries to fail as early as possible and with more elaborate constraints it should become even faster!<br />
<br />
I couldn't be bothered to write yet another regexp/parser, as that didn't really interest me.<br />
<br />
<haskell><br />
module Main where<br />
<br />
import qualified Data.Map as Map<br />
import qualified Data.List as List<br />
import Data.Char (intToDigit)<br />
import Control.Monad<br />
import Control.Monad.State<br />
import Data.Maybe (fromJust)<br />
<br />
type Carry = Integer<br />
type Assocs = Map.Map Char Integer<br />
type St = (Assocs, Carry)<br />
<br />
parts = ["forty", "ten", "ten"]<br />
result = "sixty"<br />
<br />
<br />
solve :: [String] -> String -> StateT St [] ()<br />
solve parts' res' = do<br />
let constraints = makeConstraints parts' res'<br />
mapM_ (setDigitPairs constraints) digitPairs<br />
<br />
(_, carry) <- get<br />
guard $ carry == 0<br />
<br />
where digitPairs = zip ps' (reverse res')<br />
ps' = (List.transpose . map reverse $ parts) ++ repeat ""<br />
<br />
<br />
{- construct constraints from actual data<br />
TODO: a+b=a => b=0<br />
a+a=c => c even<br />
-}<br />
makeConstraints :: [String] -> String -> [StateT St [] ()]<br />
makeConstraints parts' res' =<br />
-- leading digits shouldn't be zero<br />
map (constraintCheck (guard . (0/=))) firsts<br />
where firsts = map head (res' : parts)<br />
constraintCheck cstr c = do<br />
(s,_) <- get<br />
case Map.lookup c s of <br />
Nothing -> return ()<br />
Just i -> cstr i<br />
<br />
<br />
-- set digits, make per-digit check with carry and apply constraints<br />
setDigitPairs cstrs (ds,res) = do<br />
ls <- sequence . map placer $ ds<br />
r <- placer res<br />
<br />
(_,carry) <- get<br />
let r' = sum ls + carry<br />
guard $ r' `mod` 10 == r<br />
<br />
let carry' = r' `div` 10<br />
modify (\(a,_) -> (a,carry'))<br />
<br />
sequence cstrs<br />
<br />
<br />
-- place number if not yet set and check for uniqueness,<br />
-- otherwise return already set value<br />
placer :: Char -> StateT St [] Integer<br />
placer l = do<br />
(assoc,_) <- get<br />
case Map.lookup l assoc of<br />
Just i -> return i<br />
Nothing -> do<br />
a <- lift [0..9]<br />
guard $ a `notElem` (Map.elems assoc)<br />
modify (\(ass,c) -> (Map.insert l a ass, c))<br />
return a<br />
<br />
<br />
main = mapM_ print . Map.toList . fst . head $ <br />
execStateT (solve parts result) (Map.empty :: Assocs, 0)<br />
<br />
<br />
</haskell></div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Quiz/Verbal_ArithmeticHaskell Quiz/Verbal Arithmetic2007-07-12T10:49:33Z<p>JohannesAhlmann: added solution jethr0</p>
<hr />
<div>[[Category:Haskell Quiz|Verbal Arithmetic]]<br />
<br />
The object of this quiz was to solve cryptarithmetic problems, where one assigns digits to letters to make, for instance, 'two + two = four' true when the substitutions are made.<br />
<br />
==The Problem==<br />
<br />
* http://www.rubyquiz.com/quiz128.html<br />
<br />
==Solutions==<br />
<br />
* [[Haskell Quiz/Verbal Arithmetic/Solution Dolio|Dan Doel]]<br />
* [[Haskell_Quiz/Verbal_Arithmetic/Solution_Jethr0|Jethr0]]</div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Quiz/Verbal_Arithmetic/Solution_Jethr0Haskell Quiz/Verbal Arithmetic/Solution Jethr02007-07-12T10:47:20Z<p>JohannesAhlmann: my solution to verbal arithmetic</p>
<hr />
<div>[[Category:Haskell Quiz solutions|Verbal Arithmetic]]<br />
<br />
I'm using a StateT monad inside a list monad for backtracking. The State monad keeps track of the digits associated with characters and also a carry state, that remembers the carried number from prior additions.<br />
<br />
Several constraints are already implemented (like leading digits not being zero, all associations being unique), but of course there could be lot added (checking for zero, even/odd-ness, ...)<br />
<br />
Solution should be far quicker than generic brute-force/backtracking since it tries to fail as early as possible and with more elaborate constraints it should become even faster!<br />
<br />
I couldn't be bothered to write yet another regexp/parser, as that didn't really interest me.<br />
<br />
<haskell><br />
module Main where<br />
<br />
import qualified Data.Map as Map<br />
import qualified Data.List as List<br />
import Data.Char (intToDigit)<br />
import Control.Monad<br />
import Control.Monad.State<br />
import Data.Maybe (fromJust)<br />
<br />
type Carry = Integer<br />
type Assocs = Map.Map Char Integer<br />
type St = (Assocs, Carry)<br />
<br />
parts = ["forty", "ten", "ten"]<br />
result = "sixty"<br />
<br />
<br />
-- turn words into pairs of digits<br />
digitize :: [String] -> String -> [([Char], Char)]<br />
digitize ps res = zip ps' (reverse res)<br />
where ps' = (List.transpose . map reverse $ ps) ++ repeat ""<br />
<br />
<br />
solve :: [String] -> String -> StateT St [] ()<br />
solve parts' res' = do<br />
let digitPairs = digitize parts' res'<br />
let constraints = makeConstraints parts' res'<br />
sequence_ . map (setDigitPairs constraints) $ digitPairs<br />
<br />
<br />
{- construct constraints from actual data<br />
TODO: a+b=a => b=0<br />
a+a=c => c even<br />
-}<br />
makeConstraints :: [String] -> String -> [StateT St [] ()]<br />
makeConstraints parts' res' =<br />
-- leading digits shouldn't be zero<br />
map (constraintCheck (guard . (0/=))) firsts<br />
where firsts = map head (res' : parts)<br />
constraintCheck cstr c = do<br />
(s,_) <- get<br />
case Map.lookup c s of <br />
Nothing -> return ()<br />
Just i -> cstr i<br />
<br />
<br />
-- set digits, make per-digit check with carry and apply constraints<br />
setDigitPairs cstrs (ds,res) = do<br />
ls <- sequence . map placer $ ds<br />
r <- placer res<br />
<br />
(_,carry) <- get<br />
let r' = sum ls + carry<br />
guard $ r' `mod` 10 == r<br />
<br />
let carry' = r' `div` 10<br />
modify (\(a,_) -> (a,carry'))<br />
<br />
sequence cstrs<br />
<br />
<br />
-- place number if not yet set and check for uniqueness,<br />
-- otherwise return already set value<br />
placer :: Char -> StateT St [] Integer<br />
placer l = do<br />
(assoc,_) <- get<br />
case Map.lookup l assoc of<br />
Just i -> return i<br />
Nothing -> do<br />
a <- lift [0..9]<br />
guard $ a `notElem` (Map.elems assoc)<br />
modify (\(ass,c) -> (Map.insert l a ass, c))<br />
return a<br />
<br />
<br />
main = mapM_ print . Map.toList . fst . head $ <br />
execStateT (solve parts result) (Map.empty :: Assocs, 0)<br />
<br />
</haskell></div>JohannesAhlmannhttps://wiki.haskell.org/Euler_problems/11_to_20Euler problems/11 to 202007-04-01T15:52:07Z<p>JohannesAhlmann: small change to problem 17</p>
<hr />
<div>== [http://projecteuler.net/index.php?section=problems&id=11 Problem 11] ==<br />
What is the greatest product of four numbers on the same straight line in the 20 by 20 grid?<br />
<br />
Solution:<br />
<haskell><br />
problem_11 = undefined<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=12 Problem 12] ==<br />
What is the first triangle number to have over five-hundred divisors?<br />
<br />
Solution:<br />
<haskell><br />
problem_12 = head $ filter ((> 500) . nDivisors) triangleNumbers<br />
where triangleNumbers = scanl1 (+) [1..]<br />
nDivisors n = product $ map ((+1) . length) (group (primeFactors n))<br />
primes = 2 : filter ((== 1) . length . primeFactors) [3,5..]<br />
primeFactors n = factor n primes<br />
where factor n (p:ps) | p*p > n = [n]<br />
| n `mod` p == 0 = p : factor (n `div` p) (p:ps)<br />
| otherwise = factor n ps<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=13 Problem 13] ==<br />
Find the first ten digits of the sum of one-hundred 50-digit numbers.<br />
<br />
Solution:<br />
<haskell><br />
nums = ... -- put the numbers in a list<br />
problem_13 = take 10 . show . sum $ nums<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=14 Problem 14] ==<br />
Find the longest sequence using a starting number under one million.<br />
<br />
Solution:<br />
<haskell><br />
problem_14 = undefined<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=15 Problem 15] ==<br />
Starting in the top left corner in a 20 by 20 grid, how many routes are there to the bottom right corner?<br />
<br />
Solution:<br />
<haskell><br />
problem_15 = undefined<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=16 Problem 16] ==<br />
What is the sum of the digits of the number 2<sup>1000</sup>?<br />
<br />
Solution:<br />
<haskell><br />
dsum 0 = 0<br />
dsum n = let ( d, m ) = n `divMod` 10 in m + ( dsum d )<br />
<br />
problem_16 = dsum ( 2^1000 )<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=17 Problem 17] ==<br />
How many letters would be needed to write all the numbers in words from 1 to 1000?<br />
<br />
Solution:<br />
<haskell><br />
-- not a very concise or beautiful solution, but food for improvements :)<br />
<br />
names = concat $<br />
[zip [(0, n) | n <- [0..19]]<br />
["", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight"<br />
,"Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen"<br />
,"Sixteen", "Seventeen", "Eighteen", "Nineteen"]<br />
,zip [(1, n) | n <- [0..9]]<br />
["", "Ten", "Twenty", "Thirty", "Fourty", "Fifty", "Sixty", "Seventy"<br />
,"Eighty", "Ninety"]<br />
,[((2,0), "")]<br />
,[((2, n), look (0,n) ++ " Hundred and") | n <- [1..9]]<br />
,[((3,0), "")]<br />
,[((3, n), look (0,n) ++ " Thousand") | n <- [1..9]]]<br />
<br />
look n = fromJust . lookup n $ names<br />
<br />
spell n = unwords $ if last s == "and" then init s else s<br />
where<br />
s = words . unwords $ map look digs'<br />
digs = reverse . zip [0..] . reverse . map digitToInt . show $ n<br />
digs' = case lookup 1 digs of<br />
Just 1 -><br />
let [ten,one] = filter (\(a,_) -> a<=1) digs in<br />
(digs \\ [ten,one]) ++ [(0,(snd ten)*10+(snd one))]<br />
otherwise -> digs<br />
<br />
problem_17 xs = sum . map (length . filter (`notElem` " -") . spell) $ xs<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=18 Problem 18] ==<br />
Find the maximum sum travelling from the top of the triangle to the base.<br />
<br />
Solution:<br />
<haskell><br />
problem_18 = undefined<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=19 Problem 19] ==<br />
How many Sundays fell on the first of the month during the twentieth century?<br />
<br />
Solution:<br />
<haskell><br />
problem_19 = undefined<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=20 Problem 20] ==<br />
Find the sum of digits in 100!<br />
<br />
Solution:<br />
<haskell><br />
problem_20 = let fac n = product [1..n] in<br />
foldr ((+) . Data.Char.digitToInt) 0 $ show $ fac 100<br />
</haskell><br />
<br />
Alternate solution, summing digits directly, which is faster than the show, digitToInt route.<br />
<br />
<haskell><br />
dsum 0 = 0<br />
dsum n = let ( d, m ) = n `divMod` 10 in m + ( dsum d )<br />
<br />
problem_20' = dsum . product $ [ 1 .. 100 ]<br />
</haskell><br />
<br />
[[Category:Tutorials]]<br />
[[Category:Code]]</div>JohannesAhlmannhttps://wiki.haskell.org/Euler_problems/11_to_20Euler problems/11 to 202007-04-01T15:43:18Z<p>JohannesAhlmann: added solution 17</p>
<hr />
<div>== [http://projecteuler.net/index.php?section=problems&id=11 Problem 11] ==<br />
What is the greatest product of four numbers on the same straight line in the 20 by 20 grid?<br />
<br />
Solution:<br />
<haskell><br />
problem_11 = undefined<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=12 Problem 12] ==<br />
What is the first triangle number to have over five-hundred divisors?<br />
<br />
Solution:<br />
<haskell><br />
problem_12 = head $ filter ((> 500) . nDivisors) triangleNumbers<br />
where triangleNumbers = scanl1 (+) [1..]<br />
nDivisors n = product $ map ((+1) . length) (group (primeFactors n))<br />
primes = 2 : filter ((== 1) . length . primeFactors) [3,5..]<br />
primeFactors n = factor n primes<br />
where factor n (p:ps) | p*p > n = [n]<br />
| n `mod` p == 0 = p : factor (n `div` p) (p:ps)<br />
| otherwise = factor n ps<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=13 Problem 13] ==<br />
Find the first ten digits of the sum of one-hundred 50-digit numbers.<br />
<br />
Solution:<br />
<haskell><br />
nums = ... -- put the numbers in a list<br />
problem_13 = take 10 . show . sum $ nums<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=14 Problem 14] ==<br />
Find the longest sequence using a starting number under one million.<br />
<br />
Solution:<br />
<haskell><br />
problem_14 = undefined<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=15 Problem 15] ==<br />
Starting in the top left corner in a 20 by 20 grid, how many routes are there to the bottom right corner?<br />
<br />
Solution:<br />
<haskell><br />
problem_15 = undefined<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=16 Problem 16] ==<br />
What is the sum of the digits of the number 2<sup>1000</sup>?<br />
<br />
Solution:<br />
<haskell><br />
dsum 0 = 0<br />
dsum n = let ( d, m ) = n `divMod` 10 in m + ( dsum d )<br />
<br />
problem_16 = dsum ( 2^1000 )<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=17 Problem 17] ==<br />
How many letters would be needed to write all the numbers in words from 1 to 1000?<br />
<br />
Solution:<br />
<haskell><br />
-- not a very concise or beautiful solution, but food for improvements :)<br />
<br />
names = concat $<br />
[zip [(0, n) | n <- [0..19]]<br />
["", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight"<br />
,"Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen"<br />
,"Sixteen", "Seventeen", "Eighteen", "Nineteen"]<br />
,zip [(1, n) | n <- [0..9]]<br />
["", "Ten", "Twenty", "Thirty", "Fourty", "Fifty", "Sixty", "Seventy"<br />
,"Eighty", "Ninety"]<br />
,[((2,0), "")]<br />
,[((2, n), look (0,n) ++ " Hundred and") | n <- [1..9]]<br />
,[((3,0), "")]<br />
,[((3, n), look (0,n) ++ " Thousand") | n <- [1..9]]]<br />
<br />
look n = fromJust . lookup n $ names<br />
<br />
spell n = unwords $ if last s == "and" then init s else s<br />
where<br />
s = words . unwords $ map look digs'<br />
digs = reverse . zip [0..] . reverse . map digitToInt . show $ n<br />
digs' = case lookup 1 digs of<br />
Just 1 -><br />
let [ten,one] = filter (\(a,_) -> a<=1) digs in<br />
(digs \\ [ten,one]) ++ [(0,(snd ten)*10+(snd one))]<br />
otherwise -> digs<br />
<br />
problem_17 xs = sum . map (length . spell) $ xs<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=18 Problem 18] ==<br />
Find the maximum sum travelling from the top of the triangle to the base.<br />
<br />
Solution:<br />
<haskell><br />
problem_18 = undefined<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=19 Problem 19] ==<br />
How many Sundays fell on the first of the month during the twentieth century?<br />
<br />
Solution:<br />
<haskell><br />
problem_19 = undefined<br />
</haskell><br />
<br />
== [http://projecteuler.net/index.php?section=problems&id=20 Problem 20] ==<br />
Find the sum of digits in 100!<br />
<br />
Solution:<br />
<haskell><br />
problem_20 = let fac n = product [1..n] in<br />
foldr ((+) . Data.Char.digitToInt) 0 $ show $ fac 100<br />
</haskell><br />
<br />
Alternate solution, summing digits directly, which is faster than the show, digitToInt route.<br />
<br />
<haskell><br />
dsum 0 = 0<br />
dsum n = let ( d, m ) = n `divMod` 10 in m + ( dsum d )<br />
<br />
problem_20' = dsum . product $ [ 1 .. 100 ]<br />
</haskell><br />
<br />
[[Category:Tutorials]]<br />
[[Category:Code]]</div>JohannesAhlmannhttps://wiki.haskell.org/Talk:Prime_numbersTalk:Prime numbers2007-02-05T21:18:04Z<p>JohannesAhlmann: </p>
<hr />
<div>Here's an interesting question: will the program go faster if we replace all those <hask>(n >)</hask> expressions with <hask>(\x -> floor (sqrt n) > x)</hask>?<br />
<br />
On one hand, a composite integer cannot possess a factor greater than its square root.<br />
<br />
On the other hand, since the list we're looking through contains all possible prime numbers, we are guaranteed to find a factor or an exact match eventually, so do we need the <hask>takeWhile</hask> at all?<br />
<br />
Throwing this over to somebody with a bigger brain than me...<br />
<br />
[[User:MathematicalOrchid|MathematicalOrchid]] 16:41, 5 February 2007 (UTC)<br />
<br />
a composite can indeed have factors greater than its square root, and indeed most do. what you mean is that a composite will definitely have at least one factor smaller-equal than its square root.<br />
<br />
why not use <hask>(\x -> n > x*x)</hask> --[[User:JohannesAhlmann|Johannes Ahlmann]] 21:18, 5 February 2007 (UTC)</div>JohannesAhlmannhttps://wiki.haskell.org/Regular_expressionsRegular expressions2007-01-24T16:59:07Z<p>JohannesAhlmann: maybe implement Thompson NFA for regular expression library</p>
<hr />
<div>I just came across [http://swtch.com/~rsc/regexp/regexp1.html this article on Thompson Non-Finite Automata] which presents an alternative implementation (to the one supposedly used in perl, ruby, python) which is MAAANY times faster.<br />
<br />
Seing how badly we did in the shootout initially, wouldn't it be grand if "we" implemented this algorithm and could then outrun every other language WRT regular expressions, with a native haskell library...<br />
<br />
{{stub}}</div>JohannesAhlmannhttps://wiki.haskell.org/Questions_and_answersQuestions and answers2007-01-22T16:00:56Z<p>JohannesAhlmann: </p>
<hr />
<div>Feel free to ask your questions here. Please sign your question using four tildes (<nowiki>~~~~</nowiki>). Questions and answers will be organised as they are added, and linked from here. We don't have much here yet, but [http://www.haskell.org/hawiki/HaskellNewbie the Haskell Newbie page] on the old wiki has quite a few questions and answers you can look through.<br />
<br />
[[Category:Community]]<br />
<br />
* Is this a good place to ask questions? [[User:MathematicalOrchid|MathematicalOrchid]] 15:30, 18 January 2007 (UTC)<br />
** not yet at least. try the #haskell irc channel on freenode which is usually manned by at least a few very helpfull people. alternatively try the [http://haskell.org/pipermail/haskell-cafe/ haskell-cafe] mailing list --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** I tried the IRC channel. 300+ people and nobody speaking. Not very helpful. [[User:MathematicalOrchid|MathematicalOrchid]] 13:23, 22 January 2007 (UTC)<br />
<br />
Hmm, that sounded like a 'no'... OK, I'm going to add a few 'real' questions, and see if that gets any more of a response... [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
<br />
* Which is faster? <hask>putStr (xs ++ ys ++ xs)</hask> or <hask>putStr xs; putStr ys; putStr zs</hask>? How much of a difference does it make? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** hmm, <hask>(++)</hask> is a very slow operation which is O(n) in the length of the first string. for short strings the difference should be small, for very long string you'll see a big difference. concrete timing depends on putStr... --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** <hask>(++)</hask> is right-associative when there's several, resulting in the fastest possible performance. (I understand this is why the <hask>Show</hask> class is so damn weird...) Even so, I wonder if it's more efficient to join strings or use real I/O... [[User:MathematicalOrchid|MathematicalOrchid]] 13:23, 22 January 2007 (UTC)<br />
<br />
* Haskell apparently allows you to write functions with bizarre names like '++' or '***'. What are the rules for this? Which characters can or can't you use? Are you ''required'' to give a fixity declaration first, or can you just use them? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** please refer the [[Language_and_library_specification]] under [http://haskell.org/onlinereport/lexemes.html#ids "Identifiers and Operators"]. variable identifiers start with a lowercase letter, constructor Identifiers with an uppercase letter and both can contain underscores, single quotes, letters and digits; , operators are formed from one or more of <hask>"!#$%&*+./<=>?@\^|-~"</hask> (plus a special case involving <hask>(:)</hask>). lacking fixity declarations, the default [http://haskell.org/onlinereport/decls.html#sect4.4.2 fixity] is left associative and most tightly binding (9). --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** Right. So I can't name my function '~', but I can name it something that has '~' in it then. I also see from the spec document that apparently only data constructors can start with ':'. (I didn't know that... Well worth knowing!) [[User:MathematicalOrchid|MathematicalOrchid]] 15:52, 22 January 2007 (UTC)<br />
**** no, '~' is a valid operator ('one or more of "...~..."'). and you can't mix special characters with non-special characters (letter, digits, single quote, underscore).<br />
<br />
* GHC ''can'' do all sorts of program optimisations. But, for a given program, how can you tell what it ''really'' did when it compiled? Did it inline that function? Was that operation optimised into an in-place update? Is there a way to tell? (Short of using a disassembler that is!) [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** you can look at [http://www.haskell.org/ghc/docs/latest/html/users_guide/separate-compilation.html#keeping-intermediates intermediate compiler outputs] with ghc flags. --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** Right. So there's various bits of info you can get out of it. (All a bit low-level... but then, what would you expect?) [[User:MathematicalOrchid|MathematicalOrchid]] 15:52, 22 January 2007 (UTC)<br />
<br />
* Is there a way to make a Haskell program utilise multiple CPUs? (I rephrase: clearly this ''is'' very possible theoretically. What I mean is does any known compiler provide a way to do this?) [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** * yes, ghc 6.6 supports multiple CPUs. see [[GHC/Concurrency#Multiprocessor_GHC]] --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** Right... so I just need to compile my program with "-threaded" and run it with "+RTS -N2" or whatever? [[User:MathematicalOrchid|MathematicalOrchid]] 15:52, 22 January 2007 (UTC)<br />
<br />
* I want to write a program that renders bitmap graphics. Is there ''any'' way to get this onto the video screen in Haskell? Is there any way to get the data saved to disk in some sane file format? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** have a look at [[Libraries_and_tools/GUI_libraries]]. i'd have a look at [http://haskell.org/graphics/ HGL], [http://haskell.org/HOpenGL/ HOpenGL] and/or [http://haskell.org/gtk2hs/ gtk2hs]. of these, at least gtk2hs has some image handling routines. for pure image format libraries there's unfortunately a little less :(<br />
*** This is where it starts to get messy... I already tried using HGL from within Hugs. (Drawing 'pixels' that are really small squares.) However, once it's drawn enough pixels, I get a Dr Watson error and Hugs ungracefully terminates. (Actually, the latest version of Hugs seems to do this a lot.) So I went to compile it with GHC - and it seems GHC doesn't come with that library at all. And the page you linked says that HGL is 'currently broken on Win32'. Hmm... OK, I'm confused now. Then there's HOpenGL. (Is that the same thing as Graphics.Rendering.OpenGL, or is it seperate?) It's nice to know you can have hardware 3D acceleration if you want it, but maybe a tad overkill for just writing a bitmap to the display. Also, IIRC, doesn't OpenGL require you to open a window in a platform-specific way first? And then there's gtk2hs. I don't know if you can run Gtk on Win32... but that one looks like it might be worth investigating. [[User:MathematicalOrchid|MathematicalOrchid]] 15:52, 22 January 2007 (UTC)</div>JohannesAhlmannhttps://wiki.haskell.org/Questions_and_answersQuestions and answers2007-01-22T15:57:55Z<p>JohannesAhlmann: removed rants</p>
<hr />
<div>Feel free to ask your questions here. Please sign your question using four tildes (<nowiki>~~~~</nowiki>). Questions and answers will be organised as they are added, and linked from here. We don't have much here yet, but [http://www.haskell.org/hawiki/HaskellNewbie the Haskell Newbie page] on the old wiki has quite a few questions and answers you can look through.<br />
<br />
[[Category:Community]]<br />
<br />
* Is this a good place to ask questions? [[User:MathematicalOrchid|MathematicalOrchid]] 15:30, 18 January 2007 (UTC)<br />
** not yet at least. try the #haskell irc channel on freenode which is usually manned by at least a few very helpfull people. alternatively try the [http://haskell.org/pipermail/haskell-cafe/ haskell-cafe] mailing list --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** I tried the IRC channel. 300+ people and nobody speaking. Not very helpful. [[User:MathematicalOrchid|MathematicalOrchid]] 13:23, 22 January 2007 (UTC)<br />
<br />
Hmm, that sounded like a 'no'... OK, I'm going to add a few 'real' questions, and see if that gets any more of a response... [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
<br />
* Which is faster? <hask>putStr (xs ++ ys ++ xs)</hask> or <hask>putStr xs; putStr ys; putStr zs</hask>? How much of a difference does it make? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** hmm, <hask>(++)</hask> is a very slow operation which is O(n) in the length of the first string. for short strings the difference should be small, for very long string you'll see a big difference. concrete timing depends on putStr... --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** <hask>(++)</hask> is right-associative when there's several, resulting in the fastest possible performance. (I understand this is why the <hask>Show</hask> class is so damn weird...) Even so, I wonder if it's more efficient to join strings or use real I/O... [[User:MathematicalOrchid|MathematicalOrchid]] 13:23, 22 January 2007 (UTC)<br />
<br />
* Haskell apparently allows you to write functions with bizarre names like '++' or '***'. What are the rules for this? Which characters can or can't you use? Are you ''required'' to give a fixity declaration first, or can you just use them? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** please refer the [[Language_and_library_specification]] under [http://haskell.org/onlinereport/lexemes.html#ids "Identifiers and Operators"]. variable identifiers start with a lowercase letter, constructor Identifiers with an uppercase letter and both can contain underscores, single quotes, letters and digits; , operators are formed from one or more of <hask>"!#$%&*+./<=>?@\^|-~"</hask> (plus a special case involving <hask>(:)</hask>). lacking fixity declarations, the default [http://haskell.org/onlinereport/decls.html#sect4.4.2 fixity] is left associative and most tightly binding (9). --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** Right. So I can't name my function '~', but I can name it something that has '~' in it then. I also see from the spec document that apparently only data constructors can start with ':'. (I didn't know that... Well worth knowing!) [[User:MathematicalOrchid|MathematicalOrchid]] 15:52, 22 January 2007 (UTC)<br />
<br />
* GHC ''can'' do all sorts of program optimisations. But, for a given program, how can you tell what it ''really'' did when it compiled? Did it inline that function? Was that operation optimised into an in-place update? Is there a way to tell? (Short of using a disassembler that is!) [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** you can look at [http://www.haskell.org/ghc/docs/latest/html/users_guide/separate-compilation.html#keeping-intermediates intermediate compiler outputs] with ghc flags. --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** Right. So there's various bits of info you can get out of it. (All a bit low-level... but then, what would you expect?) [[User:MathematicalOrchid|MathematicalOrchid]] 15:52, 22 January 2007 (UTC)<br />
<br />
* Is there a way to make a Haskell program utilise multiple CPUs? (I rephrase: clearly this ''is'' very possible theoretically. What I mean is does any known compiler provide a way to do this?) [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** * yes, ghc 6.6 supports multiple CPUs. see [[GHC/Concurrency#Multiprocessor_GHC]] --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** Right... so I just need to compile my program with "-threaded" and run it with "+RTS -N2" or whatever? [[User:MathematicalOrchid|MathematicalOrchid]] 15:52, 22 January 2007 (UTC)<br />
<br />
* I want to write a program that renders bitmap graphics. Is there ''any'' way to get this onto the video screen in Haskell? Is there any way to get the data saved to disk in some sane file format? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** have a look at [[Libraries_and_tools/GUI_libraries]]. i'd have a look at [http://haskell.org/graphics/ HGL], [http://haskell.org/HOpenGL/ HOpenGL] and/or [http://haskell.org/gtk2hs/ gtk2hs]. of these, at least gtk2hs has some image handling routines. for pure image format libraries there's unfortunately a little less :(<br />
*** This is where it starts to get messy... I already tried using HGL from within Hugs. (Drawing 'pixels' that are really small squares.) However, once it's drawn enough pixels, I get a Dr Watson error and Hugs ungracefully terminates. (Actually, the latest version of Hugs seems to do this a lot.) So I went to compile it with GHC - and it seems GHC doesn't come with that library at all. And the page you linked says that HGL is 'currently broken on Win32'. Hmm... OK, I'm confused now. Then there's HOpenGL. (Is that the same thing as Graphics.Rendering.OpenGL, or is it seperate?) It's nice to know you can have hardware 3D acceleration if you want it, but maybe a tad overkill for just writing a bitmap to the display. Also, IIRC, doesn't OpenGL require you to open a window in a platform-specific way first? And then there's gtk2hs. I don't know if you can run Gtk on Win32... but that one looks like it might be worth investigating. [[User:MathematicalOrchid|MathematicalOrchid]] 15:52, 22 January 2007 (UTC)</div>JohannesAhlmannhttps://wiki.haskell.org/Questions_and_answersQuestions and answers2007-01-22T13:41:51Z<p>JohannesAhlmann: </p>
<hr />
<div>Feel free to ask your questions here. Please sign your question using four tildes (<nowiki>~~~~</nowiki>). Questions and answers will be organised as they are added, and linked from here. We don't have much here yet, but [http://www.haskell.org/hawiki/HaskellNewbie the Haskell Newbie page] on the old wiki has quite a few questions and answers you can look through.<br />
<br />
[[Category:Community]]<br />
<br />
* Is this a good place to ask questions? [[User:MathematicalOrchid|MathematicalOrchid]] 15:30, 18 January 2007 (UTC)<br />
** not yet at least. try the #haskell irc channel on freenode which is usually manned by at least a few very helpfull people. alternatively try the [http://haskell.org/pipermail/haskell-cafe/ haskell-cafe] mailing list --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** I tried the IRC channel. 300+ people and nobody speaking. Not very helpful. [[User:MathematicalOrchid|MathematicalOrchid]] 13:23, 22 January 2007 (UTC)<br />
<br />
Hmm, that sounded like a 'no'... OK, I'm going to add a few 'real' questions, and see if that gets any more of a response... [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
<br />
you know what, i really wanted to help, but this is getting ridiculous. when you're too lazy to look at the wiki/documentation and too impatient to find help on #haskell then there's just no help for you... --[[User:JohannesAhlmann|Johannes Ahlmann]] 13:30, 22 January 2007 (UTC)<br />
<br />
* Which is faster? <hask>putStr (xs ++ ys ++ xs)</hask> or <hask>putStr xs; putStr ys; putStr zs</hask>? How much of a difference does it make? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** hmm, <hask>(++)</hask> is a very slow operation which is O(n) in the length of the first string. for short strings the difference should be small, for very long string you'll see a big difference. concrete timing depends on putStr... --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** <hask>(++)</hask> is right-associative when there's several, resulting in the fastest possible performance. (I understand this is why the <hask>Show</hask> class is so damn weird...) Even so, I wonder if it's more efficient to join strings or use real I/O... [[User:MathematicalOrchid|MathematicalOrchid]] 13:23, 22 January 2007 (UTC)<br />
<br />
* Haskell apparently allows you to write functions with bizarre names like '++' or '***'. What are the rules for this? Which characters can or can't you use? Are you ''required'' to give a fixity declaration first, or can you just use them? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** please refer the [[Language_and_library_specification]] under [http://haskell.org/onlinereport/lexemes.html#ids "Identifiers and Operators"]. variable identifiers start with a lowercase letter, constructor Identifiers with an uppercase letter and both can contain underscores, single quotes, letters and digits; , operators are formed from one or more of <hask>"!#$%&*+./<=>?@\^|-~"</hask> (plus a special case involving <hask>(:)</hask>). lacking fixity declarations, the default [http://haskell.org/onlinereport/decls.html#sect4.4.2 fixity] is left associative and most tightly binding (9). --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** Ouch. Reading the spec sounds like fun...<br />
<br />
* GHC ''can'' do all sorts of program optimisations. But, for a given program, how can you tell what it ''really'' did when it compiled? Did it inline that function? Was that operation optimised into an in-place update? Is there a way to tell? (Short of using a disassembler that is!) [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** you can look at [http://www.haskell.org/ghc/docs/latest/html/users_guide/separate-compilation.html#keeping-intermediates intermediate compiler outputs] with ghc flags. --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** OK. I'll see if I can't dig it out of the GHC manual somewhere...<br />
<br />
* Is there a way to make a Haskell program utilise multiple CPUs? (I rephrase: clearly this ''is'' very possible theoretically. What I mean is does any known compiler provide a way to do this?) [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** * yes, ghc 6.6 supports multiple CPUs. see [[GHC/Concurrency#Multiprocessor_GHC]] --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** Right... Do I really need the nightly build to get this functionality? Or is that information outdated? That aside, I just need to compile my program with "-threaded" and run it with "+RTS -N2" or whatever? [[User:MathematicalOrchid|MathematicalOrchid]] 13:23, 22 January 2007 (UTC)<br />
<br />
* I want to write a program that renders bitmap graphics. Is there ''any'' way to get this onto the video screen in Haskell? Is there any way to get the data saved to disk in some sane file format? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** have a look at [[Libraries_and_tools/GUI_libraries]]. i'd have a look at [http://haskell.org/graphics/ HGL], [http://haskell.org/HOpenGL/ HOpenGL] and/or [http://haskell.org/gtk2hs/ gtk2hs]. of these, at least gtk2hs has some image handling routines. for pure image format libraries there's unfortunately a little less :(</div>JohannesAhlmannhttps://wiki.haskell.org/Questions_and_answersQuestions and answers2007-01-22T13:36:23Z<p>JohannesAhlmann: imaging</p>
<hr />
<div>Feel free to ask your questions here. Please sign your question using four tildes (<nowiki>~~~~</nowiki>). Questions and answers will be organised as they are added, and linked from here. We don't have much here yet, but [http://www.haskell.org/hawiki/HaskellNewbie the Haskell Newbie page] on the old wiki has quite a few questions and answers you can look through.<br />
<br />
[[Category:Community]]<br />
<br />
* Is this a good place to ask questions? [[User:MathematicalOrchid|MathematicalOrchid]] 15:30, 18 January 2007 (UTC)<br />
** not yet at least. try the #haskell irc channel on freenode which is usually manned by at least a few very helpfull people. alternatively try the [http://haskell.org/pipermail/haskell-cafe/ haskell-cafe] mailing list --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** I tried the IRC channel. 300+ people and nobody speaking. Not very helpful. [[User:MathematicalOrchid|MathematicalOrchid]] 13:23, 22 January 2007 (UTC)<br />
<br />
Hmm, that sounded like a 'no'... OK, I'm going to add a few 'real' questions, and see if that gets any more of a response... [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
<br />
you know what, i really wanted to help, but this is getting ridiculous. when you're too lazy to look at the wiki/documentation and too impatient to find help on #haskell then there's just no help for you... --[[User:JohannesAhlmann|Johannes Ahlmann]] 13:30, 22 January 2007 (UTC)<br />
<br />
* Which is faster? <hask>putStr (xs ++ ys ++ xs)</hask> or <hask>putStr xs; putStr ys; putStr zs</hask>? How much of a difference does it make? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** hmm, <hask>(++)</hask> is a very slow operation which is O(n) in the length of the first string. for short strings the difference should be small, for very long string you'll see a big difference. concrete timing depends on putStr... --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** <hask>(++)</hask> is right-associative when there's several, resulting in the fastest possible performance. (I understand this is why the <hask>Show</hask> class is so damn weird...) Even so, I wonder if it's more efficient to join strings or use real I/O... [[User:MathematicalOrchid|MathematicalOrchid]] 13:23, 22 January 2007 (UTC)<br />
<br />
* Haskell apparently allows you to write functions with bizarre names like '++' or '***'. What are the rules for this? Which characters can or can't you use? Are you ''required'' to give a fixity declaration first, or can you just use them? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** please refer the [[Language_and_library_specification]] under [http://haskell.org/onlinereport/lexemes.html#ids "Identifiers and Operators"]. variable identifiers start with a lowercase letter, constructor Identifiers with an uppercase letter and both can contain underscores, single quotes, letters and digits; , operators are formed from one or more of <hask>"!#$%&*+./<=>?@\^|-~"</hask> (plus a special case involving <hask>(:)</hask>). lacking fixity declarations, the default [http://haskell.org/onlinereport/decls.html#sect4.4.2 fixity] is left associative and most tightly binding (9). --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** Ouch. Reading the spec sounds like fun...<br />
<br />
* GHC ''can'' do all sorts of program optimisations. But, for a given program, how can you tell what it ''really'' did when it compiled? Did it inline that function? Was that operation optimised into an in-place update? Is there a way to tell? (Short of using a disassembler that is!) [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** you can look at [http://www.haskell.org/ghc/docs/latest/html/users_guide/separate-compilation.html#keeping-intermediates intermediate compiler outputs] with ghc flags. --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** OK. I'll see if I can't dig it out of the GHC manual somewhere...<br />
<br />
* Is there a way to make a Haskell program utilise multiple CPUs? (I rephrase: clearly this ''is'' very possible theoretically. What I mean is does any known compiler provide a way to do this?) [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** * yes, ghc 6.6 supports multiple CPUs. see [[GHC/Concurrency#Multiprocessor_GHC]] --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** Right... Do I really need the nightly build to get this functionality? Or is that information outdated? That aside, I just need to compile my program with "-threaded" and run it with "+RTS -N2" or whatever? [[User:MathematicalOrchid|MathematicalOrchid]] 13:23, 22 January 2007 (UTC)<br />
<br />
* I want to write a program that renders bitmap graphics. Is there ''any'' way to get this onto the video screen in Haskell? Is there any way to get the data saved to disk in some sane file format? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** have a look at [[Libraries_and_tools/GUI_libraries]]. i'd have a look at [http://haskell.org/graphics/ HGL], [http://haskell.org/HOpenGL/ HOpenGL] and/or [http://haskell.org/gtk2hs/ gtk2hs]. some of these may have image libraries as well. for pure image format libraries there's unfortunately a little less :(</div>JohannesAhlmannhttps://wiki.haskell.org/Questions_and_answersQuestions and answers2007-01-22T13:30:47Z<p>JohannesAhlmann: getting annoyed</p>
<hr />
<div>Feel free to ask your questions here. Please sign your question using four tildes (<nowiki>~~~~</nowiki>). Questions and answers will be organised as they are added, and linked from here. We don't have much here yet, but [http://www.haskell.org/hawiki/HaskellNewbie the Haskell Newbie page] on the old wiki has quite a few questions and answers you can look through.<br />
<br />
[[Category:Community]]<br />
<br />
* Is this a good place to ask questions? [[User:MathematicalOrchid|MathematicalOrchid]] 15:30, 18 January 2007 (UTC)<br />
** not yet at least. try the #haskell irc channel on freenode which is usually manned by at least a few very helpfull people. alternatively try the [http://haskell.org/pipermail/haskell-cafe/ haskell-cafe] mailing list --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** I tried the IRC channel. 300+ people and nobody speaking. Not very helpful. [[User:MathematicalOrchid|MathematicalOrchid]] 13:23, 22 January 2007 (UTC)<br />
<br />
Hmm, that sounded like a 'no'... OK, I'm going to add a few 'real' questions, and see if that gets any more of a response... [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
<br />
you know what, i really wanted to help, but this is getting ridiculous. when you're too lazy to look at the wiki/documentation and too impatient to find help on #haskell then there's just no help for you... --[[User:JohannesAhlmann|Johannes Ahlmann]] 13:30, 22 January 2007 (UTC)<br />
<br />
* Which is faster? <hask>putStr (xs ++ ys ++ xs)</hask> or <hask>putStr xs; putStr ys; putStr zs</hask>? How much of a difference does it make? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** hmm, <hask>(++)</hask> is a very slow operation which is O(n) in the length of the first string. for short strings the difference should be small, for very long string you'll see a big difference. concrete timing depends on putStr... --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** <hask>(++)</hask> is right-associative when there's several, resulting in the fastest possible performance. (I understand this is why the <hask>Show</hask> class is so damn weird...) Even so, I wonder if it's more efficient to join strings or use real I/O... [[User:MathematicalOrchid|MathematicalOrchid]] 13:23, 22 January 2007 (UTC)<br />
<br />
* Haskell apparently allows you to write functions with bizarre names like '++' or '***'. What are the rules for this? Which characters can or can't you use? Are you ''required'' to give a fixity declaration first, or can you just use them? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** please refer the [[Language_and_library_specification]] under [http://haskell.org/onlinereport/lexemes.html#ids "Identifiers and Operators"]. variable identifiers start with a lowercase letter, constructor Identifiers with an uppercase letter and both can contain underscores, single quotes, letters and digits; , operators are formed from one or more of <hask>"!#$%&*+./<=>?@\^|-~"</hask> (plus a special case involving <hask>(:)</hask>). lacking fixity declarations, the default [http://haskell.org/onlinereport/decls.html#sect4.4.2 fixity] is left associative and most tightly binding (9). --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** Ouch. Reading the spec sounds like fun...<br />
<br />
* GHC ''can'' do all sorts of program optimisations. But, for a given program, how can you tell what it ''really'' did when it compiled? Did it inline that function? Was that operation optimised into an in-place update? Is there a way to tell? (Short of using a disassembler that is!) [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** you can look at [http://www.haskell.org/ghc/docs/latest/html/users_guide/separate-compilation.html#keeping-intermediates intermediate compiler outputs] with ghc flags. --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** OK. I'll see if I can't dig it out of the GHC manual somewhere...<br />
<br />
* Is there a way to make a Haskell program utilise multiple CPUs? (I rephrase: clearly this ''is'' very possible theoretically. What I mean is does any known compiler provide a way to do this?) [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** * yes, ghc 6.6 supports multiple CPUs. see [[GHC/Concurrency#Multiprocessor_GHC]] --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** Right... Do I really need the nightly build to get this functionality? Or is that information outdated? That aside, I just need to compile my program with "-threaded" and run it with "+RTS -N2" or whatever? [[User:MathematicalOrchid|MathematicalOrchid]] 13:23, 22 January 2007 (UTC)<br />
<br />
* I want to write a program that renders bitmap graphics. Is there ''any'' way to get this onto the video screen in Haskell? Is there any way to get the data saved to disk in some sane file format? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)</div>JohannesAhlmannhttps://wiki.haskell.org/Questions_and_answersQuestions and answers2007-01-22T13:26:53Z<p>JohannesAhlmann: more answers</p>
<hr />
<div>Feel free to ask your questions here. Please sign your question using four tildes (<nowiki>~~~~</nowiki>). Questions and answers will be organised as they are added, and linked from here. We don't have much here yet, but [http://www.haskell.org/hawiki/HaskellNewbie the Haskell Newbie page] on the old wiki has quite a few questions and answers you can look through.<br />
<br />
[[Category:Community]]<br />
<br />
* Is this a good place to ask questions? [[User:MathematicalOrchid|MathematicalOrchid]] 15:30, 18 January 2007 (UTC)<br />
** not yet at least. try the #haskell irc channel on freenode which is usually manned by at least a few very helpfull people. alternatively try the [http://haskell.org/pipermail/haskell-cafe/ haskell-cafe] mailing list --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** I tried the IRC channel. 300+ people and nobody speaking. Not very helpful. [[User:MathematicalOrchid|MathematicalOrchid]] 13:23, 22 January 2007 (UTC)<br />
<br />
Hmm, that sounded like a 'no'... OK, I'm going to add a few 'real' questions, and see if that gets any more of a response... [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
<br />
* Which is faster? <hask>putStr (xs ++ ys ++ xs)</hask> or <hask>putStr xs; putStr ys; putStr zs</hask>? How much of a difference does it make? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** hmm, <hask>(++)</hask> is a very slow operation which is O(n) in the length of the first string. for short strings the difference should be small, for very long string you'll see a big difference. concrete timing depends on putStr... --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** <hask>(++)</hask> is right-associative when there's several, resulting in the fastest possible performance. (I understand this is why the <hask>Show</hask> class is so damn weird...) Even so, I wonder if it's more efficient to join strings or use real I/O... [[User:MathematicalOrchid|MathematicalOrchid]] 13:23, 22 January 2007 (UTC)<br />
<br />
* Haskell apparently allows you to write functions with bizarre names like '++' or '***'. What are the rules for this? Which characters can or can't you use? Are you ''required'' to give a fixity declaration first, or can you just use them? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** please refer the [[Language_and_library_specification]] under [http://haskell.org/onlinereport/lexemes.html#ids "Identifiers and Operators"]. variable identifiers start with a lowercase letter, constructor Identifiers with an uppercase letter and both can contain underscores, single quotes, letters and digits; , operators are formed from one or more of <hask>"!#$%&*+./<=>?@\^|-~"</hask> (plus a special case involving <hask>(:)</hask>). lacking fixity declarations, the default [http://haskell.org/onlinereport/decls.html#sect4.4.2 fixity] is left associative and most tightly binding (9). --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** Ouch. Reading the spec sounds like fun...<br />
<br />
* GHC ''can'' do all sorts of program optimisations. But, for a given program, how can you tell what it ''really'' did when it compiled? Did it inline that function? Was that operation optimised into an in-place update? Is there a way to tell? (Short of using a disassembler that is!) [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** you can look at intermediate compiler outputs with ghc flags. --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** OK. I'll see if I can't dig it out of the GHC manual somewhere...<br />
<br />
* Is there a way to make a Haskell program utilise multiple CPUs? (I rephrase: clearly this ''is'' very possible theoretically. What I mean is does any known compiler provide a way to do this?) [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** * yes, ghc 6.6 supports multiple CPUs. see [[GHC/Concurrency#Multiprocessor_GHC]] --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
*** Right... Do I really need the nightly build to get this functionality? Or is that information outdated? That aside, I just need to compile my program with "-threaded" and run it with "+RTS -N2" or whatever? [[User:MathematicalOrchid|MathematicalOrchid]] 13:23, 22 January 2007 (UTC)<br />
<br />
* I want to write a program that renders bitmap graphics. Is there ''any'' way to get this onto the video screen in Haskell? Is there any way to get the data saved to disk in some sane file format? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)</div>JohannesAhlmannhttps://wiki.haskell.org/Questions_and_answersQuestions and answers2007-01-22T12:29:26Z<p>JohannesAhlmann: some answers</p>
<hr />
<div>Feel free to ask your questions here. Please sign your question using four tildes (<nowiki>~~~~</nowiki>). Questions and answers will be organised as they are added, and linked from here. We don't have much here yet, but [http://www.haskell.org/hawiki/HaskellNewbie the Haskell Newbie page] on the old wiki has quite a few questions and answers you can look through.<br />
<br />
[[Category:Community]]<br />
<br />
* Is this a good place to ask questions? [[User:MathematicalOrchid|MathematicalOrchid]] 15:30, 18 January 2007 (UTC)<br />
** not yet at least. try the #haskell irc channel on freenode which is usually manned by at least a few very helpfull people. alternatively try the [http://haskell.org/pipermail/haskell-cafe/ haskell-cafe] mailing list --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
<br />
Hmm, that sounded like a 'no'... OK, I'm going to add a few 'real' questions, and see if that gets any more of a response... [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
<br />
* Which is faster? <hask>putStr (xs ++ ys ++ xs)</hask> or <hask>putStr xs; putStr ys; putStr zs</hask>? How much of a difference does it make? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** hmm, <hask>(++)</hask> is a very slow operation which is O(n) in the length of the first string. for short strings the difference should be small, for very long string you'll see a big difference. concrete timing depends on putStr... --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
<br />
* Haskell apparently allows you to write functions with bizarre names like '++' or '***'. What are the rules for this? Which characters can or can't you use? Are you ''required'' to give a fixity declaration first, or can you just use them? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** please refer the [[Language_and_library_specification]]. you don't need to give a fixity, there's a default fixity. functions starting with a letter are prefix, functions starting with a special char are infix. --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
<br />
* GHC ''can'' do all sorts of program optimisations. But, for a given program, how can you tell what it ''really'' did when it compiled? Did it inline that function? Was that operation optimised into an in-place update? Is there a way to tell? (Short of using a disassembler that is!) [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** you can look at intermediate compiler outputs with ghc flags. --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
<br />
<br />
* Is there a way to make a Haskell program utilise multiple CPUs? (I rephrase: clearly this ''is'' very possible theoretically. What I mean is does any known compiler provide a way to do this?) [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)<br />
** yes, ghc supports multiple CPUs. see [[GHC/Concurrency]] --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:29, 22 January 2007 (UTC)<br />
<br />
* I want to write a program that renders bitmap graphics. Is there ''any'' way to get this onto the video screen in Haskell? Is there any way to get the data saved to disk in some sane file format? [[User:MathematicalOrchid|MathematicalOrchid]] 11:47, 22 January 2007 (UTC)</div>JohannesAhlmannhttps://wiki.haskell.org/Talk:How_to_work_on_listsTalk:How to work on lists2007-01-21T23:44:25Z<p>JohannesAhlmann: </p>
<hr />
<div>on the topic of slower operations: it should be noted that filter, map, zip, etc. are only O(n) if the whole list is evaluated. since these are lazy functions any of these will be O(1):<br />
<br />
<haskell><br />
head $ map (+1) [0..]<br />
(filter even [0..])!!5<br />
take 5 $ zip [0..] [5..]<br />
</haskell><br />
<br />
--[[User:JohannesAhlmann|Johannes Ahlmann]] 23:44, 21 January 2007 (UTC)</div>JohannesAhlmannhttps://wiki.haskell.org/Blow_your_mindBlow your mind2007-01-16T04:28:07Z<p>JohannesAhlmann: fixed splitting into words using foldr</p>
<hr />
<div>Useful Idioms that will blow your mind (unless you already know them :)<br />
<br />
This collection is supposed to be comprised of short, useful, cool, magical examples, which should incite the reader's curiosity and (hopefully) lead him to a deeper understanding of advanced Haskell concepts. At a later time I might add explanations to the more obscure solutions. I've also started providing several alternatives to give more insight into the interrelations of solutions.<br />
<br />
More examples are always welcome, especially "obscure" monadic ones.<br />
<br />
<br />
== List/String Operations ==<br />
<br />
<br />
<haskell><br />
-- split at whitespace<br />
-- "hello world" -> ["hello","world"]<br />
words<br />
<br />
unfoldr (\b -> fmap (const . (second $ drop 1) . break (==' ') $ b) . listToMaybe $ b)<br />
<br />
fix (\f l -> if null l then [] else let (s,e) = break (==' ') l in s:f (drop 1 e))<br />
<br />
<br />
-- splitting in two (alternating)<br />
-- "1234567" -> ("1357", "246")<br />
-- the lazy match with ~ is necessary for efficiency, especially enabling processing of infinite lists<br />
foldr (\a ~(x,y) -> (a:y,x)) ([],[])<br />
<br />
(map snd *** map snd) . partition (even . fst) . zip [0..]<br />
<br />
transpose . unfoldr (\a -> toMaybe (null a) (splitAt 2 a))<br />
-- this one uses the solution to the next problem in a nice way :)<br />
<br />
toMaybe b x = if b then Just x else Nothing<br />
<br />
-- splitting into lists of length N<br />
-- "1234567" -> ["12", "34", "56", "7"]<br />
unfoldr (\a -> toMaybe (null a) (splitAt 2 a))<br />
<br />
takeWhile (not . null) . unfoldr (Just . splitAt 2)<br />
<br />
<br />
-- sorting by a custom function<br />
-- length -> ["abc", "ab", "a"] -> ["a", "ab", "abc"]<br />
comparing f x y = compare (f x) (f y)<br />
sortBy (comparing length)<br />
<br />
map snd . sortBy (comparing fst) . map (length &&& id) <br />
-- the so called "Schwartzian Transform" for computationally more expensive <br />
-- functions.<br />
<br />
-- comparing adjacent elements<br />
rises xs = zipWith (<) xs (tail xs)<br />
<br />
-- lazy substring search<br />
-- "ell" -> "hello" -> True<br />
substr a b = any (a `isPrefixOf`) $ tails b<br />
<br />
-- multiple splitAt's:<br />
-- splitAts [2,5,0,3] [1..15] == [[1,2],[3,4,5,6,7],[],[8,9,10],[11,12,13,14,15]]<br />
splitAts = foldr (\n r -> splitAt n >>> second r >>> uncurry (:)) return<br />
</haskell><br />
<br />
== Mathematical Sequences, etc ==<br />
<br />
<br />
<haskell><br />
-- factorial<br />
-- 6 -> 720<br />
product [1..6]<br />
<br />
foldl1 (*) [1..6]<br />
<br />
(!!6) $ scanl (*) 1 [1..]<br />
<br />
fix (\f n -> if n <= 0 then 1 else n * f (n-1))<br />
<br />
<br />
-- powers of two sequence<br />
iterate (*2) 1<br />
<br />
unfoldr (\z -> Just (z,2*z)) 1<br />
<br />
<br />
-- fibonacci sequence<br />
unfoldr (\(f1,f2) -> Just (f1,(f2,f1+f2))) (0,1)<br />
<br />
fibs = 0:1:zipWith (+) fibs (tail fibs)<br />
<br />
fib = 0:scanl (+) 1 fib<br />
<br />
<br />
-- pascal triangle<br />
pascal = iterate (\row -> zipWith (+) ([0] ++ row) (row ++ [0])) [1]<br />
<br />
<br />
-- prime numbers<br />
-- example of a memoising caf (??)<br />
primes = sieve [2..] where<br />
sieve (p:x) = p : sieve [ n | n <- x, n `mod` p > 0 ]<br />
<br />
unfoldr sieve [2..] where <br />
sieve (p:x) = Just(p, [ n | n <- x, n `mod` p > 0 ])<br />
<br />
-- or if you want to use the Sieve of Eratosthenes..<br />
diff [] l = l<br />
diff l [] = l<br />
diff xl@(x:xs) yl@(y:ys) | x < y = x:diff xs yl<br />
| x > y = diff xl ys<br />
| otherwise = diff xs ys <br />
esieve [] = []<br />
esieve (p:ps) = p:esieve (diff ps (iterate (+p) p))<br />
eprimes = esieve [2..]<br />
<br />
-- enumerating the rationals (see [1])<br />
rats :: [Rational]<br />
rats = iterate next 1 where<br />
next x = recip (fromInteger n+1-y) where (n,y) = properFraction x<br />
</haskell><br />
<br />
[1] [http://web.comlab.ox.ac.uk/oucl/work/jeremy.gibbons/publications/index.html#rationals Gibbons, Lest, Bird - Enumerating the Rationals]<br />
<br />
== Monad Magic ==<br />
<br />
<br />
<haskell><br />
-- all combinations of a list of lists.<br />
-- these solutions are all pretty much equivalent in that they run<br />
-- in the List Monad. the "sequence" solution has the advantage of<br />
-- scaling to N sublists.<br />
-- "12" -> "45" -> ["14", "15", "24", "25"]<br />
sequence ["12", "45"]<br />
<br />
[[x,y] | x <- "12", y <- "45"]<br />
<br />
do { x <- "12"; y <- "45"; return [x,y] }<br />
<br />
"12" >>= \a -> "45" >>= \b -> return [a,b]<br />
<br />
<br />
-- all combinations of letters<br />
(inits . repeat) ['a'..'z'] >>= sequence<br />
<br />
<br />
-- apply a list of functions to an argument<br />
-- even -> odd -> 4 -> [True,False]<br />
map ($4) [even,odd]<br />
<br />
sequence [even,odd] 4<br />
<br />
<br />
-- all subsequences of a sequence<br />
filterM (const [True, False])<br />
<br />
<br />
-- apply a function to two other function the same argument<br />
-- (lifting to the Function Monad (->))<br />
-- even 4 && odd 4 -> False<br />
liftM2 (&&) even odd 4<br />
<br />
liftM2 (>>) putStrLn return "hello"<br />
<br />
<br />
-- forward function concatenation<br />
(*3) >>> (+1) $ 2<br />
<br />
foldl1 (flip (.)) [(+1),(*2)] 500<br />
<br />
<br />
-- perform functions in/on a monad, lifting<br />
fmap (+2) (Just 2)<br />
<br />
liftM2 (+) (Just 4) (Just 2)<br />
<br />
<br />
-- [still to categorize]<br />
(id >>= (+) >>= (+) >>= (+)) 3 -- (3+3)+(3+3) = 12<br />
<br />
(join . liftM2) (*) (+3) 5 -- 64<br />
<br />
mapAccumL (\acc n -> (acc+n,acc+n)) 0 [1..10] -- interesting for fac, fib, ...<br />
<br />
do f <- [not, not]; d <- [True, False]; return (f d) -- [False,True,False,True]<br />
<br />
do { Just x <- [Nothing, Just 5, Nothing, Just 6, Just 7, Nothing]; return x }<br />
</haskell><br />
<br />
<br />
== Other ==<br />
<br />
<br />
<haskell><br />
-- simulating lisp's cond<br />
case () of () | 1 > 2 -> True<br />
| 3 < 4 -> False<br />
| otherwise -> True<br />
<br />
<br />
-- match a constructor<br />
-- this is better than applying all the arguments, because this way the<br />
-- data type can be changed without touching the code (ideally).<br />
case a of Just{} -> True<br />
_ -> False<br />
<br />
<br />
{- <br />
TODO, IDEAS:<br />
more fun with monad, monadPlus (liftM, ap, guard, when)<br />
fun with arrows (second, first, &&&, ***)<br />
liftM, ap<br />
lazy search (searching as traversal of lazy structures)<br />
innovative data types (i.e. having fun with Maybe sequencing)<br />
<br />
LINKS:<br />
bananas, envelopes, ... (generic traversal)<br />
why functional fp matters (lazy search, ...)<br />
-}<br />
</haskell><br />
<br />
=== Polynomials ===<br />
In abstract algebra you learn that polynomials can be used the same way integers are used given the right assumptions about their coefficients and roots. Specifically, polynomials support addition, subtraction, multiplication and sometimes division. It also turns out that one way to think of polynomials is that they are just lists of numbers (their coefficients). <br />
<br />
instance Num a => Num [a] where -- (1)<br />
<br />
(f:fs) + (g:gs) = f+g : fs+gs -- (2)<br />
fs + [] = fs -- (3a)<br />
[] + gs = gs -- (3b)<br />
<br />
(f:fs) * (g:gs) = f*g : [f]*gs + fs*(g:gs) -- (4)<br />
_ * _ = [] -- (5)<br />
<br />
====Explanation====<br />
(1) puts lists into type class Num, the class to which operators + and * belong, provided the list elements are in class Num.<br />
<br />
Lists are ordered by increasing powers. Thus <tt>f:fs</tt> means <tt>f+x*fs</tt> in algebraic notation. (2) and (4) follow from these algebraic identities:<br />
<br />
(f+x*fs) + (g+x*gs) = f+g + x*(fs+gs)<br />
(f+x*fs) * (g+x*gs) = f*g + x*(f*gs + fs*(g+x*gs))<br />
<br />
(3) and (5) handle list ends.<br />
<br />
The bracketed <tt>[f]</tt> in (4) avoids mixed arithmetic, which Haskell doesn't support.<br />
<br />
====Comments====<br />
<br />
The methods are qualitatively different from ordinary array-based methods; there is no vestige of subscripting or counting of terms.<br />
<br />
The methods are suitable for on-line computation. Only<br />
<i>n</i> terms of each input must be seen before the <i>n</i>-th term<br />
of output is produced.<br />
<br />
Thus the methods work on infinite series as well as polynomials.<br />
<br />
Integer power comes for free. This example tests the cubing of (1+x):<br />
<br />
[1, 1]^3 == [1, 3, 3, 1]<br />
<br />
See also<br />
* [[Pointfree]]<br />
* [http://darcs.haskell.org/numericprelude/src/MathObj/Polynomial.hs NumericPrelude: Polynomials]<br />
* [[Add Polynomials]]<br />
* Solve differential equations in terms of [http://www.haskell.org/pipermail/haskell-cafe/2004-May/006192.html power series].<br />
<br />
[[Category:Idioms]]<br />
[[Category:Mathematics]]</div>JohannesAhlmannhttps://wiki.haskell.org/H-99:_Ninety-Nine_Haskell_ProblemsH-99: Ninety-Nine Haskell Problems2007-01-14T05:33:32Z<p>JohannesAhlmann: added category:code</p>
<hr />
<div>__NOTOC__<br />
<br />
These are Haskell translations of [http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html Ninety-Nine Lisp Problems],<br />
which are themselves translations of [http://www.hta-bi.bfh.ch/~hew/informatik3/prolog/p-99/ Ninety-Nine Prolog Problems].<br />
<br />
If you want to work on one of these, put your name in the block so we know someone's working on it. Then, change n in your block to the appropriate problem number, and fill in the <Problem description>,<example in Haskell>,<solution in haskell> and <description of implementation> fields. Then be sure to update the status on this page to indicate that we have a solution!<br />
<br />
== The problems ==<br />
<br />
These problems have been split into 11 parts, for ease of access.<br />
<br />
* [[99_questions/1_to_10|Questions 1 to 10]]: Lists<br />
* [[99_questions/11_to_20|Questions 11 to 20]]: Lists, continued<br />
* [[99_questions/21_to_28|Questions 21 to 28]]: Lists again<br />
* [[99_questions/31_to_41|Questions 31 to 41]]: Arithmetic<br />
* [[99_questions/46_to_50|Questions 46 to 50]]: Logic and codes<br />
* [[99_questions/54A_to_60|Questions 54A to 60]]: Binary trees<br />
* [[99_questions/61_to_69|Questions 61 to 69]]: Binary trees, continued<br />
* [[99_questions/70B_to_73|Questions 70B to 73]]: Multiway trees<br />
* [[99_questions/80_to_89|Questions 80 to 89]]: Graphs<br />
* [[99_questions/90_to_94|Questions 90 to 94]]: Miscellaneous problems<br />
* [[99_questions/95_to_99|Questions 95 to 99]]: Miscellaneous problems, continued<br />
<br />
(Though the problems number from 1 to 99, there are some gaps and some additions marked with letters.<br />
There are actually only 88 problems.)<br />
<br />
== Status ==<br />
<br />
* [http://www.hta-bi.bfh.ch/~hew/informatik3/prolog/p-99/ P-99: Ninety-Nine Prolog Problems] contains Prolog solutions to all the problems.<br />
* [http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html L-99: Ninety-Nine Lisp Problems] contains Lisp solutions to problems 1-11, 14, 15, 17 and 20-28.<br />
* We still lack Haskell solutions to problems 68, 69, 80-89, 92 and 94. (Please edit this list if you add any solutions.)<br />
<br />
[[Category:Tutorials]]<br />
[[Category:Code]]</div>JohannesAhlmannhttps://wiki.haskell.org/The_Other_PreludeThe Other Prelude2007-01-10T22:03:07Z<p>JohannesAhlmann: added link to NotJustMaybe</p>
<hr />
<div>[[Category:Proposals]]<br />
<br />
== Call For Contribution ==<br />
This fun project, called ''The Other Prelude'', is a creative reconstruction of the standard Prelude. By disregarding history and compatibility, we get a clean sheet.<br />
<br />
== Committee ==<br />
This project has no committee whatsoever. Haskell community discussed the issues [[Talk:The Other Prelude|here]].<br />
<br />
== Naming Conventions ==<br />
* Function names should be easy for beginners to consume. <br />
* Specifically, ''The Other Prelude'' naming convention is to use <br />
** descriptive symbols for functions that are naturally infix (''e.g.'', <hask>mplus</hask> is replaced by <hask>(++)</hask>) <br />
** whole English words and camelCase for functions (''e.g.'', <hask>orElse</hask> but not <hask>fmap</hask>)<br />
<br />
== The Hierarchy ==<br />
Although, not Haskell 98, hierarchical modules will definitely be in Haskell'. We take it for granted.<br />
* <hask>TheOtherPrelude</hask> - Minimalistic module.<br />
* <hask>TheOtherPrelude.Utilities</hask> - Convenient definitions. The reasoning behind its existence is that we want the Prelude to be very concise. It should not steal good names.<br />
<br />
== Open Issues ==<br />
* Should Prelude functions use <hask>Integer</hask> instead of <hask>Int</hask>?<br />
* Should <hask>String</hask> be a class rather than a type synonym?<br />
<br />
== The Code ==<br />
Currently, the code is in Wiki form. If people do agree that the collaborative decisions begot something pretty, we'll have a group of files in darcs.haskell.org some time.<br />
<br />
The imaginery Prelude as it stands,<br />
=== <hask>TheOtherPrelude</hask> ===<br />
<haskell><br />
-- module: TheOtherPrelude<br />
import Prelude () -- hide everything<br />
<br />
<br />
-- the idea is to remove 'fmap'.<br />
-- both map :: (a -> b) -> [a] -> [b] ('fmap' for the monad []) <br />
-- and (.) :: (a -> b) -> (e -> a) -> (e -> b) ('fmap' for the (->) e monad)<br />
-- are good names, and are intuitively prefix and infix respectively.<br />
class Functor f where<br />
-- 'fmap' is guilty of nothing but a bad name<br />
map, (.) :: (a -> b) -> f a -> f b<br />
<br />
-- implementing either is enough<br />
map = (.)<br />
(.) = map<br />
<br />
<br />
-- the following has been shamelessly copied,<br />
-- from the Functor hierarchy proposal[1] wiki page.<br />
class Functor f => Applicative f where<br />
-- lifting a value<br />
return :: a -> f a<br />
<br />
-- should this be named 'ap'? is 'ap' a good name?<br />
-- can you come up with a better name?<br />
-- can it refactor the liftM* type gymnastics?<br />
(<*>) :: f (a -> b) -> f a -> f b <br />
<br />
-- when the second is independent of the first<br />
(>>) :: m a -> m b -> m b<br />
<br />
-- is there a better definition?<br />
fa >> fb = (map (const id) fa) <*> fb<br />
<br />
<br />
-- this leaves little left for the actual Monad class<br />
class Applicative m => Monad m where<br />
-- the binding operation, gist of a monad <br />
(>>=) :: m a -> (a -> m b) -> m b<br />
<br />
-- throwing out the outer monad<br />
join :: m (m a) -> m a<br />
<br />
-- intuitive definitions<br />
x >>= f = join (map f x)<br />
join x = x >>= id<br />
<br />
<br />
-- we shamelessly copy from the MonadPlus reform proposal[2] now.<br />
<br />
-- zero will be used when pattern matching against refutable patterns in<br />
-- do-notation as well as to provide support for monad comprehensions.<br />
<br />
-- should satisfy 'left zero': zero >>= f = zero<br />
class Monad m => MonadZero m where<br />
zero :: m a<br />
<br />
<br />
-- should satisfy 'monoid' <br />
-- zero ++ b = b, b ++ zero = b, (a ++ b) ++ c = a ++ (b ++ c)<br />
-- and 'left distribution'<br />
-- (a ++ b) >>= f = (a >>= f) ++ (b >>= f)<br />
class MonadZero m => MonadPlus m where<br />
(++) :: m a -> m a -> m a<br />
<br />
<br />
-- should satisfy 'monoid' <br />
-- zero `orElse` b = b, b `orElse` zero = b<br />
-- (a `orElse` b) `orElse` c = a `orElse` (b `orElse` c)<br />
-- and 'left catch'<br />
-- (return a) `orElse` b = a<br />
class MonadZero m => MonadOr m where<br />
orElse :: m a -> m a -> m a<br />
</haskell><br />
<br />
[1]: [[Functor hierarchy proposal]]<br /><br />
[2]: [[MonadPlus reform proposal]]<br />
<br />
=== <hask>TheOtherPrelude.Utilities</hask> ===<br />
<haskell><br />
-- module: TheOtherPrelude.Utilities<br />
<br />
import Prelude () -- hide everything<br />
<br />
-- this is the if-then-else proposal<br />
-- the name has been chosen to reflect the magic of Church booleans!<br />
boolean True x _ = x<br />
boolean False _ y = y<br />
<br />
</haskell><br />
== How To Use ==<br />
<haskell><br />
-- ''The Other Prelude'' is an alternative, not a replacement.<br />
-- So we need to hide everything from the Prelude<br />
import Prelude () <br />
<br />
-- This is just an example assuming there is nothing to hide<br />
import TheOtherPrelude <br />
<br />
-- Hopefully, this module will contain lift,...<br />
-- Standard convention is to use M.lift (instead of liftM)<br />
import qualified TheOtherPrelude.Monad.Kleisli as M <br />
</haskell><br />
<br />
== See also ==<br />
* [[Mathematical prelude discussion]] - A numeric Prelude in good shape already. Will a merger be ever possible?<br />
* [[Prelude extensions]] and [[Prelude function suggestions]] - Unlike ''The Other Prelude'' they ''enhance'' the Prelude.<br />
* [[Functor hierarchy proposal]] - Making <hask>Monad m</hask> imply <hask>Functor m</hask> (adopted by ''The Other Prelude'').<br />
* [[If-then-else]] - Making <hask>if</hask> a function (partially adopted by ''The Other Prelude'', we are silent on the bigger issue of sugar).<br />
* [http://software.complete.org/missingh/static/doc/ MissingH] - Functions "missing" from the Haskell Prelude/libraries.<br />
* [[MonadPlus reform proposal]] - Clarifies ambiguities around MonadPlus laws (adopted by ''The Other Prelude'') <br />
* [http://haskell.org/hawiki/NotJustMaybe NotJustMaybe] - Instead of writing inside a specific monad (i.e. Maybe) write functions generalized on (Monad m)=> where possible.<br />
[[Category:Mathematics]]<br />
[[Category:Code]]</div>JohannesAhlmannhttps://wiki.haskell.org/GroupBy_proposalGroupBy proposal2007-01-10T17:51:34Z<p>JohannesAhlmann: </p>
<hr />
<div>[[Category:Proposals]]<br />
<br />
I was a bit annoyed when I found out that Data.List.groupBy compared each new element to the first element of a group instead of the last added element.<br />
<br />
I guess the current way it is easier to implement, but severely hinders its usefulness:<br />
<br />
<haskell><br />
> groupBy (\a b -> a+1 == b) [1,2,3,4,6]<br />
[[1,2],[3,4],[6]]<br />
</haskell><br />
<br />
I propose a different implementation of groupBy which would result in the following:<br />
<br />
<haskell><br />
> groupBy (\a b -> a+1 == b) [1,2,3,4,6]<br />
[[1,2,3,4],[6]]<br />
</haskell><br />
<br />
The following a naive implementation that was written for "workiness" instead of speed or space behavior:<br />
<br />
<haskell><br />
groupBy' :: (a -> a -> Bool) -> [a] -> [[a]]<br />
groupBy' _ [] = []<br />
groupBy' f (x:xs) = gb f xs [[x]]<br />
where gb f (x:xs) ((a:as):bs) = gb f xs $ if f a x then ((x:a:as):bs)<br />
else ([x]:(a:as):bs)<br />
gb _ [] as = reverse . map reverse $ as <br />
</haskell><br />
<br />
I'm sure there are much nicer ways to implement this...</div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Quiz/DayRange/Solution_Jethr0Haskell Quiz/DayRange/Solution Jethr02007-01-10T17:41:24Z<p>JohannesAhlmann: using a modified version of groupBy</p>
<hr />
<div>[[Category:Code]]<br />
<br />
<haskell><br />
-- > dayRange [1,2,3,6,7]<br />
-- "Mon-Wed, Sat, Sun"<br />
module DayRange where<br />
import Data.List (intersperse,sort)<br />
<br />
-- > dayRange [1,2,3,6,7]<br />
-- "Mon-Wed, Sat, Sun"<br />
data Weekday = Mon | Tue | Wed | Thu | Fri | Sat | Sun deriving (Show,Enum)<br />
<br />
dayRange :: [Int] -> String<br />
dayRange = sepComma . map range . map (map toWeekday) . groupBy' (\a b -> a+1 == b) . sort<br />
where sepComma = concat . intersperse ", "<br />
toWeekday x = show $ (toEnum (x-1) :: Weekday)<br />
range xs | length xs < 3 = sepComma xs<br />
| otherwise = head xs ++ "-" ++ last xs<br />
<br />
-- groupBy compares any element to the first one of the group<br />
-- groupBy' instead compares an element to the last added group element<br />
groupBy' :: (a -> a -> Bool) -> [a] -> [[a]]<br />
groupBy' f (x:xs) = gb f xs [[x]]<br />
where gb f (x:xs) ((a:as):bs) = gb f xs $ if f a x then ((x:a:as):bs)<br />
else ([x]:(a:as):bs)<br />
gb _ [] as = reverse . map reverse $ as <br />
</haskell></div>JohannesAhlmannhttps://wiki.haskell.org/Shootout/Reverse_complementShootout/Reverse complement2007-01-09T17:46:43Z<p>JohannesAhlmann: line'd the benchmark results</p>
<hr />
<div>This is a ShootoutEntry for [http://shootout.alioth.debian.org/benchmark.php?test=revcomp&lang=all].<br />
<br />
about the reverse-complement benchmark<br />
<br />
Each program should<br />
<br />
* read line-by-line a redirected FASTA format file from stdin<br />
* for each sequence: write the id, description, and the reverse-complement sequence in FASTA format to stdout<br />
<br />
We use the FASTA file generated by the fasta benchmark as input for this benchmark. Note: the file may include both lowercase and uppercase codes.<br />
<br />
We use these code complements:<br />
<br />
code meaning complement<br />
A A T<br />
C C G<br />
G G C<br />
T/U T A<br />
M A or C K<br />
R A or G Y<br />
W A or T W<br />
S C or G S<br />
Y C or T R<br />
K G or T M<br />
V A or C or G B<br />
H A or C or T D<br />
D A or G or T H<br />
B C or G or T V<br />
N G or A or T or C N<br />
<br />
<br />
"by knowing the sequence of bases of one strand of DNA we immediately know the sequence of the DNA strand which will bind to it, this strand is called the reverse complement"<br />
DNA: Structure and Function <br />
<br />
= New Code =<br />
<br />
Performance for various entries. Size of data = 5M.<br />
<br />
{| border="1"<br />
! Code !! Time in seconds for a given file<br />
|-<br />
| Don Stewart v1 || 30.85 <br />
|-<br />
| Original entry || 24.13 <br />
|-<br />
| Mutable version 1 || 2.44 <br />
|-<br />
| Mutable version 2 || 1.67 <br />
|-<br />
|-<br />
| gcc -Onot || 0.33 <br />
|}<br />
<br />
<br />
== Data.ByteString ==<br />
<br />
Translation of "Don Stewart v1" to use Data.ByteString.<br />
About 2x faster than Mutable version 2, on my OpenBSD x86 box.<br />
<br />
Todo. Submit this.<br />
<br />
<haskell><br />
{-# OPTIONS -cpp -fglasgow-exts -O2 -optc-O3 -funbox-strict-fields #-}<br />
--<br />
-- Reverse complement benchmark<br />
--<br />
-- Written by Don Stewart<br />
--<br />
import GHC.Base<br />
import Data.Char<br />
import qualified Data.ByteString as B<br />
<br />
main = B.getContents >>= process B.empty []<br />
<br />
process h b ps<br />
| h `seq` b `seq` ps `seq` False = undefined<br />
| B.null ps = write h b<br />
| x == '>' = write h b >> process h' [] ps'<br />
| x == '\n' = process h b xs<br />
| otherwise = process h ((complement . toUpper $ x) : b) xs<br />
where (x,xs) = (B.unsafeHead ps, B.unsafeTail ps)<br />
(h',ps') = B.breakOn '\n' ps<br />
<br />
write h s<br />
| B.null h = return ()<br />
| otherwise = B.putStrLn h >> write_ (B.pack s)<br />
where<br />
write_ t<br />
| B.null t = return ()<br />
| otherwise = let (a,b) = B.splitAt 60 t in B.putStrLn a >> write_ b<br />
<br />
complement (C# i) = C# (indexCharOffAddr# arr (ord# i -# 65#))<br />
where arr = "TVGH CD M KN YSAABW R"#<br />
</haskell><br />
<br />
== Mutable version 2 ==<br />
<br />
This is the fastest Haskell entry so far. It uses mutable arrays, as<br />
well as a handcrafted inner-loop on the reverse, and doesn't waste time<br />
coercing the input chars to words (and identity, in this case, anyway).<br />
<br />
<haskell><br />
<br />
{-# OPTIONS -fglasgow-exts -O2 -optc-O3 #-}<br />
<br />
--<br />
-- <br />
-- Translation of C version to Haskell by Don Stewart<br />
--<br />
<br />
import Data.Char<br />
import Control.Arrow<br />
import Foreign.Marshal.Array<br />
import Foreign.Storable<br />
import Control.Monad<br />
import qualified Control.Exception as C<br />
import System.IO<br />
import GHC.IOBase<br />
import GHC.Base<br />
import GHC.Ptr<br />
import GHC.Word<br />
<br />
pairs = map (c2w *** c2w) [('A','T'),('C','G'),('B','V'),('D','H'),('K','M'),('R','Y'),('\0','\0')]<br />
<br />
main = do<br />
inp <- mallocArray 129 :: IO (Ptr Word8)<br />
buf <- mallocArray 1024 :: IO (Ptr Word8)<br />
iubP <- sequence [ newArray [x,y] | (x,y) <- pairs ] >>= newArray<br />
iubC <- newArray (map c2w ['\0'..'\255']++[0])<br />
buildIubComplement iubC iubP (0 :: Int)<br />
(slen,inp) <- go 0 128 inp buf iubC<br />
when (slen > 0) $ process iubC inp slen<br />
<br />
go slen mlen inp buffer iubC = do<br />
eof <- C.catch (getLine >>= pokeArray0 0 buffer . c2ws . take 1023 >> return False)<br />
(\_ -> return True)<br />
if eof then return (slen,inp) else do<br />
b0 <- buffer ! (0::Int)<br />
if b0 == c2w '>' <br />
then do when (slen > 0) $ process iubC inp slen<br />
lengthArray0 0 buffer >>= hPutBuf stdout buffer >> putChar '\n'<br />
go 0 mlen inp buffer iubC<br />
<br />
else do l <- lengthArray0 0 buffer >>= shrink buffer . (+1)<br />
(inp',mlen') <- tweak slen mlen l inp<br />
copyArray (inp' `plusPtr` slen) buffer l<br />
go (slen + l) mlen' inp' buffer iubC<br />
<br />
process iubc strand len = do<br />
inplacereverse iubc strand len<br />
(s,l) <- print60 strand len<br />
hPutBuf stdout s l >> putChar '\n'<br />
<br />
print60 s n <br />
| n <= 60 = return (s,n)<br />
| otherwise = do<br />
hPutBuf stdout s 60 >> putChar '\n'<br />
print60 (s `advancePtr` 60) (n - 60)<br />
<br />
tweak slen mlen l inp <br />
| slen + l <= mlen = return (inp,mlen)<br />
| otherwise = do <br />
let mlen' = mlen + mlen<br />
inp' <- reallocArray0 inp mlen'<br />
tweak slen mlen' l inp'<br />
<br />
shrink b l | l <= 0 = return l<br />
| otherwise = do<br />
bl1 <- b ! (l-1)<br />
if not . isAlpha . w2c $ bl1 then shrink b (l-1) else return l<br />
<br />
buildIubComplement iubC iubP i = do<br />
i0 <- index2 iubP i (0::Int)<br />
when (i0 /= 0) $ do<br />
i1 <- index2 iubP i (1::Int) <br />
set iubC i0 i1<br />
set iubC i1 i0<br />
set iubC (tolower i0) i1<br />
set iubC (tolower i1) i0<br />
buildIubComplement iubC iubP (i+1)<br />
<br />
inplacereverse iubc@(Ptr r) strand@(Ptr s) len@(I# ln) = do <br />
(i,l) <- IO $ reverseit r s 0# (ln -# 1#)<br />
when (i == l) $ strand ! i >>= (iubc !) >>= set strand i<br />
<br />
reverseit iubc strand i l s =<br />
if i >=# l <br />
then (# s, (I# i, I# l) #)<br />
else case readWord8OffAddr# strand i s of { (# s, c #) -> <br />
case readWord8OffAddr# strand l s of { (# s, x #) -> <br />
case readWord8OffAddr# iubc (word2Int# x) s of { (# s, y #) -> <br />
case readWord8OffAddr# iubc (word2Int# c) s of { (# s, z #) -><br />
case writeWord8OffAddr# strand i y s of { s -><br />
case writeWord8OffAddr# strand l z s of { s -><br />
reverseit iubc strand (i +# 1#) (l -# 1#) s<br />
} } } } } }<br />
<br />
arr ! i = peekElemOff arr (fromIntegral i)<br />
set arr i n = pokeElemOff arr (fromIntegral i) n<br />
<br />
index2 arr i j = arr ! i >>= (! j)<br />
set2 arr i j n = arr ! i >>= \arr' -> set arr' j n<br />
<br />
c2w = fromIntegral . ord<br />
w2c = chr . fromIntegral<br />
c2ws = unsafeCoerce#<br />
tolower = fromIntegral . ord . toLower . chr . fromIntegral<br />
</haskell><br />
<br />
<br />
<br />
== Mutable version 1 ==<br />
<br />
This is a translation of the fast C entry into Haskell. It uses mutable arrays.<br />
<br />
<haskell><br />
{-# OPTIONS -fglasgow-exts -O2 -optc-O3 #-}<br />
<br />
--<br />
-- Translation of C version by Don Stewart<br />
--<br />
<br />
import Data.Word<br />
import Data.Char<br />
import Control.Arrow<br />
import Foreign.Marshal.Array<br />
import Foreign.Storable<br />
import Foreign.Ptr<br />
import Control.Monad<br />
import qualified Control.Exception as C<br />
import System.IO<br />
<br />
pairs :: [(Word8,Word8)]<br />
pairs = map (c2w *** c2w) [('A','T'),('C','G'),('B','V'),('D','H'),('K','M'),('R','Y'),('\0','\0')]<br />
<br />
c2w :: Char -> Word8<br />
c2w = fromIntegral . ord<br />
<br />
w2c :: Word8 -> Char<br />
w2c = chr . fromIntegral<br />
<br />
tolower :: Word8 -> Word8<br />
tolower = fromIntegral . ord . toLower . chr . fromIntegral<br />
<br />
main = do<br />
inp <- mallocArray 129 :: IO (Ptr Word8)<br />
buf <- mallocArray 1024 :: IO (Ptr Word8)<br />
iubP <- sequence [ newArray [x,y] | (x,y) <- pairs ] >>= newArray<br />
iubC <- newArray (map c2w ['\0'..'\255']++[0])<br />
buildIubComplement iubC iubP (0 :: Int)<br />
(slen,inp) <- go 0 128 inp buf iubC<br />
when (slen > 0) $ process iubC inp slen<br />
<br />
go slen mlen inp buffer iubC = do<br />
eof <- C.catch (getLine >>= pokeArray0 0 buffer . map c2w . take 1023 >> return False) <br />
(\_ -> return True)<br />
if eof then return (slen,inp) else do<br />
b0 <- buffer ! (0::Int)<br />
if b0 == c2w '>' <br />
then do when (slen > 0) $ process iubC inp slen<br />
lengthArray0 0 buffer >>= hPutBuf stdout buffer >> putChar '\n'<br />
go 0 mlen inp buffer iubC<br />
<br />
else do l <- lengthArray0 0 buffer >>= shrink buffer . (+1)<br />
(inp',mlen') <- tweak slen mlen l inp<br />
copyArray (inp' `plusPtr` slen) buffer l<br />
go (slen + l) mlen' inp' buffer iubC<br />
<br />
inplacereverse :: Ptr Word8 -> Ptr Word8 -> Int -> IO ()<br />
inplacereverse iubc strand len = do <br />
(i,l) <- reverseit iubc strand 0 (len-1)<br />
when (i == l) $ strand ! i >>= (iubc !) >>= set strand i<br />
<br />
reverseit iubc strand i l <br />
= if i >= l then return (i,l)<br />
else do c <- strand ! i<br />
strand ! l >>= (iubc !) >>= set strand i<br />
iubc ! c >>= set strand l<br />
reverseit iubc strand (i+1) (l-1)<br />
<br />
process :: Ptr Word8 -> Ptr Word8 -> Int -> IO ()<br />
process iubc strand len = do<br />
inplacereverse iubc strand len<br />
(s,l) <- print60 strand len<br />
hPutBuf stdout s l >> putChar '\n'<br />
<br />
print60 s n <br />
| n <= 60 = return (s,n)<br />
| otherwise = do<br />
hPutBuf stdout s 60 >> putChar '\n'<br />
print60 (s `advancePtr` 60) (n - 60)<br />
<br />
tweak slen mlen l inp <br />
| slen + l <= mlen = return (inp,mlen)<br />
| otherwise = do <br />
let mlen' = mlen + mlen<br />
inp' <- reallocArray0 inp mlen'<br />
tweak slen mlen' l inp'<br />
<br />
shrink b l =<br />
if l <= 0 <br />
then return l<br />
else do bl1 <- b ! (l-1)<br />
if not . isAlpha . w2c $ bl1<br />
then shrink b (l-1) <br />
else return l<br />
<br />
buildIubComplement iubC iubP i = do<br />
i0 <- index2 iubP i (0::Int)<br />
when (i0 /= 0) $ do<br />
i1 <- index2 iubP i (1::Int) <br />
set iubC i0 i1<br />
set iubC i1 i0<br />
set iubC (tolower i0) i1<br />
set iubC (tolower i1) i0<br />
buildIubComplement iubC iubP (i+1)<br />
<br />
arr ! i = peekElemOff arr (fromIntegral i)<br />
set arr i n = pokeElemOff arr (fromIntegral i) n<br />
<br />
index2 arr i j = arr ! i >>= (! j)<br />
<br />
set2 arr i j n = arr ! i >>= \arr' -> set arr' j n<br />
</haskell><br />
<br />
== Don Stewart v1 ==<br />
<br />
A combination of the original entry, with an array index idea from the alex lexer. The original verbose version uses marginally less heap space, and they're both roughly the same speed. This version uses half the space of the array index version.<br />
<br />
<haskell><br />
{-# OPTIONS -fglagsow-exts #-}<br />
import GHC.Base<br />
import Data.Char<br />
<br />
main = getContents >>= process . (,,) [] []<br />
<br />
complement (C# i) = C# (indexCharOffAddr# arr (ord# i -# 65#))<br />
where arr = "TVGH..CD..M.KN...YSAABW.R"#<br />
<br />
process (h,b,c@('>':_)) = write h b >> process (h',[],cs')<br />
where (h',cs') = break (=='\n') c<br />
process (h,b,('\n':cs)) = process (h,b,cs)<br />
process (h,b,(c:cs)) = process (h,((complement $ toUpper c):b),cs)<br />
process (h,b,[]) = write h b<br />
<br />
write [] _ = return ()<br />
write h s = putStrLn h >> write' s<br />
where write' [] = return ()<br />
write' t = let (a,b) = splitAt 60 t in putStrLn a >> write' b<br />
</haskell><br />
<br />
<br />
= Old Code =<br />
<br />
This is the original haskell entry<br />
<br />
<haskell><br />
<br />
-- The Great Computer Language Shootout<br />
-- http://shootout.alioth.debian.org/<br />
-- contributed by Jeff Newbern<br />
<br />
-- Note: This code has not been optimized *at all*. It is written to be clear<br />
-- and concise, using standard Haskell idioms. Performance is decent with<br />
-- ghc -O2, but if it can be improved without sacrificing the clarity of the<br />
-- code, by all means go for it!<br />
<br />
import Data.Char(toLower)<br />
<br />
type Base = Char<br />
type Sequence = [Base]<br />
<br />
complement :: Base -> Base<br />
complement 'A' = 'T'<br />
complement 'a' = 'T'<br />
complement 'C' = 'G'<br />
complement 'c' = 'G'<br />
complement 'G' = 'C'<br />
complement 'g' = 'C'<br />
complement 'T' = 'A'<br />
complement 't' = 'A'<br />
complement 'U' = 'A'<br />
complement 'u' = 'A'<br />
complement 'M' = 'K'<br />
complement 'm' = 'K'<br />
complement 'R' = 'Y'<br />
complement 'r' = 'Y'<br />
complement 'Y' = 'R'<br />
complement 'y' = 'R'<br />
complement 'K' = 'M'<br />
complement 'k' = 'M'<br />
complement 'V' = 'B'<br />
complement 'v' = 'B'<br />
complement 'H' = 'D'<br />
complement 'h' = 'D'<br />
complement 'D' = 'H'<br />
complement 'd' = 'H'<br />
complement 'B' = 'V'<br />
complement 'b' = 'V'<br />
complement x = x<br />
<br />
-- write a sequence in Fasta format<br />
writeFasta :: String -> Sequence -> IO ()<br />
writeFasta [] _ = do return ()<br />
writeFasta header sequence =<br />
do putStrLn header<br />
writeWrapped 60 sequence<br />
where writeWrapped _ [] = do return ()<br />
writeWrapped len str = do let (s1,s2) = splitAt len str<br />
putStrLn s1<br />
writeWrapped len s2<br />
<br />
-- recurse over input stream, accumulating and writing processed sequences<br />
process :: (String,[Base],String) -> IO()<br />
process (header,bases,[]) = writeFasta header bases<br />
process (header,bases,c@('>':cs)) = do writeFasta header bases<br />
let (header',cs') = break (\c->c == '\n') c<br />
process (header',[],cs')<br />
process (header,bases,('\n':cs)) = process (header,bases,cs)<br />
process (header,bases,(c:cs)) = process (header,((complement c):bases),cs)<br />
<br />
main = do cs <- getContents<br />
process ([],[],cs)<br />
</haskell><br />
<br />
[[Category:Code]]</div>JohannesAhlmannhttps://wiki.haskell.org/The_Other_PreludeThe Other Prelude2006-12-26T02:09:49Z<p>JohannesAhlmann: use "Integer" instead of "Int"</p>
<hr />
<div>[[Category:Proposals]]<br />
<br />
== Call for contribution ==<br />
This fun project, called "The Other Prelude", and is a creative reconstruction of the standard Prelude. By disregarding history and compatibility, we get a clean sheet.<br />
<br />
== Naming conventions ==<br />
The principal is to make the names very readable for both beginners and category theorists (if any).<br />
<br />
== Guidelines ==<br />
* The prelude should not contain any "projection" functions (like <hask>fst</hask> and <hask>snd</hask>. They go to the Extension module.<br />
<br />
<br />
== Issues ==<br />
* Should alphanumeric names be preferred over symbols when defining a class?<br />
* Why do many functions in Prelude use <hask>Int</hask> instead of <hask>Integer</hask>? IMO, <hask>Integer</hask> should be THE preferred datatype for everything (examples: length, splitAt, replicate, drop, take, ...)!<br />
<br />
<br />
== The hierarchy ==<br />
* <hask>TheOtherPrelude</hask> - Minimalistic module.<br />
* <hask>TheOtherPrelude.Extension</hask> - Convenient definitions.<br />
<br />
== The code ==<br />
Currently, the code is in Wiki form. If people do agree that the collaborative decisions begot something pretty, we'll have a group of files in darcs.haskell.org some time.<br />
<br />
The imaginery Prelude as it stands,<br />
<br />
<haskell><br />
import Prelude () -- hide everything<br />
<br />
-- the idea is to remove 'fmap' <br />
-- and map :: (a -> b) -> [a] -> [b] to be a special case<br />
-- as well as having (.) :: (a -> b) -> (e -> a) -> (e -> b) as a<br />
-- special case from the Functor instance for ((->) e)<br />
-- Both notations can be provided to allow for clarity in different situations.<br />
class Functor f where<br />
map :: (a -> b) -> f a -> f b<br />
(.) :: (a -> b) -> f a -> f b<br />
map = (.)<br />
(.) = map<br />
<br />
-- the following has been shamelessly copied <br />
-- from the functor hierarchy proposal wiki page<br />
class Functor f => Applicative f where<br />
return :: a -> f a<br />
(<*>) :: f (a -> b) -> f a -> f b -- or should this be named 'ap'? <br />
-- or something even better?<br />
-- could this nice looking function<br />
-- refactor the liftM* idioms?<br />
<br />
(>>) :: f a -> f b -> f b<br />
fa >> fb = (map (const id) fa) <*> fb<br />
<br />
-- this leaves little left for the actual Monad class<br />
class (Applicative m) => Monad m where<br />
(>>=) :: m a -> (a -> m b) -> m b<br />
join :: m (m a) -> m a<br />
<br />
x >>= f = join (map f x)<br />
join x = x >>= id<br />
<br />
-- end of Functor hierarchy dilemma<br />
<br />
-- zero will be used when pattern matching against refutable patterns in<br />
-- do-notation as well as to provide support for monad comprehensions.<br />
class (Monad m) => MonadZero m where<br />
zero :: m a<br />
<br />
class (MonadZero m) => MonadPlus m where<br />
(++) :: m a -> m a -> m a<br />
<br />
class (MonadZero m) => MonadOr m where<br />
orElse :: m a -> m a -> m a<br />
<br />
</haskell><br />
<br />
How to use it, as it stands,<br />
<br />
<haskell><br />
import Prelude () -- hide everything<br />
import TheOtherPrelude -- get everything<br />
import qualified TheOtherPrelude.Monad.Kleisli as M -- standard convention <br />
</haskell><br />
<br />
== See also ==<br />
* [[Mathematical prelude discussion]] - A numeric Prelude. Could this be merged into this one?<br />
* [[Prelude extensions]] and [[Prelude function suggestions]] - Unlike "The Other Prelude" they ''enhance'' the Prelude.<br />
* [[Functor hierarchy proposal]] - making "Monad m" imply "Functor m"<br />
* [[If-then-else]] - making "if" a function<br />
* [http://software.complete.org/missingh/static/doc/ MissingH] - functions "missing" from the haskell Prelude/libraries<br />
<br />
[[Category:Mathematics]]<br />
[[Category:Code]]</div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Quiz/Animal_Quiz/Solution_Jethr0Haskell Quiz/Animal Quiz/Solution Jethr02006-12-23T13:37:22Z<p>JohannesAhlmann: Haskell Quiz/Animal Quiz/Solution Animal Quiz moved to Haskell Quiz/Animal Quiz/Solution Jethr0</p>
<hr />
<div>[[Category:Code]]<br />
<haskell><br />
data Question = Question {qString :: String, qYes,qNo :: Question} | Guess String deriving (Show,Eq)<br />
<br />
getAnswer :: String -> IO Bool<br />
getAnswer prompt = do putStrLn prompt<br />
let loop = do a <- getLine<br />
case a of<br />
"y" -> return True<br />
"n" -> return False<br />
_ -> loop<br />
loop <br />
<br />
initQuestion = Guess "an elephant"<br />
<br />
loopAsk q = do ask' <- ask q<br />
again <- getAnswer "Play again? (y/n)"<br />
if again then loopAsk ask' else return ask'<br />
<br />
ask :: Question -> IO Question<br />
ask (Guess animal) = do answer <- getAnswer $ "Is it " ++ animal ++ "? (y/n)"<br />
if answer then do putStrLn "I win. Pretty smart, aren't I?"<br />
return (Guess animal)<br />
else addEntry animal<br />
ask q@Question{} = do answer <- getAnswer $ qString q<br />
new <- ask $ if answer then qYes q else qNo q<br />
return $ if answer then q{qYes = new} else q{qNo = new}<br />
<br />
addEntry :: String -> IO Question<br />
addEntry oldAnimal = <br />
do putStrLn "You win. Help me learn from my mistake before you go..."<br />
putStrLn "What animal were you thinking of?"<br />
animal <- getLine<br />
putStrLn $ "Give me a question to distinguish " ++ animal ++ " from " ++ oldAnimal<br />
question <- getLine<br />
answer <- getAnswer $ "For " ++ animal ++ ", what is the answer to your question? (y/n)"<br />
putStrLn "Thanks."<br />
let (y,n) = if answer then (animal, oldAnimal) else (oldAnimal, animal)<br />
return $ Question {qString = question, qYes = (Guess y), qNo = (Guess n)}<br />
</haskell></div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Quiz/Animal_Quiz/Solution_Animal_QuizHaskell Quiz/Animal Quiz/Solution Animal Quiz2006-12-23T13:37:22Z<p>JohannesAhlmann: Haskell Quiz/Animal Quiz/Solution Animal Quiz moved to Haskell Quiz/Animal Quiz/Solution Jethr0: sorry, my bad</p>
<hr />
<div>#redirect [[Haskell Quiz/Animal Quiz/Solution Jethr0]]</div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Quiz/Animal_QuizHaskell Quiz/Animal Quiz2006-12-23T13:36:59Z<p>JohannesAhlmann: fixed link to my solution</p>
<hr />
<div>Animal Quiz (#15)<br />
<br />
It works like this. The program starts by telling the user to think of an animal. It then begins asking a series of yes/no questions about that animal: does it swim, does it have hair, etc. Eventually, it will narrow down the possibilities to a single animal and guess that (Is it a mouse?).<br />
<br />
If the program has guessed correctly, the game is over and may be restarted with a new animal. If the program has guess incorrectly, it asks the user for the kind of animal they were thinking of and then asks for the user to provide a question that can distinguish between its incorrect guess and the correct answer. It then adds the new question and animal to its "database" and will guess that animal in the future (if appropriate).<br />
<br />
==The Problem==<br />
<br />
* http://www.rubyquiz.com/quiz15.html<br />
<br />
==Solutions==<br />
<br />
* [[Haskell Quiz/Animal Quiz/Solution Jethr0|Jethr0]]</div>JohannesAhlmannhttps://wiki.haskell.org/Haskell_Quiz/Animal_Quiz/Solution_Jethr0Haskell Quiz/Animal Quiz/Solution Jethr02006-12-23T13:36:20Z<p>JohannesAhlmann: Haskell Quiz/Countdown/Solution Animal Quiz moved to Haskell Quiz/Animal Quiz/Solution Animal Quiz</p>
<hr />
<div>[[Category:Code]]<br />
<haskell><br />
data Question = Question {qString :: String, qYes,qNo :: Question} | Guess String deriving (Show,Eq)<br />
<br />
getAnswer :: String -> IO Bool<br />
getAnswer prompt = do putStrLn prompt<br />
let loop = do a <- getLine<br />
case a of<br />
"y" -> return True<br />
"n" -> return False<br />
_ -> loop<br />
loop <br />
<br />
initQuestion = Guess "an elephant"<br />
<br />
loopAsk q = do ask' <- ask q<br />
again <- getAnswer "Play again? (y/n)"<br />
if again then loopAsk ask' else return ask'<br />
<br />
ask :: Question -> IO Question<br />
ask (Guess animal) = do answer <- getAnswer $ "Is it " ++ animal ++ "? (y/n)"<br />
if answer then do putStrLn "I win. Pretty smart, aren't I?"<br />
return (Guess animal)<br />
else addEntry animal<br />
ask q@Question{} = do answer <- getAnswer $ qString q<br />
new <- ask $ if answer then qYes q else qNo q<br />
return $ if answer then q{qYes = new} else q{qNo = new}<br />
<br />
addEntry :: String -> IO Question<br />
addEntry oldAnimal = <br />
do putStrLn "You win. Help me learn from my mistake before you go..."<br />
putStrLn "What animal were you thinking of?"<br />
animal <- getLine<br />
putStrLn $ "Give me a question to distinguish " ++ animal ++ " from " ++ oldAnimal<br />
question <- getLine<br />
answer <- getAnswer $ "For " ++ animal ++ ", what is the answer to your question? (y/n)"<br />
putStrLn "Thanks."<br />
let (y,n) = if answer then (animal, oldAnimal) else (oldAnimal, animal)<br />
return $ Question {qString = question, qYes = (Guess y), qNo = (Guess n)}<br />
</haskell></div>JohannesAhlmann