<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mokka mit Schlag &#187; Haskell</title>
	<atom:link href="http://www.elharo.com/blog/category/software-development/haskell/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.elharo.com/blog</link>
	<description>Ranting and Raving</description>
	<lastBuildDate>Wed, 01 Feb 2012 13:01:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Data Constructors and Readability</title>
		<link>http://www.elharo.com/blog/software-development/haskell/2009/02/05/data-constructors-and-readability/</link>
		<comments>http://www.elharo.com/blog/software-development/haskell/2009/02/05/data-constructors-and-readability/#comments</comments>
		<pubDate>Thu, 05 Feb 2009 16:23:18 +0000</pubDate>
		<dc:creator>Elliotte Rusty Harold</dc:creator>
				<category><![CDATA[Haskell]]></category>

		<guid isPermaLink="false">http://www.elharo.com/blog/?p=1002094</guid>
		<description><![CDATA[I think I&#8217;ve put my finger on one reason I&#8217;m finding Haskell hard to read. Consider this algebraic data type definition from Real World Haskell: data Doc = Empty &#124; Char Char &#124; Text String &#124; Line &#124; Concat Doc Doc &#124; Union Doc Doc deriving (Show, Eq) There&#8217;s no distinction between the value constructor [...]]]></description>
			<content:encoded><![CDATA[<p>I think I&#8217;ve put my finger on one reason I&#8217;m finding Haskell hard to read. Consider this algebraic data type definition from <cite>Real World Haskell</cite>:</p>
<pre>data Doc = Empty
         | Char Char
         | Text String
         | Line
         | Concat Doc Doc
         | Union Doc Doc
         deriving (Show, Eq)</pre>
<p>There&#8217;s no distinction between the value constructor and the components of the type. This is especially critical when the constructor and the components have the same name as in the <code>Char</code> constructor above. It also doesn&#8217;t help that they have the same naming convention (mixed camel case, initial uppercase letter). </p>
<p>A Java class with multiple factory methods or multiple constructors would be much more verbose, but much more readable. Humans need redundancy, even if it&#8217;s logically superfluous.</p>
<p>I suspect a language that retained Haskell&#8217;s semantics, but completely replaced the syntax with something more usable, legible, and familiar would have a much greater chance of success. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.elharo.com/blog/software-development/haskell/2009/02/05/data-constructors-and-readability/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>unlines with fold</title>
		<link>http://www.elharo.com/blog/software-development/haskell/2009/01/27/unlines-with-fold/</link>
		<comments>http://www.elharo.com/blog/software-development/haskell/2009/01/27/unlines-with-fold/#comments</comments>
		<pubDate>Tue, 27 Jan 2009 15:01:40 +0000</pubDate>
		<dc:creator>Elliotte Rusty Harold</dc:creator>
				<category><![CDATA[Haskell]]></category>

		<guid isPermaLink="false">http://www.elharo.com/blog/?p=1002080</guid>
		<description><![CDATA[Real World Haskell, Exercise 10, p. 99: This was an easy one: myUnlines :: [String] -> String myUnlines xs = foldr (addLine) "" xs where addLine c acc = acc ++ c ++ "\n" It&#8217;s pretty much straight down the path of exactly what folds are meant for, though the inferred types still managed to [...]]]></description>
			<content:encoded><![CDATA[<p><cite><a href="http://book.realworldhaskell.org/read/functional-programming.html">Real World Haskell</a></cite>, Exercise 10, p. 99: This was an easy one:</p>
<pre>myUnlines :: [String] -> String
myUnlines xs = foldr (addLine) "" xs
    where addLine c acc = acc ++ c ++ "\n"</pre>
<p>It&#8217;s pretty much straight down the path of exactly what folds are meant for, though the inferred types still managed to surprise me, and my initial implementation was about twice this size. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.elharo.com/blog/software-development/haskell/2009/01/27/unlines-with-fold/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>words with fold</title>
		<link>http://www.elharo.com/blog/software-development/haskell/2009/01/26/words-with-fold/</link>
		<comments>http://www.elharo.com/blog/software-development/haskell/2009/01/26/words-with-fold/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 15:48:30 +0000</pubDate>
		<dc:creator>Elliotte Rusty Harold</dc:creator>
				<category><![CDATA[Haskell]]></category>

		<guid isPermaLink="false">http://www.elharo.com/blog/?p=1002069</guid>
		<description><![CDATA[Real World Haskell, Exercise 10, p. 98: Write the words function using list folds: myWords :: String -> [String] myWords s = reverse (foldr step [] (trim s)) step :: Char -> [String] -> [String] step c [] = [c:[]] step c acc &#124; (isSpace c) = acc ++ [""] &#124; otherwise = (take ((length [...]]]></description>
			<content:encoded><![CDATA[<p><cite><a href="http://book.realworldhaskell.org/read/functional-programming.html">Real World Haskell</a></cite>, Exercise 10, p. 98: Write the <code>words</code> function using list folds: </p>
<pre>myWords :: String -> [String]
myWords s = reverse (foldr step [] (trim s))

step :: Char -> [String] -> [String]
step c [] = [c:[]]
step c acc
    | (isSpace c) = acc ++ [""]
    | otherwise = (take ((length acc) - 1) acc) ++ [c:(last acc)]

isSpace :: Char -> Bool
isSpace ' '  = True
isSpace '\n' = True
isSpace '\r' = True
isSpace '\t' = True
isSpace _    = False

lstrip :: String -> String
lstrip [] = ""
lstrip (x:xs)
  | (isSpace x) = lstrip xs
  | otherwise = x:xs

rstrip :: String -> String
rstrip s = reverse (lstrip (reverse s))

trim :: String -> String
trim = lstrip . rstrip</pre>
<p>Moral of this exercise: you can only pass a list to <code>++</code>. You can&#8217;t use <code>++</code> to append a Char to a String. You have to append <code>[c]</code> instead.<br />
<span id="more-1002069"></span></p>
<p>There&#8217;s probably an <code>isSpace</code> function in the standard library somewhere I could be using instead. (Found it. It&#8217;s <code>Char.isSpace</code>)</p>
<p>The <code>trim</code> function feels unnecessary. A more clever implementation of the fold might avoid it. </p>
<p>And that <code>reverse</code> is really yucky. I should be able to rewrite the fold so the values come out in the right order. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.elharo.com/blog/software-development/haskell/2009/01/26/words-with-fold/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hypothesis: cycles cannot be implemented only with folds</title>
		<link>http://www.elharo.com/blog/software-development/haskell/2009/01/24/hypothesis-cycles-cannot-be-implemented-only-with-folds/</link>
		<comments>http://www.elharo.com/blog/software-development/haskell/2009/01/24/hypothesis-cycles-cannot-be-implemented-only-with-folds/#comments</comments>
		<pubDate>Sat, 24 Jan 2009 15:31:07 +0000</pubDate>
		<dc:creator>Elliotte Rusty Harold</dc:creator>
				<category><![CDATA[Haskell]]></category>

		<guid isPermaLink="false">http://www.elharo.com/blog/?p=1002054</guid>
		<description><![CDATA[The cycle function turns a list into an infinite list by repeating it. For instance, cycle [1,2,3] is [1,2,3,1,2,3,1,2,3...]. I could be wrong but I don&#8217;t think you can do this one purely with folds and here&#8217;s why: The infinite list would have to be the accumulator. A fold (foldr or foldl) operation steps over [...]]]></description>
			<content:encoded><![CDATA[<p>The <code>cycle</code> function turns a list into an infinite list by repeating it. For instance, <code>cycle [1,2,3]</code> is <code>[1,2,3,1,2,3,1,2,3...]</code>. I could be wrong but I don&#8217;t think you can do this one purely with folds and here&#8217;s why:<br />
<span id="more-1002054"></span></p>
<ol>
<li>The infinite list would have to be the accumulator.</li>
<li>A fold (foldr or foldl) operation steps over (processes) each element of the finite input list exactly once.</li>
<li>Each step can insert only a finite number of elements into the accumulator list.</li>
<li>Thus the final accumulated list must be finite.</li>
</ol>
<p>Of course, Murphy&#8217;s Law guarantees that someone is now going to post a cycle implementation with pure folds in the comments. If there&#8217;s a mistake in this proof, it&#8217;s in step 3. But it really feels to me like a fold alone won&#8217;t do the trick. You have to use recursion of some sort here. Maybe a fold of folds? What if the step function is itself a fold? </p>
]]></content:encoded>
			<wfw:commentRss>http://www.elharo.com/blog/software-development/haskell/2009/01/24/hypothesis-cycles-cannot-be-implemented-only-with-folds/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>any with foldr</title>
		<link>http://www.elharo.com/blog/software-development/haskell/2009/01/23/any-with-foldr/</link>
		<comments>http://www.elharo.com/blog/software-development/haskell/2009/01/23/any-with-foldr/#comments</comments>
		<pubDate>Fri, 23 Jan 2009 05:48:02 +0000</pubDate>
		<dc:creator>Elliotte Rusty Harold</dc:creator>
				<category><![CDATA[Haskell]]></category>

		<guid isPermaLink="false">http://www.elharo.com/blog/?p=1002051</guid>
		<description><![CDATA[myAny :: (a -> Bool) -> [a] -> Bool myAny f [] = False myAny f (x:xs) = foldr step False xs where step x acc = acc &#124;&#124; f x I&#8217;m beginning to hate type inference. Yes the compiler can figure out the types, but the human (i.e. me) often can&#8217;t without running the [...]]]></description>
			<content:encoded><![CDATA[<pre>myAny :: (a -> Bool) -> [a] -> Bool
myAny f [] = False
myAny f (x:xs) = foldr step False xs
     where step x acc = acc || f x
</pre>
<p>I&#8217;m beginning to hate type inference. Yes the compiler can figure out the types, but the human (i.e. me) often can&#8217;t without running the compiler. Redundancy and verbosity are not bugs. They are features. Human language (e.g. English) is verbose and redundant for good reason. Redundancy helps humans understand. </p>
<p>The source code is not just for the compiler. Otherwise we&#8217;d write in machine language. User interface factors need to be considered in the design of programming languages. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.elharo.com/blog/software-development/haskell/2009/01/23/any-with-foldr/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>foldr Starts at the Head</title>
		<link>http://www.elharo.com/blog/software-development/haskell/2009/01/21/foldr-starts-at-the-head/</link>
		<comments>http://www.elharo.com/blog/software-development/haskell/2009/01/21/foldr-starts-at-the-head/#comments</comments>
		<pubDate>Thu, 22 Jan 2009 04:03:45 +0000</pubDate>
		<dc:creator>Elliotte Rusty Harold</dc:creator>
				<category><![CDATA[Haskell]]></category>

		<guid isPermaLink="false">http://www.elharo.com/blog/?p=1002049</guid>
		<description><![CDATA[It took me long enough to realize that foldr still moves from the beginning to the end of a list. Somehow I thought it started at the right (i.e. the tail) of the list. Once I realized that Exercise 7 was easy: Write your own definition of the standard takeWhile function, first using explicit recursion, [...]]]></description>
			<content:encoded><![CDATA[<p>It took me long enough to realize that foldr still moves from the beginning to the end of a list. Somehow I thought it started at the right (i.e. the tail) of the list. Once I realized that Exercise 7 was easy:</p>
<blockquote><p>Write your own definition of the standard <code>takeWhile</code> function, first using explicit recursion, and then foldr.</p></blockquote>
<p><span id="more-1002049"></span></p>
<pre>myTakeWhile :: (a -> Bool) -> [a] -> [a]
myTakeWhile _ [] = []
myTakeWhile f (x:xs) = if (f x)
                       then x : (myTakeWhile f xs)
                       else []

fMyTakeWhile :: (a -> Bool) -> [a] -> [a]
fMyTakeWhile f (xs) = foldr step [] xs
     where step x ys | f x = x : ys
                     | otherwise = [] </pre>
]]></content:encoded>
			<wfw:commentRss>http://www.elharo.com/blog/software-development/haskell/2009/01/21/foldr-starts-at-the-head/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>asInt_either</title>
		<link>http://www.elharo.com/blog/software-development/haskell/2009/01/20/asint_either/</link>
		<comments>http://www.elharo.com/blog/software-development/haskell/2009/01/20/asint_either/#comments</comments>
		<pubDate>Wed, 21 Jan 2009 04:13:54 +0000</pubDate>
		<dc:creator>Elliotte Rusty Harold</dc:creator>
				<category><![CDATA[Haskell]]></category>

		<guid isPermaLink="false">http://www.elharo.com/blog/?p=1002043</guid>
		<description><![CDATA[Real World Haskell, Exercise 4, p. 98: The asInt_fold function uses error, so its callers cannot handle errors. Rewrite it to fix this problem. -- file: ch04/IntParse.hs import Data.Char (digitToInt) asInt :: String -> Int asInt ('-':xs) = -1 * asInt xs asInt xs = foldl step 0 xs where step acc x = acc [...]]]></description>
			<content:encoded><![CDATA[<p><cite><a href="http://book.realworldhaskell.org/read/functional-programming.html">Real World Haskell</a></cite>, Exercise 4, p. 98:</p>
<p>The <code>asInt_fold</code> function uses <code>error</code>, so its callers cannot handle errors. Rewrite it to fix this problem.<br />
<span id="more-1002043"></span></p>
<pre>-- file: ch04/IntParse.hs
import Data.Char (digitToInt) 

asInt :: String -> Int
asInt ('-':xs) = -1 * asInt xs
asInt xs = foldl step 0 xs
  where step acc x = acc * 10 + safeDigitToInt x

safeDigitToInt :: Char -> Int
safeDigitToInt x =  if x >= '0' &#038;&#038; x &lt;= '9'
                      then digitToInt x
                      else error "Non-digit"

asInt_either :: String -> Ei
asInt_either xs = if onlyHasDigits xs
                  then Main.Right (asInt xs)
                  else Main.Left ("non-digit '" ++ ((firstNonDigit xs) : "'"))

onlyHasDigits :: String -> Bool
onlyHasDigits [] = True
onlyHasDigits (x:xs) = if x >= '0' &#038;&#038; x &lt;= '9'
                      then onlyHasDigits xs
                      else False

firstNonDigit :: String -> Char
firstNonDigit [] = '\0'
firstNonDigit (x:xs) = if x &lt;= '0' || x >= '9'
                      then x
                      else firstNonDigit xs

data Ei = Right Int
          | Left String
        deriving (Show)</pre>
<p>Doubtless this could be much mproved by someone who knows what they&#8217;re doing. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.elharo.com/blog/software-development/haskell/2009/01/20/asint_either/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>transpose</title>
		<link>http://www.elharo.com/blog/software-development/haskell/2009/01/18/transpose/</link>
		<comments>http://www.elharo.com/blog/software-development/haskell/2009/01/18/transpose/#comments</comments>
		<pubDate>Sun, 18 Jan 2009 17:10:40 +0000</pubDate>
		<dc:creator>Elliotte Rusty Harold</dc:creator>
				<category><![CDATA[Haskell]]></category>

		<guid isPermaLink="false">http://www.elharo.com/blog/?p=1002011</guid>
		<description><![CDATA[Real World Haskell, Exercise 4, p. 84: Write a program that transposes the text in a file. For instance, it should convert &#8220;hello\nworld\n&#8221; to &#8220;hw\neo\nlr\nll\nod\n&#8221;. cc :: String -> String -> String cc x y = x ++ y ++ "\n" transposeSingle :: String -> String transposeSingle [] = [] transposeSingle (x:xs) = x : [...]]]></description>
			<content:encoded><![CDATA[<p><cite><a href="http://book.realworldhaskell.org/read/functional-programming.html">Real World Haskell</a></cite>, Exercise 4, p. 84:</p>
<p>Write a program that transposes the text in a file. For instance, it should convert &#8220;hello\nworld\n&#8221; to &#8220;hw\neo\nlr\nll\nod\n&#8221;.<br />
<span id="more-1002011"></span></p>
<pre><code>cc :: String -> String -> String
cc x y = x ++ y ++ "\n"

transposeSingle :: String -> String
transposeSingle [] = []
transposeSingle (x:xs) = x : '\n' : (transposeSingle xs)

-- the accumulator string and the next line
transposeDouble :: String -> String -> String
transposeDouble x y = concat (zipWith (cc) (lines x) (lines (transposeSingle y)))

transposeEven :: [String] -> String
transposeEven [] = []
transposeEven [x] = (transposeSingle x)
transposeEven (x:xs) = foldl (transposeDouble) (transposeSingle x) xs

transpose :: String -> String
transpose s = transposeEven (pad (maxLength s) (lines s))

-- pad each line with spaces to maximum length
maxLength :: String -> Int
maxLength s = maximum (map length (lines s))

pad :: Int -> [String] -> [String]
pad _ [] = []
pad n (x:xs) = (padOneLine (n - (length x)) x) : (pad n xs)

padOneLine :: Int -> String -> String
padOneLine n s = if n > 0
                 then padOneLine (n-1) (s ++ ".")
                 else s</code></pre>
<p>The exercise wasn&#8217;t clear on what you should do when not all lines were the same size, so I padded them out with periods.</p>
<p>This took way longer to implement than it should have, and I had to use several functions from later parts of the book. I certainly could have implemented this faster in Java or, to pick a language I haven&#8217;t been using day in and day out for 14 years, Python. Doubtless an experienced Haskell programmer could come up with a simpler implementation.</p>
<p>On the positive side, the interactive ghci shell was a big help in debugging this, and by their very nature Haskell&#8217;s pure functions are very amenable to testing and debugging in isolation. However, I still have to learn how to do real test driven development in Haskell. (One thing I proved to myself a couple of jobs ago  was that TDD matters a lot more than what language you code in. I figured this out after I realized I could write correct Python code faster than the professional Python programmers we had hired because I was using TDD and they weren&#8217;t. This despite the fact that I  knew next to no Python and they had years of experience in the language. Of course, an experienced Python programmer who did use test-driven development could still wipe the floor with me. )</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elharo.com/blog/software-development/haskell/2009/01/18/transpose/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Haskell: Concatenation vs. Prepending</title>
		<link>http://www.elharo.com/blog/software-development/haskell/2009/01/14/haskell-concatenation-vs-prepending/</link>
		<comments>http://www.elharo.com/blog/software-development/haskell/2009/01/14/haskell-concatenation-vs-prepending/#comments</comments>
		<pubDate>Wed, 14 Jan 2009 14:37:35 +0000</pubDate>
		<dc:creator>Elliotte Rusty Harold</dc:creator>
				<category><![CDATA[Haskell]]></category>

		<guid isPermaLink="false">http://www.elharo.com/blog/?p=1001986</guid>
		<description><![CDATA[This confused me a little until I grokked it. In Haskell, an item is not the same as a list containing the one item. (Obvious, I know, but some languages like XQuery take the opposite view). The : operator prepends an item to the beginning of a list. It can only be used to insert [...]]]></description>
			<content:encoded><![CDATA[<p>This confused me a little until I grokked it. In Haskell, an item is not the same as a list containing the one item. (Obvious, I know, but some languages like XQuery take the opposite view). </p>
<p>The <code>:</code> operator prepends an item to the beginning of a list. It can only be used to insert an item at the beginning of a list. It cannot be used to append an item to the end of a list.  Thus <code>x:xs</code> is correct but <code>xs:x</code> is a syntax error. (Haskell&#8217;s design seems stuck with assumptions going all the way back to Lisp and 1950s era processors including that the singly linked list is a good implementation for the list abstract data type. This has other consequences. For instance, <code>length</code> is an O(n) operation. And now that I look for it, insert into the middle of the list also seems to be missing.)</p>
<p>Lists are concatenated with the <code>++</code> operator, not <code>:</code>. </p>
<p>So, to sum up:</p>
<ul>
<li>Use <code>:</code> to insert an item at the beginning of a list.</li>
<li>Use <code>++</code> to join two lists together.</li>
<li>To append an item to a list, insert the item into an empty list, and then concatenate the two lists together.</li>
<li>More generally, to insert an item into a list at any position other than the first:
<ol>
<li>Split the list into two sublists at the insertion point with <code>splitAt</code>.</li>
<li>Use <code>:</code> to prepend the new item to the second list.</li>
<li>Concatenate the two lists back together with <code>++</code></li>
</ol>
</li>
</ul>
<p>Am I missing something obvious here?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elharo.com/blog/software-development/haskell/2009/01/14/haskell-concatenation-vs-prepending/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>How Long Does It Take to Compile Haskell?</title>
		<link>http://www.elharo.com/blog/software-development/haskell/2008/12/22/how-long-does-it-take-to-compile-haskell/</link>
		<comments>http://www.elharo.com/blog/software-development/haskell/2008/12/22/how-long-does-it-take-to-compile-haskell/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 15:10:31 +0000</pubDate>
		<dc:creator>Elliotte Rusty Harold</dc:creator>
				<category><![CDATA[Haskell]]></category>

		<guid isPermaLink="false">http://www.elharo.com/blog/?p=1001782</guid>
		<description><![CDATA[I&#8217;ve been compiling ghc from MacPorts on this 2.0 GHz MacBook, and I&#8217;m beginning to wonder if it&#8217;s hung. I&#8217;ve been stuck on &#8220;Building ghc&#8221; for quite a while, maybe an hour: ---> Cleaning perl5.8 ---> Fetching ghc ---> Attempting to fetch ghc-6.10.1-src.tar.bz2 from http://haskell.org/ghc/dist/stable/dist/ ---> Attempting to fetch ghc-6.10.1-src-extralibs.tar.bz2 from http://haskell.org/ghc/dist/stable/dist/ ---> Attempting to [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been compiling ghc from MacPorts on this 2.0 GHz MacBook, and I&#8217;m beginning to wonder if it&#8217;s hung. I&#8217;ve been stuck on &#8220;Building ghc&#8221; for quite a while, maybe an hour:</p>
<pre>--->  Cleaning perl5.8
--->  Fetching ghc
--->  Attempting to fetch ghc-6.10.1-src.tar.bz2 from http://haskell.org/ghc/dist/stable/dist/
--->  Attempting to fetch ghc-6.10.1-src-extralibs.tar.bz2 from http://haskell.org/ghc/dist/stable/dist/
--->  Attempting to fetch ghc-6.8.2-darwin-i386-leopard-bootstrap.tar.bz2 from http://haskell.org/ghc/dist/6.8.2/
--->  Verifying checksum(s) for ghc
--->  Extracting ghc
--->  Applying patches to ghc
--->  Configuring ghc
--->  Building ghc
</pre>
<p>Certainly it was long enough to answer a bunch of e-mails, and edit an article. Is this the point where it actually compiles the compiler? Is ghc self-hosting? That is, is ghc written in ghc? That may be what the bootstrap bit is about. Yep, <a href='http://www.haskell.org/ghc/'>looks like it is</a>.</p>
<p>I do remember 2 hour gcc compiles, but that was 15 years ago on much slower hardware. How long does it take to compile a compiler nowadays?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elharo.com/blog/software-development/haskell/2008/12/22/how-long-does-it-take-to-compile-haskell/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

