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==188.8.131.52.
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’
Enter and wait for the next prompt
- type ‘SublimeHaskell’ and press
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)]
Pattern syntax in expression context: f x -> f x
Prelude> zipWith ((f x) -> f x) [1, 2, 3] cycle $ [id (*2)]
Pattern syntax in expression context: (f x) -> f x
Prelude> zipWith ($) [1, 2, 3] cycle $ [id (*2)]
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)])
No instance for (Num ((a0 -> a0) -> c0))
arising from the literal `3'
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]
Prelude> zipWith ($) (cycle $ [id, (*2)]) [1,2,3]
Prelude> zipWith ($) (cycle $ [id, (*2)]) [1,2,3,4,5]
Prelude> zipWith ($) (cycle $ [id, (*2)]) [1,1,1,1,1]
Prelude> let doubleAlternate = zipWith ($) (cycle $ [id, (*2)])
Prelude> doubleAlternate [2,2,2,2,2,2,2,2,2,2]
Prelude> doubleAlternate [1,2,3,4]
Prelude> let doubleAlternateFromEnd = reverse . doubleAlternate . reverse
Prelude> doubleAlternateFromEnd [1,2,3,4]
Two things are apparent from this:
- I need to get more sleep.
- I would benefit from some review of things like:
- operator precedence
- what exactly
- 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]
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.