0 Members and 1 Guest are viewing this topic.
[19:32:06] *** Joins: thewormkill (~thewormki@worms.lair)[19:32:06] *** Server sets mode: + [19:32:08] *** Server sets mode: + [19:32:14] *** Joins: lenoch (~lenoch@61476DB6.A460EC41.F860C5F1.IP)[19:32:28] *** Joins: acaan (~doctor@evilzone-F267F0C0.whyrlpool.com)[19:34:21] <thewormkill> we're waiting for poly[19:34:43] <acaan> kk i will go to bring some food i have to eat [19:34:44] <lenoch> fucking slow guy[19:34:48] <lenoch> [19:34:49] <thewormkill> [19:35:43] <lenoch> and thewormkill i'm actually serious about giving haskell maybe a go[19:35:50] <thewormkill> that's great[19:35:53] <thewormkill> [19:36:16] <lenoch> should learn a functional language someday so why not in the near future[19:36:49] <thewormkill> second, I'll be back in 5 minutes, dishes await[19:36:52] *** Joins: Polyphony (~Polyphony@local.host)[19:36:57] <Polyphony> i'm a shitty student[19:36:58] <lenoch> oh man[19:36:59] <lenoch> lol[19:37:05] <thewormkill> brb[19:38:47] <Polyphony> i need to start learning some haskell too[19:38:57] <Polyphony> i've played with it before, just never actually used it[19:42:20] <thewormkill> so I am back[19:42:32] <acaan> wooo[19:42:34] <thewormkill> acaan, lenoch, Polyphony, let's begin[19:42:38] <Polyphony> kk[19:43:11] <thewormkill> well, we talk about monads today[19:43:33] <thewormkill> these are a construct from a field of mathematics called category theory [19:43:53] <thewormkill> which roughly deals with categorizing things (woo!), mathematical things[19:44:12] <thewormkill> so, if anyone of you has a question, just interrupt, we have time for that[19:44:27] <acaan> question[19:44:34] <thewormkill> so, let's start with simple values...[19:44:38] <thewormkill> yeah, acaan?[19:44:51] <acaan> does it categorizes just numbers or some other objects ?[19:44:58] <thewormkill> objects in general[19:45:03] <acaan> kk[19:45:06] <thewormkill> that's the point[19:45:16] <thewormkill> well, a value is just that, some data[19:45:34] <thewormkill> using haskell syntax to bind a name to a value looks like so:[19:45:37] <thewormkill> let a = 5[19:46:00] <thewormkill> this is not universally valid syntax, but it makes claer what's going on[19:46:33] <thewormkill> now, the point is, functional languages generally don't allow for *changing* the value of a variable[19:46:50] <thewormkill> so if you already have a defined, changing what it means isn't possible[19:47:10] <thewormkill> instead, you can use functions to transform values[19:47:26] <lenoch> aight seems logical I was thinking of that[19:47:30] <thewormkill> now, these functions aren't like functions in, say, Ceither[19:47:37] <thewormkill> *C either[19:47:44] <thewormkill> in C I can write[19:47:59] <thewormkill> void a(){some_global++;}[19:48:11] <thewormkill> which does something but does not return a value[19:48:35] <thewormkill> so, if we compare it to the mathematical notion of a function, we see some glaring differences[19:49:08] <thewormkill> in mathematics, a function just maps values of an input domain to values of an output domain, so that you have unambiguous results[19:49:27] <thewormkill> now we see that this notion does not apply to void a, because it behaves very differently[19:49:44] <thewormkill> instead of just computing a value, it... well what does it? any ideas?[19:49:54] <acaan> changes it [19:49:59] <thewormkill> changes what?[19:50:04] <acaan> value[19:50:13] <acaan> of a global, side efect[19:50:13] <Polyphony> a is just a pointer[19:50:39] <thewormkill> actually both of you are right to some extend[19:50:57] <Polyphony> it's not a function because there's no output[19:50:58] <thewormkill> 1. it does not compute a value, so it has nothing to return (useless as a mathematical function)[19:51:10] <Polyphony> ^^ "mathematical function"[19:51:20] <lenoch> it's just a subroutien[19:51:31] <Polyphony> yeah, it's just a chunk of instruction[19:51:37] <thewormkill> 2. it does something else, which is modifying global state[19:51:55] <thewormkill> so, to sum up, it is not a real function, but a procedure.[19:52:01] <Polyphony> ah[19:52:11] <thewormkill> this means that it does not behave well in some contexts[19:52:20] <thewormkill> think of concurrency[19:52:57] <thewormkill> if you have multiple threads, the changes they apply to some data might be interfering with each other[19:53:39] <thewormkill> so some people thought that it might be a good idea to avoid these side-effects as they are called, what acaan already mentioned[19:53:46] <thewormkill> and I forgot to honour[19:54:38] <thewormkill> now, let's take a different approach of thinking, or simply get back to the point we are at now from a different direction[19:55:17] <thewormkill> so if data is just a bunch of values and we can calculate the results of functions on those to get *new* values[19:55:27] <thewormkill> how do we distinguish values?[19:55:32] <thewormkill> any ideas?[19:55:38] <acaan> we dont ?[19:56:04] <acaan> no[19:56:06] <acaan> MONAD[19:56:08] <acaan> :O[19:56:12] <thewormkill> lol[19:56:21] <thewormkill> okay, I'll spoiler it[19:56:26] <thewormkill> adding context to values[19:56:37] <thewormkill> sounds easy, but what does that mean?[19:56:46] <acaan> wait[19:56:50] <thewormkill> well, let's introduce a new concept...[19:56:53] <thewormkill> yeah?[19:56:59] <acaan> what do you mean by adding context [19:57:24] <thewormkill> well, say you have a function[19:57:54] <thewormkill> a pure function (which is how funcional programming calls mathematical functions with no side effects)[19:58:06] <thewormkill> code follows:[19:58:25] <thewormkill> f(x) = 1 / x[19:58:32] <thewormkill> (not haskell but w/e)[19:58:54] <thewormkill> it is certainly nothing special[19:59:09] <thewormkill> but, if you use it in source code, what will happen if we pass x=0[19:59:12] <thewormkill> ?[19:59:26] <lenoch> infinity[19:59:27] <acaan> undefined[19:59:32] <Polyphony> "undefined behavior" lol[19:59:40] <acaan> error[19:59:41] <Polyphony> actually i don't know, i just love C[19:59:52] <lenoch> you can't divide by 0[19:59:52] <acaan> i love U[19:59:52] <thewormkill> well, actually you crash your proggram[19:59:54] <acaan> LOL[20:00:02] <thewormkill> because you can't divide by 0[20:00:23] <thewormkill> it doesn't make sense in maths, so why should it make sense in our program?[20:00:26] <lenoch> well I heard it is something with infinity and stuff[20:00:29] <lenoch> but yeah you can't[20:00:30] <lenoch> :p[20:00:47] <lenoch> because um we want to bend the laws of space[20:00:54] <acaan> and time[20:00:54] <thewormkill> well, you could just check whether x is 0 but that leaves you with deciding what to do now[20:01:19] <Polyphony> "floating point exception (core dumped)"[20:01:26] <Polyphony> that's what happens with c[20:01:43] <thewormkill> so, basically we conclude that our function can *fail*[20:01:57] <lenoch> kinda like exceptions[20:01:59] <Polyphony> set errno and return NULL[20:02:26] <thewormkill> well, that's a way of representing failure, but it certainly isn't beautiful[20:02:35] <thewormkill> ...or not feasible in a pure context[20:02:39] <Polyphony> lol [20:02:43] <acaan> well just say undefined[20:02:55] <thewormkill> so instead we alter the output range of our function[20:02:55] <Polyphony> can we just pause for a moment, i'm gonna switch computers real quick[20:02:56] <acaan> its nothing[20:03:00] <thewormkill> Polyphony: sure[20:03:11] <lenoch> ok i'm reboot to the linoox then[20:03:13] <Polyphony> kk, it'll take like 5 seconds[20:03:14] <thewormkill> acaan: sure, but we're coming to that[20:03:20] <thewormkill> we'll wait[20:03:27] <acaan> sure[20:03:47] *** lenoch is now known as lenoch_away[20:04:14] <Polyphony> o/[20:04:22] <Polyphony> i'm back, told you it'd be quick[20:04:44] <thewormkill> lenoch left[20:05:33] <thewormkill> still left[20:05:35] <acaan> it connection i gues[20:06:03] <thewormkill> no he's rebooting[20:06:23] *** lenoch_away is now known as lenoch[20:06:30] <thewormkill> oh, we can proceedd[20:06:45] <thewormkill> well, acaan proposed to add undefined to the range of our function[20:06:45] <lenoch> fucking windows update[20:07:16] <thewormkill> that makes sense, but if we pass our result on to other functions (look up composition if you don't know what that is)[20:07:34] <thewormkill> , we need those functions to know of undefined[20:07:37] <thewormkill> meh, ugly[20:07:54] <thewormkill> so, instead we decide to add the *context of failure*[20:07:56] <lenoch> can't you do an if?[20:08:15] <thewormkill> lenoch: we do, but that's ugly if we need to repeat it[20:08:59] <Polyphony> so how does haskell handle it?[20:09:01] <lenoch> so what do we use?[20:09:04] <thewormkill> so, let's redefine the range of our function to two values: "Nothing" and "Just x"[20:09:06] <acaan> MONAD[20:09:18] <thewormkill> where x is the result of our computation[20:09:32] <acaan> the same function f(x)=1/x ?[20:09:44] <thewormkill> we basically pull out undefined from the range of results and handle it dufferently[20:09:53] <thewormkill> acaan: yes, with a quirk[20:09:55] <thewormkill> observe[20:10:06] <thewormkill> f(x) = 1/x if x != 0[20:10:15] <thewormkill> f(x) = Nothing otherwise[20:10:35] <lenoch> can you do it in haskell? that just looks weird :p[20:10:46] <thewormkill> *FIX: the first line has a Just[20:10:50] <thewormkill> lenoch: yes, you can[20:10:57] <acaan> well its like c with if statement[20:11:03] <thewormkill> haskell has a datatype called Maybe a[20:11:10] <thewormkill> a is any type[20:11:23] <thewormkill> and Maybe has two value constructors[20:11:27] <lenoch> yeah I saw that pop around [20:11:42] <thewormkill> 1. Nothing 2. Just a[20:11:48] <thewormkill> where a is a value of type a[20:11:57] <thewormkill> fuck I took the same name for both -.-[20:12:37] <thewormkill> is that clear that way of should I clarify?[20:13:10] <acaan> not really [20:13:25] <acaan> maybe is datatype that we pass two values ?[20:15:56] <thewormkill> No, Maybe is a datatype that has two constructors[20:16:04] <thewormkill> Nothing, which takes no arguments[20:16:13] <thewormkill> and Just x that takes one (x)[20:16:25] <lenoch> constructors in the oop sense?[20:16:31] <thewormkill> not exactly[20:16:48] <thewormkill> a value constructor constructs a value by representing the arguments[20:17:01] <thewormkill> basically it's a pattern for a value of a type[20:17:08] <thewormkill> but you can have multiple patterns[20:17:47] <thewormkill> so, we have a datatype that incorporates failure[20:18:11] <thewormkill> a function that returns something of type Maybe Int can return:[20:18:18] <thewormkill> 1. Just <an int here>[20:18:20] <thewormkill> 2. Nothing[20:18:36] <thewormkill> but what if we want to chain functions?[20:18:40] <acaan> ohhh[20:19:01] <acaan> well it fine if it returns maybe[20:19:19] <thewormkill> and if the second one *takes* a maybe as argument[20:19:29] <thewormkill> if it takes an int, we can't do that[20:19:58] <thewormkill> but there is a concept called a Functor[20:20:28] <thewormkill> a functor is just this: some construct that contains a value and adds some specific context to it[20:20:42] <thewormkill> but now comes the interesting part:[20:21:17] <thewormkill> a functor defines a function fmap that takes a function that takes a type a and a functor with a type a in it[20:21:32] <thewormkill> and returns a functor with the result of the function in it[20:21:41] <thewormkill> and it obeys one law[20:21:44] <thewormkill> if you call[20:22:07] <thewormkill> fmap identity f where f is an arbitry functor with something inside, you get f back[20:22:22] <thewormkill> so, that was a lot of info, are there any questions?[20:22:58] <lenoch> I should learn haskell to understand it fully right?[20:23:08] <acaan> and math[20:23:15] <acaan> i mean just enoguh [20:23:46] <thewormkill> lenoch: well, is there something unclear? because this is just generic atm[20:24:15] <lenoch> the context thing with a functor[20:24:29] <lenoch> what do you mean with context?[20:24:39] <thewormkill> in our example it is failure[20:25:03] <thewormkill> but it can be basically anything: non-determinism, side-effects...[20:25:12] <lenoch> oh so a functor is like a return value for a function?[20:25:26] <thewormkill> no, it's a thing that contains a value[20:25:34] <thewormkill> and adds some context to it by being thee[20:25:37] <thewormkill> *there[20:25:45] <lenoch> anything? or just a function as value?[20:26:20] <thewormkill> I don't really understand what you mean[20:26:46] <lenoch> is it like a lambda?[20:26:54] <thewormkill> no.[20:27:08] <thewormkill> lists are functors[20:27:14] <thewormkill> maybe's are as well[20:27:29] <thewormkill> the idea is that each functor contains values[20:27:37] <thewormkill> and that it adds context[20:27:49] <thewormkill> in case of maybe that's the possible absence of a value[20:28:09] <thewormkill> in case of a list that's the possibly unlimited number of values[20:28:35] <thewormkill> acaan, Polyphony, do you have questions as well?[20:29:29] <acaan> hmm, what does functor returns ?[20:29:45] <Polyphony> honestly i'm just logging this convo so i can look at it later[20:29:58] <thewormkill> okay, Polyphony[20:30:05] <thewormkill> acaan: it does not return anything[20:30:08] <Polyphony> i am a data hoarder, and this is kind of interesting [20:30:16] <thewormkill> it's not a function[20:30:31] <acaan> its a special haskell construtc ?[20:30:34] <thewormkill> a list doesn't return anything, doesn't it?[20:30:35] <acaan> *construct [20:30:43] <thewormkill> acaan: no, that's category theory[20:30:55] <acaan> ohh its like wrapper for datatype ?[20:30:57] <thewormkill> lenoch: is it getting a bit clearer now?[20:30:59] <thewormkill> acaan: yes[20:31:05] <thewormkill> absolutely[20:31:09] <lenoch> ooooh[20:31:44] <lenoch> Yeah I think it's good[20:31:52] <acaan> its good now[20:31:55] <acaan> alot clearer[20:31:56] <thewormkill> good [20:32:32] <thewormkill> now, we can just fmap functions over functors and thus apply functions to values inside them[20:32:52] <thewormkill> but now there are some other contexts that are more complex, behod[20:32:55] <thewormkill> *behold[20:33:19] <lenoch> in haskel you can in theory chain infinite functions?[20:33:32] <thewormkill> yes, but that gets messy around 500 [20:33:56] <lenoch> yeah I mean lol[20:34:06] <thewormkill> jokes aside, what if our context is "having side effects"?[20:34:09] <lenoch> seems quite powerfull in some scenario's[20:34:14] <thewormkill> in all [20:34:29] <thewormkill> you can split it in parts, which you do[20:34:32] <lenoch> use a Maybe[20:34:37] <acaan> it can't have them ?[20:34:44] <thewormkill> well, but you need them[20:34:59] <thewormkill> if your program can't print to the screen, you might as well not run it[20:35:23] <acaan> hmm[20:35:31] <thewormkill> well, if you need to have a function to have side effects, the values it returns need a context[20:35:38] <thewormkill> they are "contaminated"[20:36:06] <thewormkill> I mean if you list a directory, your program needs to know that the data it got could have been different[20:36:23] <thewormkill> and that it's computation required interacting with teh outside world[20:37:02] <thewormkill> well, this also requires sequencing[20:37:20] <thewormkill> let's say you print to the screen and print to the screen again[20:37:28] <thewormkill> you want the data to appear in order[20:37:56] <thewormkill> but if all your functions are pure, the compiler can do A LOT of optimizations, rearranging and the like to them[20:38:10] <thewormkill> so, sequencing is explicit[20:38:17] <thewormkill> enter monads[20:38:23] * thewormkill bangs drum[20:38:43] <thewormkill> a monad is a functor[20:38:51] <thewormkill> but not each functor is a monad[20:39:03] <thewormkill> a monad supports a few operations[20:39:27] <thewormkill> 1. inserting a pure, a context-less value, into a default context[20:40:17] <thewormkill> 2. taking a value in a monad (a monadic value) and a function that takes a pure value of the same type and returns a monadic value[20:40:25] <thewormkill> let's express that in code:[20:40:50] <thewormkill> (>>=) :: Monad m => m a -> (a -> m b) -> m b[20:40:56] <thewormkill> whoo scary haskell[20:41:04] <acaan> damn[20:41:07] <thewormkill> but that's easy: it expresses a type[20:41:14] <thewormkill> >>= is the function name[20:41:35] <thewormkill> Monad m means that m is a monad (look up typeclasses if you want to know more)[20:41:45] <thewormkill> m a is the first argument[20:41:55] <thewormkill> it's a monad m with a value of type a inside[20:42:09] <thewormkill> the second argument, (a -> m b) is function[20:42:17] <thewormkill> now guess what it does[20:42:40] <acaan> returns monad ?[20:42:47] <acaan> or functor ?[20:42:50] <acaan> or b[20:42:52] <thewormkill> yes it takes an a and returns a monad with b inside[20:42:59] <thewormkill> * a monad m[20:43:18] <thewormkill> lenoch: you with us so far?[20:43:57] * thewormkill throws chalk at lenoch[20:44:18] <acaan> lol[20:44:28] <thewormkill> is he asleep?[20:44:56] <acaan> throw another one [20:44:57] <Polyphony> heh[20:45:20] <Polyphony> why in the hell would you name a function >>=[20:45:33] *** lenoch is now known as lenoch_away[20:45:41] <Polyphony> inb4 thewormkill is just trolling us all[20:45:43] <thewormkill> Polyphony: you call it in infix notation[20:45:55] <thewormkill> arg1 >>= arg2[20:46:14] <thewormkill> inb4 you ask + is a function in haskell[20:46:29] <Polyphony> oh lol i get it then[20:47:33] <thewormkill> hm, not sure if I should carry on without lenoch, he has my last piece of chalk in his beer[20:47:41] <thewormkill> oh the fucker is away[20:47:56] <Polyphony> lel[20:48:37] * thewormkill gets uses a nail to write on[20:48:46] <thewormkill> okay, he'll catch up I'm sure[20:49:11] <Polyphony> we're learning shell scripting in OS class... D:[20:49:14] <thewormkill> well, this way you can chain monadic actions together[20:49:27] <thewormkill> acaan: are you following at least?[20:49:30] <thewormkill> [20:49:40] <Polyphony> acaan is now known as acaan_away[20:49:42] <acaan> yes[20:49:52] <thewormkill> good[20:50:02] <thewormkill> well, now you can add order, how cool is that?[20:50:38] <thewormkill> there are some more functions defined for monads tho:[20:50:54] <thewormkill> fail (which just tells us that a monadic action is not possible)[20:51:17] <thewormkill> and (>>) which has the type[20:51:32] <thewormkill> (>>) :: Monad m => m a -> m b -> m b[20:51:49] <thewormkill> it just executes it's arguments in order and returns the second[20:52:37] <acaan> it returns b ? [20:52:38] <thewormkill> This way, you can perform IO (although it is buried a bit in the actual implementation of haskell's features[20:52:49] <thewormkill> acaan: it returns a monad with b inside[20:53:09] <thewormkill> now, you may ask why we did all this[20:53:19] <acaan> for no side effects ?[20:53:38] *** lenoch_away is now known as lenoch[20:54:03] <thewormkill> yes, you can have complete purity everywhere, unless you need something to perform IO[20:54:11] <thewormkill> but even those functions are pure[20:54:14] <thewormkill> you ask why?[20:54:23] <thewormkill> simple, they just chain monadic actions[20:54:30] <thewormkill> thus, they return a monad[20:54:55] <thewormkill> and how that monad does what it does (IO, carrying state, adding read-only data...)[20:55:06] <thewormkill> is completely independent of it's usage[20:55:13] <acaan> it wraps it bascicly[20:55:16] <acaan> it protects purenes[20:55:17] <thewormkill> yes[20:55:47] <thewormkill> IO is done by creating IO actions you need and generating the stuff you need to do for them[20:56:03] <thewormkill> now, you may have noticed that a value can't escape a monad[20:56:23] <thewormkill> if you put it in, you can transform it etc.[20:56:27] <thewormkill> but it stays in there[20:56:34] <thewormkill> because the context can't be undone[20:56:49] <thewormkill> if you did IO to get a value, that value needs to be treated as such[20:57:03] <thewormkill> lenoch: you missed a bit, right?[20:57:13] <lenoch> yeah[20:58:11] <thewormkill> well, I did essentially explain the basic concept of monads, so you just need to let me know what you missed [20:58:26] <thewormkill> if anyone else has questions, feel free to ask them as well[20:59:08] <lenoch> hmm no i don't think I missed it[20:59:12] <lenoch> the bouncer had it[20:59:26] <thewormkill> oh, nice[20:59:39] <thewormkill> well, I'll put it up on evilzone, okay?[20:59:47] <lenoch> good idea![21:00:02] * thewormkill is going to get the logs[21:00:37] <acaan> cool, thanks thewormkill [21:00:41] <thewormkill> np[21:01:45] <acaan> ok i am starting with haskell now]
<m0rph-is-gay> fuck you thewormkill you python coding mother fucker