~spidernet/algebraiC

371a71fb6dc40ab46c99f9b7343b306da8e21364 — Alessio Chiapperini 5 years ago bb624e8
Add list data type example

Add list data type and data constructors inspired by Miran Lipovaca's
"Learn You a Haskell for Great Good".

To demonstrate the concept added length(), print_list() and map()
functions.
2 files changed, 138 insertions(+), 0 deletions(-)

A list/Makefile
A list/list.c
A list/Makefile => list/Makefile +14 -0
@@ 0,0 1,14 @@
.POSIX:
CC 		= cc
CFLAGS 	= -std=c99 -Wpedantic -Wall -Wextra -O3
LDFLAGS = 

all: list

list: list.o
	$(CC) $(CFLAGS) -o main list.o $(LDFLAGS)

list.o: list.c

clean:
	rm -f list list.o

A list/list.c => list/list.c +124 -0
@@ 0,0 1,124 @@
#include <stdio.h>
#include <stdlib.h>

#define NUM_ELEMS 15

/* Data constructor names */
enum list_const {EMPTY, CONS};

/* Actual sum data type */
struct list {
        enum list_const type;
        struct data {
                int num;
                struct list *next;
        } data;
};

/* Empty list constructor */
struct list *
make_empty(struct list *lst)
{
        lst->type = EMPTY;
        lst->data = (struct data) {0};

        return lst;
}

/* Cons constructor */
struct list *
cons(int a, struct list *lst)
{
        if (lst) {
                struct list *new = malloc(sizeof(struct list));

                if (new) {
                        new->type = CONS;
                        new->data.num = a;
                        new->data.next = lst;
                        lst = new;
                }
        }

        return lst;
}

int
length(struct list *lst)
{
        if (lst) {
                switch (lst->type) {
                case EMPTY:
                        return 0;
                case CONS:
                        /* Could use tail recursion */
                        return 1 + length(lst->data.next);
                default:
                        fprintf(stderr, "Non-exhaustive patterns in function "
                            "%s\n", __func__);
                }
        }

        return -1;
}

struct list *
map(int (*fun)(int a), struct list *lst)
{
        if (lst) {
                struct list *tmp = lst;
                while (tmp) {
                        tmp->data.num = fun(tmp->data.num);
                        tmp = tmp->data.next;
                }
        }

        return lst;
}

void
print_list(struct list *lst)
{
        switch (lst->type) {
        case EMPTY:
                puts("[]");
                break;
        case CONS:
                printf("%d,", lst->data.num);
                print_list(lst->data.next);
        }
}

int
sum(int a)
{
        return a+1;
}

int
main(void)
{
        struct list *lst = malloc(sizeof(struct list));
        if (!lst) return EXIT_FAILURE;

        make_empty(lst);
        print_list(lst);

        for (int i = 1; i <= NUM_ELEMS; i++) {
                lst = cons(i, lst);
        }
        
        print_list(lst);
        printf("Length %d\n", length(lst));

        map(&sum, lst);
        print_list(lst);

        struct list *curr = 0;
        while ((curr = lst)) {
                lst = lst->data.next;
                free(curr);
        }

        return EXIT_SUCCESS;
}