Created
May 21, 2017 15:57
-
-
Save enobayram/4c9ba6e7723a1622530e56884fc97357 to your computer and use it in GitHub Desktop.
Maybe monad in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
// return :: Monad m => a -> m a | |
typedef void * /* m a */ return_t(void * /* a */); | |
// type kleisli_arrow a b = a -> m b | |
typedef void * /* m b */ kleisli_arrow(void * /* a */); | |
// bind :: Monad m => m a -> (a -> m b) -> m b | |
typedef void * /* m b */ bind_t(void * /* m a */, kleisli_arrow * /* a -> m b */); | |
// class Monad m | |
typedef struct { | |
bind_t * bind; | |
return_t * return_; | |
} Monad; | |
// data Maybe a = Nothing | Just a | |
typedef struct { | |
int is_it_there; | |
void * /* a */ it; | |
} Maybe; | |
Maybe nothing = {0,0}; | |
void * /* Maybe a */ just (void * a /* a */) { | |
Maybe * result = (Maybe *)malloc(sizeof(Maybe)); | |
result->is_it_there=1; | |
result->it=a; | |
return result; | |
} | |
// instance Monad Maybe | |
bind_t bindMaybe; | |
Monad maybeMonad = { bindMaybe, just}; | |
void * /* Maybe b */ bindMaybe (void * ma /* Maybe a */ | |
,kleisli_arrow * a_mb /* a -> Maybe b */) { | |
Maybe * maybeA = (Maybe *) ma; | |
if(!maybeA->is_it_there) return ¬hing; | |
return a_mb(maybeA->it); | |
} | |
int weatherIsNice() {return 1;} // Imagine this is more complicated | |
// Maybe Int | |
void * getData() { | |
if(weatherIsNice()) { | |
int * it = (int *) malloc(sizeof(int)); | |
*it = 3; | |
return just(it); | |
} else return ¬hing; | |
} | |
float data[] = {42.0f, 41.0f, 0.5f, 15.0f }; | |
// Int -> Maybe Float | |
void * /* Maybe Float */ getMoreData(void * data_index_p /* Int */ ) { | |
int data_index = * (int *) data_index_p; | |
if(data_index>=0 && data_index < 4) { | |
float * it = (float *)malloc(sizeof(float)); | |
*it = data[data_index]; | |
return just(it); | |
} else return ¬hing; | |
} | |
struct Unit /* () */ {} unit; // A data type that holds no information | |
// Float -> Maybe () | |
void * print(void * f_ /* Float */) { | |
float f = * (float *) f_; | |
printf("%f", f); // Nobody said we're in a pure language! (Evil grin) | |
return just(&unit); | |
} | |
/* | |
main = do | |
a <- getData | |
b <- getMoreData a | |
print b | |
*/ | |
int main() { | |
maybeMonad.bind(maybeMonad.bind(getData(), getMoreData), print); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment