Simple IO stuff

Today we’ll play around with the following task:

Write a program that will receive a number N as an input, and that then will do additional N reads and print them out.

So first, let’s see how we can do this with a static number of times, say 3:

*Main> (readLn :: IO Int) >>= \x -> return $ x : []
1
[1]
*Main> (readLn :: IO Int) >>= \x -> (readLn :: IO Int) >>= \y -> return $ x : y : []
1
2
[1,2]
*Main> (readLn :: IO Int) >>= \x -> (readLn :: IO Int) >>= \y -> (readLn :: IO Int) >>=
\z -> return $ x : y : z : []
1
2
3
[1,2,3]
*Main>

So what we need, is a function that will take a number as an input, and spit list of IO Ints as an output.
There are 2 ways to do this, and we’ll do both and then discuss the difference between them.

pn :: Int -> [IO Int]
pn' :: Int -> IO [Int]

What pn does, is returns a list of IO actions that need to be executed (which we can execute with sequence for example).
pn’ on the other hand, returns an IO action of list of numbers.
So we can view pn’ as one IO action that returns a list of numbers, and pn as a list of IO actions that return a number. Pretty simple!

Let’s start with pn. To cover the base case, we say that pn = 0 will return an empty list of actions. Note that [] is [IO Int] here, not [Int].

pn 0 = []

For the inductive step, we store the *read a number using readLn* action in a list (but not execute it), and then append that action to the list. Note that x is IO Int here, not Int.

pn n = do
-- No need for explicit signature here because Haskell already knows this by the fn signature
let x = readLn :: IO Int
x : pn (n - 1)

Now, to execute this, we can do:

*Main> sequence $ pn 3
1
2
3
[1,2,3]
*Main>

And what is sequence?

*Main> :t sequence
sequence :: Monad m => [m a] -> m [a]
sequence [] = return []
sequence (x:xs) = do v <- x; vs <- sequence xs; return (v:vs)
*Main>

So, sequence takes a list of monads (IO actions in this case), executes each one of them and returns their result *combined*.
pn’ is the same implementation as pn, but with sequence _within_ it so that we don’t have to call sequence each time.

pn' :: Int -> IO [Int]
pn' 0 = return []
pn' n = do
x <- readLn
xs <- pn' (n - 1)
return $ x : xs

For the base case, we need a monadic empty list, that is:

*Main> :t return
return :: Monad m => a -> m a
*Main> :t (return []) :: IO [Int]
(return []) :: IO [Int] :: IO [Int]

For the inductive step, we are reading a number into x, i.e. executing the read action with <- (in contrast to =). Note that x is Int here, not IO Int.
Then, we recursively call pn’ to read for more numbers, and store those executed reads in xs. Note that xs is [Int] here.
After that, we return x:xs in order to get a IO [Int] instead of [Int].
We can now call it like:

*Main> pn' 3
1
2
3
[1,2,3]
*Main>

Let’s try to unwrap this call:

test :: IO [Int]
test = do
x' <- readLn
xs' <- do
x'' <- readLn
xs'' <- do
x''' <- readLn
xs''' <- return []
return $ x''' : xs'''
return $ x'' : xs''
return $ x' : xs'

And that’s how it works. Or, we can rewrite everything as:


Prelude> let pn'' n = sequence $ take n $ repeat (readLn :: IO Int)
Prelude> pn'' 5
1
2
3
4
5
[1,2,3,4,5]
Prelude>

But it’s worth knowing what it does behind the scenes 🙂
We can now extend this function to accept an additional parameter (function), that will do something to the read value:

pn''' :: Int -> (Int -> Int) -> IO [Int]
pn''' 0 _ = return []
pn''' n f = do
x <- readLn
xs <- pn'' (n - 1) f
return $ (f x) : xs

And call it like:

*Main> pn''' 5 succ
1
2
3
4
5
[2,3,4,5,6]
*Main>

Vector and Monoids

Today I was playing around with Haskell and Monoids, and here’s what I came up with:

import Data.Monoid

data Vector = Vector (Int, Int) deriving (Show)
newtype SumVector = SumVector Vector deriving (Show)
newtype ProductVector = ProductVector Vector deriving (Show)

instance Monoid (SumVector) where
mempty = SumVector $ Vector (0, 0)
SumVector (Vector (a, b)) `mappend` SumVector (Vector (c, d)) = SumVector $ Vector (a+c, b+d)

instance Monoid (ProductVector) where
mempty = ProductVector $ Vector (1, 1)
ProductVector (Vector (a, b)) `mappend` ProductVector (Vector (c, d)) = ProductVector $ Vector (a*c, b*d)

