Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save veslav3/0a8c9d96ee0d185058deccd77e42618a to your computer and use it in GitHub Desktop.
Save veslav3/0a8c9d96ee0d185058deccd77e42618a to your computer and use it in GitHub Desktop.

Day two spock's great strength with Haskell

Today I will continue with the second chapter of the seven languages in seven weeks book about haskell.

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:

foldl (+) 0 [1..3]
6

This will give the same result as:

1 + 2 + 3
6

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.

# Day two spock's great strength with Haskell
Today I will continue with the second chapter of the seven languages in seven weeks book about haskell.
## 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 ")".
```haskell
(\x -> x ++ " captain.") "Logical,"
"Logical, captain."
```
Using anonymous functions has the most effect when using it in combination with other functions:
```haskell
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:
```haskell
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:
```haskell
foldl (+) 0 [1..3]
6
```
This will give the same result as:
```haskell
1 + 2 + 3
6
```
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:
```haskell
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:
```haskell
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:
```haskell
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:
```haskell
import Data.List
sortList a = sort a
```
Now I can sort a list like this:
```haskell
*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:
```haskell
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.**
```haskell
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.**
```haskell
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.**
```haskell
halfSize = (/ 2)
addNewLine :: String -> String
addNewLine = (++ "\n")
```
**Write a function to determine the greatest common denominator of two integers.**
```haskell
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.**
```haskell
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.**
```haskell
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:
```haskell
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment