diff options
author | glenda <glenda@9front.local> | 2020-11-15 15:13:27 +0000 |
---|---|---|
committer | glenda <glenda@9front.local> | 2020-11-15 15:13:27 +0000 |
commit | 39318169e0b50551db511851829f9337c5fa6313 (patch) | |
tree | 65a0ef5c1da9677532fa8105293d017919473057 /sites/pmikkelsen.com/haskell |
Import site to git
Diffstat (limited to 'sites/pmikkelsen.com/haskell')
-rw-r--r-- | sites/pmikkelsen.com/haskell/quine.md | 94 |
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 = " + |