What I was interested in, what is the difference between newtype and data? Since when I replaced newtype with data, the code worked as expected.
Here’s what I got as an answer:

 what is the main difference between data and newtype?
Bor0: newtype has the same runtime representation as the underlying type
data can do sum types (using |) and multi-element records
you'd use newtype for performance reasons, when it is possible to do so
also, you can use GeneralizedNewtypeDeriving to pull existing instances into your new type
e.g., suppose you have data Foobar { ... } and instance ToJSON Foobar
then you can do newtype Baz = Baz Foobar deriving (ToJSON)
you can't do that with data Baz = Baz Foobar

foldl and foldr

First, we start with the definitions:
foldr:

foldr f z (x:xs) = f x (foldr f z xs) (*)
foldr _ z [] = z (**)

foldl:

foldl f z (x:xs) = foldl f (f z x) xs (*)
foldl _ z [] = z (**)

foldr starts from the right and goes on to the left (right-associative), while foldl does exactly the opposite.
As usual, it’s best to see with examples. Assume generic list of [a, b, c] and generic function f:

Case foldr:

foldr f z (x:xs) = f x (foldr f z xs)
=> foldr f z [a, b, c]
= f a (foldr f z [b, c]) (by (*))
= f a (f b (foldr f z [c]) (by (*))
= f a (f b (f c (foldr f z []))) (by (*) and (**))
= f a (f b (f c z))

Case foldl:

foldl f z (x:xs) = foldl f (f z x) xs
=> foldl f z [a, b, c] (by (*))
= foldl f (f z a) [b, c] (by (*))
= foldl f (f (f z a) b) [c] (by (*))
= foldl f (f (f (f z a) b) c) [] (by (*) and (**))
= (f (f (f z a) b) c)

So we’ve shown the associativity of both foldr and foldl.
Why do we need both foldr and foldl? Because of associativity of course. There are some cases where we’d want to use foldr, and some cases where we’d want to use foldl.
Consider some f (binary function) which is not associative (e.g. ‘-‘). Try evaluating:


*Main> foldr (-) 0 [1,2,3]
2
*Main> foldl (-) 0 [1,2,3]
-6

So, what really inspired me to write this article is one of the examples given in LYAH:


solveRPN x = foldl foldingFunction [] $ words x
where foldingFunction (x:y:ys) "*" = (x * y):ys
foldingFunction (x:y:ys) "+" = (x + y):ys
foldingFunction (x:y:ys) "-" = (y - x):ys
foldingFunction xs numberString = read numberString:xs

This is a very elegant solution. I tried writing a RPN calculator some time ago in JS (imperative style) and it involved a lot of checks for side cases, while in Haskell where we have the definitions of all functions that we are using, there is no room for side cases. We know exactly what we are trying to evaluate.

If you want a thorough explanation of the solveRPN function, you can check it at http://learnyouahaskell.com/functionally-solving-problems, while here I’ll only give a brief explanation.

Our foldingFunction acts as a stack storage, and accepts two parameters (the first parameter being the initial parameter that we pass (an empty stack), and the second one being the current element taken from the list), as foldl expects. So, in the where clause we are actually pattern matching on foldingFunction .

In the case where we have two (or more) numbers stored into our stack (x:y:ys) and we arrive at “*” as the current element of the input list, then we multiply those two numbers and store the result back in the stack. Likewise is the definition for “+” and “-“. However, if we match none of the specified operators, then we just store it back into our stack as a number.

Class and Instance

Today, we want a generic Animal class, so that we can instantiate animals out of it in a easy way. How can we do that?
First, we’ll want to create our generic class. We do it this way:

class Animal c where
doSomething :: c -> String
name :: c -> String

But we have a problem here. We can’t do

class Animal c where
doSomething :: String
name :: String

Because Haskell forces us to use the type that will be instantiated in our instances. We’ll cover on that later (*).
So let’s make our Cat and Dog instances now

data Dog = Dog
data Cat = Cat

instance Animal Dog where
doSomething _ = "Woof!"
-- name = "A dog" -- you can't do this
name _ = "A dog"

instance Animal Cat where
doSomething _ = "Meow!"
name _ = "A cat"

Now we can do some fancy stuff like

*Main> doSomething Dog
"Woof!"
*Main> doSomething Cat
"Meow!"
*Main> name Dog
"A dog"
*Main> name Cat
"A cat"
*Main>

So, basically, what we just wrote is “syntactic sugar” for

data DogOrCat = Dog' | Cat'

name' Dog' = "A dog"
name' Cat' = "A cat"

doSomething' Dog' = "Woof!"
doSomething' Cat' = "Meow!"

But the problem with this approach is that, whenever we want to instantiate another animal, we’d have to change the already existing structure (DogOrCat). We don’t want that.
We also risk in calling name’ for an Animal which may not have an instance. Instance forces you to instantiate all functions in the Class.
(*) Basically, this is what triggered this post: I had a discussion with a friend of mine today, and he said that you can’t do something like this in Haskell:

data Dog = Dog { name :: String; age :: Int, bark :: BarkKind }
data Cat = Cat { name :: String, age :: Int, meow :: MeowKind } -- error.

Which is correct. The reason for this is the namespace. name and age (declared in Dog) are global functions, and we are trying to re-declare them in Cat.
He wanted this kind of structure in order to be able to parse some JSON stuff.
I headed over to #haskell and had a discussion, where one guy had this implementation as a suggestion:

instance FromJSON Dog where
parseJSON (Object v) =
Dog v .: "name"
v .: "bites"
parseJSON _ = mzero

instance FromJSON Cat where
parseJSON (Object v) =
Cat v .: "name"
v .: "likes-humans"
parseJSON _ = mzero

This is using the Aeson library. Basically, that’s what Aeson did. They declared some generic class, so that we can make instances out of it in a elegant way where types will not conflict with each other.

Int List Monoid implementation in C

Here is an implementation in C of the monoid ([Int], ++, []):

/*
* Experimental fun. List Monoid implementation in C by Boro Sitnikovski
* 26.12.2013
*
*
boro@boro:~/test$ gcc list.c
boro@boro:~/test$ ./a.out
A = [ 1 2 3 ]
B = [ 5 6 7 ]
Head of list A: 1
Head of list B: 5
B ++ A = [ 5 6 1 2 3 ]
A ++ B = [ 1 2 5 6 7 ]
123:A ++ B = [ 123 1 2 5 6 7 ]
boro@boro:~/test$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> let a = [1, 2, 3]
Prelude> let b = [5, 6, 7]
Prelude> head a
1
Prelude> head b
5
Prelude> b ++ a
[5,6,7,1,2,3]
Prelude> a ++ b
[1,2,3,5,6,7]
Prelude> 123:a ++ b
[123,1,2,3,5,6,7]
Prelude>
*
*/

#include
#include

#define T int
#define EMPTY_LIST NULL

typedef struct ListMonoid {
T value;
struct ListMonoid *next;
} ListMonoid;

ListMonoid *A, *B;

void list_init() {
static ListMonoid a1, a2, a3;
static ListMonoid b1, b2, b3;

a1.next = &a2; a2.next = &a3; a3.next = EMPTY_LIST;
b1.next = &b2; b2.next = &b3; b3.next = EMPTY_LIST;

a1.value = 1;
a2.value = 2;
a3.value = 3;

b1.value = 5;
b2.value = 6;
b3.value = 7;

A = &a1;
B = &b1;
}

T list_head(ListMonoid *L) {
return L->value;
}

void list_append(ListMonoid **L, T value) {
ListMonoid *newL = (ListMonoid *)malloc(sizeof(ListMonoid));
newL->value = value;
newL->next = *L;
*L = newL;
}

void list_print(ListMonoid *L) {
printf("[ ");
while (L) {
printf("%d ", L->value);
L = L->next;
}
printf("]\n");
}

void list_free(ListMonoid *L) {
ListMonoid *tmp = L;
while (tmp) {
L = tmp->next;
free(tmp);
tmp = L;
}
return;
}

ListMonoid *list_add(ListMonoid *L1, ListMonoid *L2) {
ListMonoid *tmp, *L;
tmp = L = (ListMonoid *)malloc(sizeof(ListMonoid));

while (1) { // L1
tmp->value = L1->value;
L1 = L1->next;
if (!L1) {
tmp->next = NULL;
break;
}
tmp = tmp->next = (ListMonoid *)malloc(sizeof(ListMonoid));
}

while (1) { // L2
tmp->value = L2->value;
L2 = L2->next;
if (!L2) {
tmp->next = NULL;
break;
}
tmp = tmp->next = (ListMonoid *)malloc(sizeof(ListMonoid));
}

tmp->next = NULL;

return L;

}

int main() {

ListMonoid *L;

list_init();

printf("A = ");
list_print(A);

printf("B = ");
list_print(B);

printf("Head of list A: %d\n", list_head(A));
printf("Head of list B: %d\n", list_head(B));

L = list_add(B, A);
printf("B ++ A = ");
list_print(L);
list_free(L);

L = list_add(A, B);
printf("A ++ B = ");
list_print(L);
list_free(L);

L = list_add(A, B);
list_append(&L, 123);
printf("123:A ++ B = ");
list_print(L);
list_free(L);


return 0;
}