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==18.104.22.168.
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’
Enterand 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
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:
- 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] 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.