Archives

All posts for the month July, 2014

I decided to get my editor set up this evening, before I make a start on the homework exercises.

I tend to use Sublime Text 3, so I am adding Sublime Haskell to get it sorted.

The first instruction is to get some dependencies by running cabal install aeson haskell-src-exts haddock so I go ahead and do that. Most of it seems to work, but it fails when compiling haddock. I could have saved myself a bit of time by reading the instructions more thoroughly, but I was playing games at the same time. The problem was that the haddock version was too new for the version of ghc that I have, and I had to constrain it to an earlier version, like so: cabal install haddock --constraint=haddock==2.13.2.1.

I decided to go ahead and add some of the “optional, but useful” requirements as well:

cabal install ghc-mod
cabal install stylish-haskell
cabal install haskell-docs
cabal install hdevtools

They all seem to work without any problems.

I frequently forget how to bring up package control in Sublime Text. To do it:

  • Ctrl + Shift + P
  • type ‘Install’ to filter for ‘Package Control: Install Package’
  • press Enter and wait for the next prompt
  • type ‘SublimeHaskell’ and press Enter

That’s it, it seems to be ready to go. Entering Ctrl+Shift+P, haskell gives me a nice set of options.

I started on the first homework. The first exercise was simple enough, and I incidentally learned something about monadic map:

I wanted to have my program print a few different test values, so I made an array of print . This didn’t work so well – main is expected to be of type IO (), and I had ended up with [IO ()]. The solution was to use mapM_ with the list of display values.

  • mapM is a monadic map
  • mapM_ is similar but that does not collect its output

The second exercise was too much for my late-evening brain, so I turned in for the night.

At work the next day I played around on GHCi with ideas my brain had come up with overnight, and got it sorted:

Prelude> :type zip
zip :: [a] -> [b] -> [(a, b)]
Prelude> :type zipWith
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
Prelude> zipWith apply [1, 2, 3] cycle $ [id (*2)]

<interactive>:1:9: Not in scope: `apply'
Prelude> zipWith (f x -> f x) [1, 2, 3] cycle $ [id (*2)]

<interactive>:1:10:
    Pattern syntax in expression context: f x -> f x
Prelude> zipWith ((f x) -> f x) [1, 2, 3] cycle $ [id (*2)]

<interactive>:1:10:
    Pattern syntax in expression context: (f x) -> f x
Prelude> zipWith ($) [1, 2, 3] cycle $ [id (*2)]

<interactive>:1:23:
    Couldn't match expected type `[b0]' with actual type `[a0] -> [a0]'
    In the third argument of `zipWith', namely `cycle'
    In the expression: zipWith ($) [1, 2, 3] cycle
    In the expression: zipWith ($) [1, 2, 3] cycle $ [id (* 2)]
Prelude> zipWith ($) [1, 2, 3] (cycle $ [id (*2)])

<interactive>:1:20:
    No instance for (Num ((a0 -> a0) -> c0))
      arising from the literal `3'
    Possible fix:
      add an instance declaration for (Num ((a0 -> a0) -> c0))
    In the expression: 3
    In the second argument of `zipWith', namely `[1, 2, 3]'
    In the expression: zipWith ($) [1, 2, 3] (cycle $ [id (* 2)])
Prelude> zipWith ($) (cycle $ [id (*2)]) [1,2,3]
[2,4,6]
Prelude> zipWith ($) (cycle $ [id, (*2)]) [1,2,3]
[1,4,3]
Prelude> zipWith ($) (cycle $ [id, (*2)]) [1,2,3,4,5]
[1,4,3,8,5]
Prelude> zipWith ($) (cycle $ [id, (*2)]) [1,1,1,1,1]
[1,2,1,2,1]
Prelude> let doubleAlternate = zipWith ($) (cycle $ [id, (*2)])
Prelude> doubleAlternate [2,2,2,2,2,2,2,2,2,2]
[2,4,2,4,2,4,2,4,2,4]
Prelude> doubleAlternate [1,2,3,4]
[1,4,3,8]
Prelude> let doubleAlternateFromEnd = reverse . doubleAlternate . reverse
Prelude> doubleAlternateFromEnd [1,2,3,4]
[2,2,6,4]
Prelude>

Two things are apparent from this:

  1. I need to get more sleep.
  2. I would benefit from some review of things like:
    • operator precedence
    • what exactly $ means
    • paying attention to the order of parameters

I was bored for a moment and had a quick play with the next exercise:

