Day two spock’s great strength with Haskell

Roy Honders
yes-coding
Published in
6 min readNov 1, 2017

Today I will continue with the second chapter of the seven languages in seven weeks book about haskell.
If you want to read about part one in this blog series, you should look over here.

Anonymous functions

In haskell anonymous functions exist. These are function without a name. They are started off with the following characters “(“ and closed with the character “)”.

(\x -> x ++ " captain.") "Logical," 
"Logical, captain."

Using anonymous functions has the most effect when using it in combination with other functions:

map (\x -> x * x) [1, 2, 3] 
[1,4,9]

I think this way of defining functions without giving them a name is interesting, because it’s a simple way to define them and they are easy for me to read and interpret. In Java something similar exists called a lambda expression. This is not exactly the same, so it’s hard to compare the two of them. I think anonymous functions could be a good solution in some usecases when trying something new really quick. But I don’t think it’s a good way to write clean code.

filter, foldl, foldr

In haskell there is a common, predefined function called “filter”. This function will filter a list based on another function. For example you can use the “odd” function to return a new list with only the odd numbers:

filter odd [1, 2, 3, 4, 5] 
[1,3,5]

I think this is a great, clean way to filter lists without having to hassle with method declarations and return types. It also reads well, it does what you expect.

Next to the filter function there is also a fold function. There is a fold left function and a fold right function. These functions can be used to fold over a list using an operator. For example:

This will give the same result as:

I think this is an interesting way to combine functions to achieve results with using only one line of code. In Java you would have to use loops to get a similar result. (Without writing your own functions)

Partially Applied Functions and Currying

In this section we will find out that Haskell uses functions that take one parameter. How could that work for a function where you supply two parameters? Take this function as an example:

let prod x y = x * y :t prod 
prod :: Num a => a -> a -> a

This function is defined as a function that takes a number parameter, where every given parameter is split up with his own function with just one parameter. This is called partial application. Using partial application we can define a new function where only the “x” parameter is defined in the above function and the “y” parameter will be given through the new function:

let triple = prod 3 triple 4 12

This process is called currying. I think using partial application and currying is an interesting way to let functions ‘automatically’ work together with eachother. However this application really requires a new way of thinking about programming.

Lazy Evaluation

Haskell makes extensive use of lazy evaluation. With lazy evaluation you can build functions that return infinite lists. As an example we can use a function that builds an infinite range:

myRange start step = start:(myRange (start + step) step)*Main> take 10 (myRange 10 1) 
[10,11,12,13,14,15,16,17,18,19]
*Main> take 5 (myRange 0 5)
[0,5,10,15,20]

This function calls itself recursively and infinitely. This means we need a way to stop the function from executing. We do this by adding a take 5 option where we stop at the 4th recursive call. This will make sure we don’t get lost in the infinite loop. ;) In Java this isn’t really possible, because a take function would not be processed until the endless loop has finished executing, which is never. So I think it’s cool that in Haskell it’s possible to take a part of a list like this. Haskell is able to do this because Haskell only computes the part necessary to do the job.

Day two self study

Find functions that you can use on lists, strings, or tuples
List functions: https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-List.html
String functions: https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-String.html
Tuple functions: https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Tuple.html

Find a way to sort lists
I found a function to sort a list: https://www.haskell.org/hoogle/?hoogle=Data.List.sort
I created a new file called “sort_list.hs” where I imported a Haskell module called Data.List:

import Data.List sortList a = sort a

Now I can sort a list like this:

*Main> sortList [1, 5, 2] 
[1,2,5]

Write a sort that takes a list and returns a sorted list
In all of my enthusiasm, I already wrote that function during answering the question above.

Write a sort that takes a list and a function that compares its two arguments and then returns a sorted list. After hassling with the typings for this function I came up with a solution:

import Data.List sortList :: (Ord a) => [a] -> (a -> a -> Ordering) -> [a] 
sortList [] _ = []
sortList list function = sortBy function list
*Main> sortList [1, 5, 3] (\a b -> if (a < b) then LT else GT) [1,3,5]

Write a Haskell function to convert a string to a number. The string should be in the form of $2,345,678.99 and can possibly have leading zeros.

stringToNumber :: String -> Float 
stringToNumber value = read
strippedValue :: Float
where strippedValue = foldl (\ newString c -> if (c == '$' || c == ',') then newString else newString ++ [c] ) "" value

Write a function that takes an argument x and returns a lazy sequence that has every third number, starting with x. Then, write a function that includes every fith number beginning with y. Combine these functions through composition to return every eighth number, beginning with x + y.

everyThird :: Int -> [Int] 
everyThird x = [x, (x + 3) ..]
everyFifth :: Int -> [Int]
everyFifth y = [y, (y + 5) ..]
everyEighth :: Int -> Int -> [Int]
everyEighth x y = (zipWith (+) (everyThird x) (everyFifth y))

Use a partially applied function to define a function that will return half of a number and another that will append \n to the end of any string.

halfSize = (/ 2) addNewLine :: String -> String 
addNewLine = (++ "\n")

Write a function to determine the greatest common denominator of two integers.

gcd2 :: (Integral a) => a -> a -> a 
gcd2 x y = gcd2_ (abs x) (abs y)
where
gcd2_ a 0 = a
gcd2_ a b = gcd2_ b (a `rem` b)

Create a lazy sequence of prime numbers.

primes :: [Integer] 
primes = a [2..]
where
a (p:xs) = p : a [x | x <- xs, x `mod` p > 0]

Break a long string into individual lines at proper word boundaries.

changer :: [Char] -> [Char] -> [Char] 
changer [] res = res
changer (x:xs) res = changer xs (res ++ (if x == ' ' then "\n" else if x == '.' then ".\n" else [x]))
newLine :: [Char] -> [Char]
newLine xs = changer xs ""
main = print $ newLine "this is my test string which you can use to validate the output."

Add line numbers to the previous exercise I tried this exercise, but it was too hard for me to find a way to add the number to the sentence for every space in the word. What I could come up with was this:

renderLine :: Show a => Integer -> a -> String 
renderLine i a = show i ++ ". " ++ show a
bs :: Show a => [a] -> String
bs = unlines . zipWith renderLine [1..]
*Main> putStr $ bs "hello world"
1. 'h'
2. 'e'
3. 'l'
4. 'l'
5. 'o'
6. ' '
7. 'w'
8. 'o'
9. 'r'
10. 'l'
11. 'd'

To the above exercise, add functions to the left, right, and fully justify the text with spaces (making both margins straight).
Because I didn’t succeed with the above exercise, I will not be able to complete this exercise either.

Wrapping up

Today I learned more about the working of Haskell. I am looking forward to what the next chapter has in store for me.
Tomorrow I will continue with day three of the book. You can find my blog about that here:

Originally published at gist.github.com.

--

--

Roy Honders
yes-coding

Working as a frontend developer at Quintor. Currently writing short stories about tech.