I got 99 problems…
Ooooh boy. This is gonna be huge.
It’s 2 am in the morning and I’ve just decided to try solving the 99 Haskell Problems. I’ve tried to grok Haskell on and off for at least three times now and I still haven’t gotten as far as monads. That’s a great thing, because I’m getting fed up at not being able to code every day and Haskell is as good as it’s gonna get.
So let’s get started.
Problem 01 (2016-04-28 02:07-02:40)
The first problem is to return the tail of a list. Armed with:
ghc main.hs ./main
…I get to work. Now I haven’t seen Haskell in n years so it’s gonna take me a while to do this. Let’s see:
main = do print (last [1, 2, 3, 4]) -- 4 print (last ['x','y','z']) -- 'z'
That gave me a headache. Moving on…
Problem 02 (2016-04-28 02:40-02:47)
I just found out about this:
…and will be using it for the remainder of this post.
Anyway, the current task is to get the penultimate element from a list. Let’s see:
main = do print $ last $ init [1..4] -- 3 print $ last $ init ['a'..'z'] -- 'y'
…and we’re done.
Problem 03 (2016-04-28 02:47-02:56)
The current problem is indexing a list (starting from 1). Let’s see:
main = do print $ [1, 2, 3] !! (2-1) -- 2 print $ "haskell" !! (5-1) -- 'e'
This is borderline cheating but, hey, whatever works right?
Problem 04 (2016-04-28 02:56-03:09)
Okay, let’s try and shake things up. From now on, I am restricting my use of Prelude to the following functions: map, filter, foldl’ (the non-lazy version of foldl), and foldr. Hopefully this teaches me integrity and character. The current problem is to find the length of a list. This should be easy:
main = do print $ (foldr (\x acc -> acc + 1) 0 [123, 456, 789]) -- 3 print $ (foldr (\x acc -> acc + 1) 0 "Hello, world!") -- 13
My time is wasted editing things.
Problem 05 (2016-04-28 03:12-03:15)
The current problem is to reverse a list:
_reverse  =  _reverse (x:xs) = (_reverse xs) ++ [x] main = do print $ _reverse "A man, a plan, a canal, panama!" -- "!amanap ,lanac a ,nalp a ,nam A" print $ _reverse [1,2,3,4] -- [4,3,2,1]
That was longer than expected. I wonder if this can be done using anonymous functions. Hmm…
EDIT (2016-04-28 03:18):
main = do print $ foldr (\x acc -> acc ++ [x])  "A man, a plan, a canal, panama!" print $ foldr (\x acc -> acc ++ [x])  [1,2,3,4]
Uses anonymous functions but a bit shorter than the original one.
I’m going to take a nap and resume this later.
Problem 06 (2016-04-29 08:27-08:31)
Slept in yesterday. Still feel like crap. Anyway, the current problem wants me to decide whether or not a given string is a palindrome:
main = do print $ [1,2,3] == (foldr (\x acc -> acc ++ [x])  [1,2,3]) -- False print $ "madamimadam" == (foldr (\x acc -> acc ++ [x])  "madamimadam") -- True print $ [1,2,4,8,16,8,4,2,1] == (foldr (\x acc -> acc ++ [x])  [1,2,4,8,16,8,4,2,1]) -- True
These lines are getting longer.
A quick aside
Haskell on Arch Linux is hell on Earth. There exists something called “cabal dependency hell” which I will neglect to explain because I don’t really understand how one of the most sophisticated group of hackers on Earth has not yet engineered a package manager that Simply Works. Lone wolf syndrome? Not qualified enough to comment on it. Nevertheless, there’s a way out of the pit and it starts when you
cd into your project directory and do:
# Generates .cabal file used by cabal build cabal init # Initialises sandbox, installs necessary # packages, and builds your project cabal sandbox init cabal install --only-dependencies cabal build
And when you want to install a particular package in the sandbox, just do:
cabal install --require-sandbox <package-name>
- a word/string/list that’s the same forwards and backwards; e.g., “timtom motmit”