Prelude> :type fold
foldl   foldl1  foldr   foldr1
Prelude> :type foldl
foldl :: (a -> b -> a) -> a -> [b] -> a
Prelude> :type foldl1
foldl1 :: (a -> a -> a) -> [a] -> a
Prelude> let sumDigits = foldl1 (+)
Prelude> sumDigits [5,15,2,8]
30
Prelude>

Putting it all together once I got home was a simple matter of stringing a set of functions together:

validate = (== 0) . (`mod` 10) . sumDigits . doubleEveryOther . toDigits

I would prefer all the functions to be strung together the other way, at least with how I think about things at the moment. I would need (a -> b) -> (b -> c) -> a -> c, but Hoogle just matches (.) and some things with Strategy b, which don’t help me. I could define something like (.>) = flip (.), but for all I know I’m stomping on an existing symbol.

Further investigation turned up >>>, which looks promising. I can import it with import Control.Category ((>>>)). The selective import is necessary, since Control.Category appears to have a function (.), which clashes with the (.) from prelude (which looks to be an alias of <<<). I presume from the package name that these operators are getting right into some category theory, so I might do some reading into that later on.

I am pretty sure that Open Sans by Steve Matteson is my favourite font for reading on a screen. Lately, I have found myself opening the browser’s developer tools and messing with the font-face when I want to read anything non-trivial that uses a font I dislike, but turning on Open Sans is less trivial since it is often not available as a browser default.

I could just settle for a default sans serif font, but that makes my eyes sad. I want my eyes to be tiny smiles when I read, so I wrote some code to fix it:

First I made a script that I can paste into the console:

var lnk = document.createElement('link')
lnk.setAttribute('href', '//fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800')
lnk.setAttribute('rel', 'stylesheet')
lnk.setAttribute('type', 'text/css')
document.head.appendChild(lnk)
document.body.style.fontFamily = 'Open Sans'

Finding the script and manually pasting it is not ideal though, so I turned it into a bookmarklet:

javascript:(function(){var lnk = document.createElement('link');lnk.setAttribute('href', '//fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800');lnk.setAttribute('rel', 'stylesheet');lnk.setAttribute('type', 'text/css');document.head.appendChild(lnk);document.body.style.fontFamily = 'Open Sans'})()

That is much better, except I don’t tend to keep my bookmarks visible on normal pages (just on my new tab page). I looked around and found this little tool: Convert bookmarklet to Chrome extension by Peter Legierski which let me get an icon next to my omni bar. That did the trick. Peter writes about the conversion tool in his blog How to Convert Bookmarklet to Chrome Extension.

Now I can switch to Open Sans with a single click. Thanks Peter 🙂

It is Sunday evening – yesterday was a LAN and I was up gaming until the wee hours. Now I am back home. I have had enough of games for now; I am sleepy, but it is too early for bed; I feel like doing something. Why not Haskell?

I will begin the journey of learning described in learnhaskell, a guide by Chris Allen.

Installation

This was pretty straightforward. The steps I followed are here for posterity:

  • downloaded and installed Haskell Platform for Windows

    • there was one little WTF in the process – after the installation was done, the wizard informed me that I did not have something called “GLUT”, and asked if I wanted to install it. No indication of what GLUT is. A little investigation indicated that it is probably something related to OpenGL. I decided to install it; I doubt I will use it any time soon, but I was feeling adventurous.
  • opened cmd and ran ghci, and played around to make sure it worked:

    C:\Users\Monkey>ghci
    GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
    Loading package ghc-prim ... linking ... done.
    Loading package integer-gmp ... linking ... done.
    Loading package base ... linking ... done.
    Prelude> 1 + 1
    2
    Prelude> let x = 5 in x * x
    25
    Prelude> let f x = case x of 1 -> "hello"; _ -> "goodbye" in f 1
    "hello"
    Prelude> let f x = case x of 1 -> "hello"; _ -> "goodbye" in f 45
    "goodbye"
    Prelude>
    Leaving GHCi.
    
  • looked at learnhaskell and it said I should have cabal, so I ended up running cabal update then cabal install cabal cabal-install, which seems a bit odd but it said to do that in Getting The Haskell Cabal. It seemed to work as the output included Installed Cabal-1.20.0.1 and Installed cabal-install-1.20.0.3.

First Steps

learnhaskell is telling me to do the “Yorgey course” first. I am informed that this will, in addition to equipping me to write Haskell, help me to understand parser combinators. I am glad about this, because the Wikipedia page for Parser combinator does not seem to be helping much with understanding. Perhaps I just lack education about combinators in general, and about context-free grammars.

