summaryrefslogtreecommitdiff
path: root/sites/pmikkelsen.com/haskell
diff options
context:
space:
mode:
authorglenda <glenda@9front.local>2020-11-15 15:13:27 +0000
committerglenda <glenda@9front.local>2020-11-15 15:13:27 +0000
commit39318169e0b50551db511851829f9337c5fa6313 (patch)
tree65a0ef5c1da9677532fa8105293d017919473057 /sites/pmikkelsen.com/haskell
Import site to git
Diffstat (limited to 'sites/pmikkelsen.com/haskell')
-rw-r--r--sites/pmikkelsen.com/haskell/quine.md94
1 files changed, 94 insertions, 0 deletions
diff --git a/sites/pmikkelsen.com/haskell/quine.md b/sites/pmikkelsen.com/haskell/quine.md
new file mode 100644
index 0000000..09a3dcd
--- /dev/null
+++ b/sites/pmikkelsen.com/haskell/quine.md
@@ -0,0 +1,94 @@
+Today I am going to go through the process of writing a small program
+which prints it's own source when executed. These kinds of programs are
+also called quines, and I suggest that you try it out on your own if you
+haven't already done so, as it is a very fun little problem! So if you
+don't want any spoilers, please leave this page now and come back later.
+
+
+## First attempt
+
+Okay, so first of let's just write a small hello world program to get
+things going. All our code will be in a file called `quine.hs`. The code
+for hello world looks like this
+
+
+ main = putStrLn "Hello world!"
+
+
+When this is run using runhaskell quine.hs, it produces the output
+
+
+ Hello world!
+
+
+Well, not quite a quine yet but we are getting something to the screen
+at least ;)
+
+## Second attempt
+
+Now we get the idea that we copy the entire program's source into a
+string and print that string instead. To do this, the code could look
+something like this
+
+
+ main = putStrLn code
+ where code = "main = putStrLn code\n where code = ???"
+
+
+Here we run into a problem, since we can't include the entire code into
+the string. Copying everything we can into the string just increases
+the size of the string itself, which means that there is now even more
+to copy! We start by only copying all the code upto the string and see
+how it looks when executed. The code is now
+
+
+ main = putStrLn code
+ where code = "main = putStrLn code\n where code = "
+
+
+And it outputs
+
+ main = putStrLn code
+ where code =
+
+Quite good! Now if we could only include the string itself in its printed form, with the quotes and all, and not the interpreted form with `\n` shown as newlines.
+
+## Third attempt
+
+After looking through the haskell standard libraries for a bit, we find
+a function that looks promising for what we want to do. This function is
+`print`, which prints the output using the `show` function instead of
+interpreting the string. We would want to both print it as before, and
+to print it using `print`, so we change our main to be `main = putStrLn
+code >> print code`, and update our string to include the print. The
+code then becomes
+
+ main = putStrLn code >> print code
+ where code = "main = putStrLn code >> print code\n where code = "
+
+And it outputs
+
+
+ main = putStrLn code >> print code
+ where code =
+ "main = putStrLn code >> print code\n where code = "
+
+
+So close! The only problem is that the `putStrLn` append a newline after
+the output, which we don't want in this case.
+
+## Final attempt
+
+The simple fix is just to use `putStrLn`'s little brother `putStr`
+which doesn't print that newline. The final program is then
+
+
+ main = putStr code >> print code
+ where code = "main = putStr code >> print code\n where code = "
+
+And luckily it outputs exactly itself
+
+
+ main = putStr code >> print code
+ where code = "main = putStr code >> print code\n where code = "
+