Much of the first lecture is familiar from previous study. Key points:

  • Integer is an integral type that is only limited by computer memory, whereas Int is just a system integer that can only be guaranteed to deal with values up to +/- 2^29 (may be bigger depending on machine).
  • backticks make prefix operators infix, parens make infix operators prefix:

    1 + 2 == (+) 1 2
    mod 2 1 == 2 `mod` 1
    (%) = mod
    2 `mod` 1 == 2 % 1
    
  • pattern matching is handy for functions. Expressions are checked in the order they are written:

    factorial :: Integer -> Integer
    factorial 0 = 1
    factorial 1 = 1
    factorial n = n + factorial (n - 1)
    
  • guards use pipe character:

    <functionName> <pattern>
      | <predicate expression> = <value>
      | <predicate expression> = <value>
      | <predicate expression> = <value>
    

    e.g.

    foo n
      | n < 0 = 0
      | n < 10 = n + 10
      | otherwise = n
    
  • function application has higher precedence than any infix operator, so f 3 n+1 7 parses as (f 3 n) + (1 7)

  • make lists with [1, 2, 3], or cons operator: 1 : 2 : 3 : []. They are singly linked lists (cons lists), with type [Integer].

  • String is just sugar for [Char], so ['h', 'i'] == "hi"

Other than a reassurance about error messages, that is it for the lecture. Next is the first homework. It looks exciting, with credit card number validation and towers of Hanoi, among other less illustrated problems, but will have to wait until after I have had some sleep.

The course also recommends Chapter 2 of Learn You A Haskell and two Real World Haskell chapters: Chapter 1 and Chapter 2, so I will have a read of those.

I have been confused more learning Haskell than learning any other language so far. I am convinced that the reason for this is that Haskell requires thought a lot earlier in the process than any other language I have learned, and it doesn’t let you keep your hands busy while you figure things out by typing a whole lot of worthless syntax.

Not only does Haskell require more thinking upfront; it also takes away a lot of the trivial little bits and pieces that let you continue to keep your hands busy and feel like you’re really doing quite a lot of stuff, like telling the computer how to iterate over a list or add some things up. With thought at a higher level, it forces me to just think about what the program is supposed to do, and just tell the computer to do that.

How am I supposed to feel like a l33t h4ck3r if I’m not typing furiously for hours on end?

Really I was just writing a post about Haskell to make a note about a few things to check out or remember:

  • yesod for writing web applications in Haskell.
  • cabal describes, and provides support for, Haskell packages.
  • Hackage is the central package archive for Haskell.
  • learnhaskell is guide on github to learning Haskell, with links to several courses in a recommended order.
  • Learn You a Haskell for Great Good! is, as the name suggests, a book for learning Haskell. It has amusing pictures, and that would be enough, but it is also well written (as best I can tell – I am not an editor or critic).

Fraser at work said that yesod is fairly heavyweight and requires a lot of up-front learning before being able to do much. This probably makes it a poor candidate while learning, particularly since it is just in my spare time. He mentioned two more lightweight frameworks:

@mwotton uses Scotty, and also mentioned MFlow, describing it as a “continuation-based thing, so you can write multi-transaction web code in a single function”. It sounds like something to check out once I’ve covered some basics.

Chris Allen linked Magma (algebra), “so you know what you’re doing in Haskell,” so I’d better check that out too.

There is a mailing list for people learning Haskell: Haskell-Beginners.

In a podcast recently, probably NodeUP, there was some discussion about how much more readable console output can be when it has a bit of colour. I heartily agree – distinctive colours allow my visual firmware to very reliably distinguishing different blocks of text; more reliably than layout alone.

By “visual firmware” I am talking about the parts of the brain involved in the pre-attentive process of visual scene segmentation.

I care about effective pre-attentive processing because it means my cerebral cortex gets a far better indexed set of visual data, so I can avoid some of the conscious cognitive load of manually distinguishing the different things I am looking at. Facilitating effective pre-attentive processing is a bit like adding a GPU to a computer: graphics processing can happen separately from the CPU, leaving more clock cycles for general processing.

So, when I was reminded today that some functionality is being added to our command line client, I immediately set out to figure out how to get nice command-line colours across all the platforms the client can run on. ANSI escape codes do not work on a standard Windows console, so I was pretty sure something more would be needed. This looks like the solution: Jansi, a library that allows Java console output to use ANSI escape codes in Windows as well.