<     May 2017     >
Su Mo Tu We Th Fr Sa  
    1  2  3  4  5  6  
 7  8  9 10 11 12 13  
14 15 16 17 18 19 20  
21 22 23 24 _2_5 26 27  
28 29 30 31
00:00 saussure joined
00:02 takle joined
00:04 acarrico joined
00:16 uglyfigurine joined
00:17 exferenceBot joined
00:17 hexagoxel joined
00:18 saussure joined
00:21 mb013619 joined
00:23 takle joined
00:28 diegs_ joined
00:29 conal joined
00:35 juanpaucar joined
00:36 saussure joined
00:37 lewis joined
00:39 Bare joined
00:40 aarvar joined
00:41 juanpaucar joined
00:41 louispan joined
00:43 takle joined
00:49 conal joined
00:54 saussure joined
01:04 takle joined
01:08 juanpaucar joined
01:11 louispan joined
01:12 <thang1> Okay, let me know if I'm crazy...
01:12 siduzy joined
01:12 <thang1> But is it overkill to solve "convert a number to roman numerals" with a parser?
01:12 vaibhavsagar joined
01:13 <geekosaur> wrong tool entirely, I'd think, since the parser can't easily handle the subtraction-based rules
01:13 <thang1> Right, that's what I thought
01:14 <thang1> I'm trying to think of the most elegant solution to solve the most general case of roman numerals: https://en.wikipedia.org/wiki/Roman_numerals
01:14 <geekosaur> last time I needed to do it I built something recursive, but that was in the 80s and in C >.>
01:15 <thang1> Roman numerals can either have (or not have) subtraction-based rules. Sometimes they use IIII instead of IV. Sometimes roman numerals omit V and L entirely, using IIIII and XXXXX instead. Sometimes they use overbar for x1000, sometimes they don't, sometimes they use |--| boxes to denote x1,000,000, sometimes they use different symbols for I, V, X, M, etc...
01:16 <thang1> Sometimes there are double subtractives, so XIIX, IIXX, XVIII are all potentially valid for "18"
01:17 <thang1> Sometimes IIII is used for 4 but IV is still used for 10 (especially for clocks). Sometimes N is used for zero, sometimes it's used for 90, sometimes 70, 40, 11, 7, 150, 151, 160, etc., all have special characters for them
01:18 <thang1> It gets a little ridiculous. So I was basically thinking that if one could just make a way to define an "alphabet", the "rules", etc., and then just generate a way to convert arabic numerals to roman numerals based on the alphabet and rules and so on. Which, to me, sounds like something you would use a parser or grammer or something for
01:22 diegs_ joined
01:23 malaclyps joined
01:23 <mb013619> you could just use arabic numerals ¯\_(ツ)_/¯
01:24 <thang1> This is more an exercise in bikeshedding and "how would I solve this if I wanted to do it MOSTEST CORRECTERIST METHOD(tm)"
01:25 <thang1> What inspired this was mostly me getting pissed off about leetcode's "convert to roman numeral" problem that's limited from 0-4,000 and people solve it in like 4-5 lines by hardcoding knowledge of the domain into the answer to the point where it'll break every time you want to modify some super minor thing.
01:25 takle joined
01:26 <thang1> Sure, it's "elegant", but it also feels super wrong. So, then, I naturally wondered what the /most general/ method possible would be. Which lead to me discovering just how insanely messed up and non-standardized roman numerals are... prompting the parser question. So yeah :p
01:35 juanpaucar joined
01:37 seantparsons joined
01:41 ianandrich joined
01:42 uglyfigurine joined
01:46 texasmynsted joined
01:46 takle joined
01:50 saussure joined
01:57 juanpaucar joined
02:00 texasmynsted joined
02:00 Youmu joined
02:02 conal joined
02:07 takle joined
02:07 saussure joined
02:17 saussure joined
02:18 systemfault joined
02:26 ebsen joined
02:27 louispan joined
02:28 takle joined
02:35 saussure joined
02:48 exferenceBot joined
02:49 takle joined
02:53 famusmockingbird joined
02:53 saussure joined
02:53 mjora7 joined
02:53 hexagoxel joined
02:53 carlomagno joined
03:02 saussure joined
03:10 takle joined
03:10 juanpaucar joined
03:14 <glguy> thang1: I'd start with something like this http://lpaste.net/355802 the rules for when to subtract things seem to just been when small digits occur before large digits
03:17 <thang1> Only in most cases. Sometimes there's double subtraction where XIIX counts as 18 and so does IIXX and XVIII. (xviij is also possible in some rules such as medical notation). Or were you thinking of cases like that when you said small digits before large digits?
03:17 <glguy> Yeah, that's what I was thinking of
03:19 <thang1> (Completely tangent question: Is there any good resource out there for understanding Modules on a deeper level? I understand them somewhat but whenever people start talking about polymorphic functions over modules and embedding modules in functions as first class values and other things like that it's just a giant woosh over my head lol)
03:20 <glguy> Which language?
03:20 <thang1> Modules as a concept in general. I know that they're different in implementation for different languages and I suppose I'm most interested in Haskell since I'm most familiar with it, but modules in OCaml and SML seem to be where most of the weird magic occurs
03:21 saussure joined
03:21 <glguy> Modules in Haskell aren't first-class things
03:21 |sync| joined
03:22 HoloIRCUser1 joined
03:22 <thang1> Yeah, I noticed. So they're basically solely for "namespaces" in haskell, but somehow first class modules can be used in place of type families or other things like that? At that point I start to think I don't really understand what the point of a module is in the first place
03:22 louispan joined
03:23 <thang1> glguy: the roman numerals snippit looks pretty neat, though. I'll have to play around with it
03:29 sabin joined
03:30 takle joined
03:31 uglyfigurine joined
03:35 mjora7 joined
03:35 sabin joined
03:39 saussure joined
03:40 vaibhavsagar joined
03:48 saussure joined
03:52 takle joined
03:58 saussure joined
04:12 takle joined
04:15 juanpaucar joined
04:16 saussure joined
04:19 Sornaensis joined
04:33 takle joined
04:34 saussure joined
04:38 Nycatelos joined
04:42 Big_G joined
04:44 louispan joined
04:51 saussure joined
04:53 famusmockingbird joined
04:54 takle joined
05:01 saussure joined
05:01 moei joined
05:10 pbrant joined
05:15 takle joined
05:17 meandi_2 joined
05:19 saussure joined
05:32 mjora7 joined
05:36 takle joined
05:37 saussure joined
05:37 juanpaucar joined
05:39 Kuros` joined
05:47 saussure joined
05:57 takle joined
05:59 Durbley joined
06:00 MarcelineVQ joined
06:05 saussure joined
06:11 a3f_ joined
06:12 aphorisme joined
06:18 takle joined
06:23 saussure joined
06:25 eacameron joined
06:32 saussure joined
06:39 takle joined
06:42 juanpaucar joined
06:50 saussure joined
06:50 galderz joined
06:51 aphorisme joined
06:57 mjora7 joined
06:58 arquebus joined
06:59 takle joined
07:00 saussure joined
07:05 juanpaucar joined
07:09 saussure joined
07:15 Pupnik joined
07:20 takle joined
07:27 saussure joined
07:27 govg joined
07:28 eatman joined
07:30 bvad joined
07:34 merijn joined
07:41 takle joined
07:43 colt44 joined
07:45 saussure joined
07:47 nickolay_ joined
07:51 bvad joined
07:53 mengu joined
07:54 thc202 joined
07:57 mattyw joined
08:02 takle joined
08:03 saussure joined
08:07 grdryn joined
08:08 psukys joined
08:08 uglyfigurine joined
08:09 juanpaucar joined
08:09 shookees joined
08:10 shookees left
08:13 saussure joined
08:22 prophile joined
08:23 takle joined
08:24 mattyw joined
08:25 slomo joined
08:25 slomo joined
08:30 Levex joined
08:38 i-amd3 left
08:44 takle joined
08:50 govg joined
08:54 MotherFlojo joined
08:58 zero_byte joined
08:58 saussure joined
09:02 im0nde joined
09:03 Bhootrk_ joined
09:05 takle joined
09:06 fotonzade joined
09:06 Bhootrk_ joined
09:06 mattyw joined
09:08 saussure joined
09:13 juanpaucar joined
09:25 takle joined
09:26 saussure joined
09:27 juanpaucar joined
09:35 saussure joined
09:37 romank joined
09:40 yellowj joined
09:41 rotsix joined
09:41 dni- joined
09:42 romank_ joined
09:45 saussure joined
09:46 takle joined
09:49 Levex joined
09:50 juanpaucar joined
10:00 govg joined
10:04 Gurkenglas joined
10:05 cschneid_ joined
10:07 takle joined
10:13 ThomasLocke joined
10:23 jarshwah joined
10:28 takle joined
10:29 uglyfigurine joined
10:29 saussure joined
10:37 romank joined
10:48 saussure joined
10:49 takle joined
10:54 juanpaucar joined
10:57 saussure joined
10:59 mattyw joined
11:10 takle joined
11:13 anmin joined
11:15 saussure joined
11:15 Orion3k joined
11:22 dni- joined
11:24 mattyw joined
11:31 takle joined
11:32 netheranthem joined
11:33 saussure joined
11:41 Gurkenglas joined
11:43 saussure joined
11:46 Levex joined
11:50 c0smo joined
11:50 baroncharlus joined
11:50 ThomasLocke joined
11:51 adarqui joined
11:52 takle joined
11:53 Purlox joined
11:58 govg joined
11:58 juanpaucar joined
11:58 takle joined
12:01 saussure joined
12:05 Levex joined
12:07 Iceland_jack joined
12:17 im0nde joined
12:19 saussure joined
12:28 saussure joined
12:29 seanparsons joined
12:31 lewis joined
12:42 kritzcreek joined
12:46 saussure joined
12:53 dni- joined
12:54 Cale joined
13:03 juanpaucar joined
13:04 saussure joined
13:08 prophile joined
13:14 saussure joined
13:22 iAmerikan joined
13:23 nyuszika7h joined
13:23 WhereIsMySpoon joined
13:23 <WhereIsMySpoon> o/
13:23 LKoen joined
13:24 scav joined
13:24 halogenandtoast joined
13:24 sullyj3 joined
13:25 <mniip> WhereIsMySpoon, for now, let's not get concerned with the implementation of reverse
13:25 <mniip> and move on with the 99 questions
13:25 <WhereIsMySpoon> ok :P
13:26 <WhereIsMySpoon> i see everyone followed me here
13:26 <mniip> haskell is all about making larger stuff from smaller stuff, so
13:26 <Cale> Well, I wanted to make sure you understood that reverse function I gave
13:26 raek joined
13:26 <mniip> would be a good example if you used your own reverse in your palindome implementation
13:26 <Cale> I think you were pretty close to it :)
13:26 <mniip> Cale, I think it's a little early
13:28 <WhereIsMySpoon> Cale: im sorry but i tried to re-read and i got hopelessly confused at the reverse’ xs . (x:) bit again
13:28 <WhereIsMySpoon> so..maybe not so close )
13:28 <mniip> Cale, perhaps the eta-expanded definition is better?
13:30 <Cale> WhereIsMySpoon: Well, that whole definition, I obtained by systematically replacing [] with id, and [x] with (x:) and (++) with (.)
13:30 <Cale> but we can think about it directly
13:30 <Cale> reverse' xs is the function which adds the elements of xs in reverse order to any list it's given
13:30 <Cale> (x:) is the function which will add x to the list it's given
13:31 <Cale> So if we do both those things, we'll have added all the elements of (x:xs), in reverse order
13:32 prophile joined
13:32 saussure joined
13:32 <Cale> and yeah, if you don't like this approach, a similar definition might be easier to follow for now:
13:32 <Cale> reverse' [] ys = ys
13:32 tsmish joined
13:32 <Cale> reverse' (x:xs) ys = reverse' xs (x:ys)
13:33 <Cale> I tend to prefer the other way of thinking about it, because it's just nice to see that we can make these substitutions and turn a slow algorithm into a fast one.
13:33 <* ski> . o O ( Thompson calls that function `shunt' .. another possible name would be `reverseAppend', where `reverseAppend xs ys' is intended to be equal to `reverse xs ++ ys' )
13:33 <Cale> yeah
13:34 <WhereIsMySpoon> i need a better way to textualise <function> (x:xs) in my head
13:35 <WhereIsMySpoon> also why are you doing reverse’ (x:xs) with ys on the end
13:35 <WhereIsMySpoon> all the pattern matching ive seen doesnt have an extra bit on the end
13:35 <WhereIsMySpoon> its just <function> (x:xs) = <blah>
13:36 <LKoen> it"s a function of two arguments
13:36 <LKoen> (and the pattern matching is only on the first argument)
13:37 jathan_ joined
13:40 <WhereIsMySpoon> so <function> (x:xs) just means that we’re matching on the fact that the param is in the form of a head prepended to a tail, right?
13:40 <WhereIsMySpoon> i.e. some form of list
13:41 Iceland_jack joined
13:42 carlomagno joined
13:43 wei2912 joined
13:46 saussure joined
13:55 <Cale> WhereIsMySpoon: a nonempty list, specifically
13:55 <Cale> (sorry for disappearing for a bit)
13:55 saussure joined
13:57 <WhereIsMySpoon> Cale: right, thats waht i meant :)
13:57 blissdev joined
13:57 <WhereIsMySpoon> Cale: why are you writing like reverse’ [] ys = ys
13:57 <WhereIsMySpoon> and not reverse’ [] = []
13:58 <Cale> Well, we're writing a function which will take the list we want to reverse, and some other list, and what it's going to do is upend the first list onto the second
13:58 <Cale> You can imagine taking a deck of cards, and reversing its order by repeatedly taking the top card off and placing it into a new pile
13:59 <Cale> and then when the first pile is empty, the second pile is the resulting reversed deck
13:59 <LKoen> > let reverse [] = []
13:59 <LKoen> :t reverse
13:59 <lambdabot> <no location info>: error: not an expression: ‘let reverse [] = []’
13:59 <lambdabot> [a] -> [a]
13:59 <WhereIsMySpoon> please dont all pile in again
13:59 <LKoen> > let reverse' [] ys = ys
13:59 <Cale> haha
13:59 <LKoen> :t reverse'
13:59 <lambdabot> <no location info>: error:
13:59 <lambdabot> not an expression: ‘let reverse' [] ys = ys’
13:59 <WhereIsMySpoon> thats why we moved here
13:59 <lambdabot> error:
13:59 <lambdabot> • Variable not in scope: reverse'
13:59 <lambdabot> • Perhaps you meant one of these:
13:59 <Cale> LKoen: You can't define things one line at a time like that, it has to be all at once
13:59 <LKoen> oh
14:00 <WhereIsMySpoon> Cale: sure, thats fine
14:00 <WhereIsMySpoon> can you write out the whole function definition again
14:00 <WhereIsMySpoon> for your reverse
14:00 <WhereIsMySpoon> so i have it in front of me again
14:01 <LKoen> https://pastebin.com/crNGwxzM
14:02 <Cale> Which one did you want?
14:03 <Cale> reverse' [] = id
14:03 <Cale> reverse' (x:xs) = reverse' xs . (x:)
14:03 <WhereIsMySpoon> the other one
14:03 <Cale> reverse xs = reverse' xs []
14:03 <Cale> okay
14:03 <Cale> reverse' [] ys = ys
14:03 <Cale> reverse' (x:xs) ys = reverse' xs (x:ys)
14:04 <WhereIsMySpoon> so ‘the reverse of an empty list applied to ys is ys’
14:05 <WhereIsMySpoon> ‘the reverse of a non-empty list applied to ys is the reverse of the tail applied to the head, prepended to ys’
14:05 <WhereIsMySpoon> how do you ‘apply’ a list to something
14:05 <Cale> reverse' xs ys will reverse xs on to the beginning of the list ys
14:05 <Cale> The intention being that in the end, we'll define the usual reverse by setting ys to []
14:06 <Cale> reverse xs = reverse' xs []
14:06 <WhereIsMySpoon> =/
14:07 <WhereIsMySpoon> im confused
14:07 <Cale> So, reverse' [1,2,3] []
14:07 <Cale> = reverse' [2,3] [1]
14:07 <Cale> = reverse' [3] [2,1]
14:07 <Cale> = reverse' [] [3,2,1]
14:08 <Cale> = [3,2,1]
14:08 mb013619 joined
14:09 <WhereIsMySpoon> but you defined reverse’ [] ys
14:09 <WhereIsMySpoon> not reverse’ ys []
14:09 Big_G joined
14:11 juanpaucar joined
14:11 nobodyzxc joined
14:11 <Cale> Ah, maybe I should have used this notation:
14:11 <WhereIsMySpoon> not trying to be pedantic, im just confused
14:12 <Cale> reverse (1:(2:(3:[]))) []
14:12 <Cale> oops
14:12 <Cale> reverse' (1:(2:(3:[]))) []
14:12 <Cale> = reverse' (2:(3:[])) (1:[])
14:12 <Cale> = reverse' (3:[]) (2:(1:[]))
14:12 <Cale> = reverse' [] (3:(2:(1:[])))
14:12 juanpaucar joined
14:12 <Cale> = (3:(2:(1:[])))
14:13 <Cale> That's what it looks like without the list sugar
14:13 <Cale> We're matching on the first list, whether it's empty or not, to determine each step there
14:13 <Cale> If it's not empty, we basically move the element at the beginning of the first list, to the beginning of the second list.
14:16 Gurkenglas joined
14:16 <WhereIsMySpoon> ca
14:16 <WhereIsMySpoon> oops
14:16 <WhereIsMySpoon> Cale: so do i still pass one list to reverse’ ?
14:22 <Cale> no, you pass two
14:22 Xion__ joined
14:22 <Cale> and we define reverse in terms of reverse' by giving the empty list as the second list
14:22 <WhereIsMySpoon> ok that wasnt the requirement
14:22 <WhereIsMySpoon> sorry :P
14:23 <Cale> Right, we're solving a related problem first, in order to solve the original problem better.
14:23 <WhereIsMySpoon> oh ok
14:23 <sullyj3> hey, can someone point me to a good resource on forall? I have trouble understanding what it's for, and when it is/isn't required
14:23 Xion_ joined
14:23 <WhereIsMySpoon> ys will be the empty list then?
14:25 marmalod1 joined
14:27 <Cale> WhereIsMySpoon: initially
14:28 <raek> sullyj3: are you talking about cases such as "id :: a -> a" vs "id :: forall a. a -> a"?
14:28 <raek> the first one is a less explicit version of the second one
14:29 <raek> basically the "forall" part can be added at the outermost level and it means the same thing
14:30 <sullyj3> raek: I guess my question is, are there any cases where it adds new information?
14:30 <WhereIsMySpoon> Cale: i think i get what your function is doing, i dont really see why you need to define it so that it has to take an empty list to work, surely theres a better way to do it that doesnt
14:31 <Cale> WhereIsMySpoon: Well, we can then define the original reverse in terms of it
14:31 <raek> sullyj3: yes. but I'm no expert. I know that RankNTypes and existential types (?) use the forall keyword in special ways
14:31 <Cale> WhereIsMySpoon: and that won't need to take an empty list to start with
14:31 <WhereIsMySpoon> is there a way to define reverse’ so it doesnt need to take an empty list
14:31 <Cale> raek: that's right
14:31 <sullyj3> raek: thanks, googleable keywords are helpful
14:32 <raek> with rank n types, you can say things like, this function only accepts the polymorphic id function as an argument: "f :: (forall a. a -> a) -> Int"
14:33 <raek> it still means forall, but the difference is in who get's to decide what "a" means
14:33 <raek> I liked this tutorial for rank n types: https://ocharles.org.uk/blog/guest-posts/2014-12-18-rank-n-types.html
14:33 <Cale> WhereIsMySpoon: Well, I'm not sure that would make sense -- it *is* a function of two lists.
14:34 <sullyj3> raek: can you give an example of an implementation of f that would be an error?
14:34 <Cale> WhereIsMySpoon: and it basically upends the first list on to the second.
14:34 <WhereIsMySpoon> but surely the second list will always be empty
14:34 <WhereIsMySpoon> so why do you need to define it as a function of two lists when really its just of one
14:34 <Cale> WhereIsMySpoon: It won't though.
14:34 <WhereIsMySpoon> what
14:35 <raek> sullyj3: I actually borrow that example from the article. he explains it much better... :-)
14:35 <Cale> It's immediately going to become nonempty, so long as the first argument was nonempty
14:35 <Cale> Right?
14:35 <WhereIsMySpoon> thats an impl detai
14:35 <WhereIsMySpoon> l
14:35 <Cale> Look at the evaluation example I gave:
14:35 <Cale> reverse' [1,2,3] []
14:35 <Cale> = reverse' [2,3] [1]
14:35 <sullyj3> raek: i'll check it out, ta
14:35 <WhereIsMySpoon> at a high level, the requirement is that I reverse a list to give another list, reversed
14:35 <raek> sullyj3: here the "f" function can apply its argument to multiple types in its body
14:35 <WhereIsMySpoon> not that i give 2 lists, one being empty, and reverse the first onto the second
14:36 <raek> so I cannot pass a String -> String function to f. I must pass a polymorphic function.
14:37 <raek> "f :: forall a. (a -> a) -> Int" means that I, the caller of f, gets to decide what "a" is. f cannot choose and cannot assume anything about the type "a".
14:37 <Cale> WhereIsMySpoon: Yeah, so the thing is, this reverse' solves a problem which is strictly more general than the original problem, so we can define the thing we wanted originally in terms of it.
14:37 <Cale> WhereIsMySpoon: i.e. reverse xs = reverse' xs []
14:37 <Cale> and then we have a function of a single argument again
14:37 <WhereIsMySpoon> huh
14:37 <WhereIsMySpoon> how is reverse’ solving a more general problem
14:37 <raek> are there any more usages of the forall keyword than rank n types and existential types?
14:38 chlong joined
14:38 <raek> I'm curious too... :-)
14:38 <Cale> Well, reversing a list is a special case of reversing one list on to the start of another list
14:38 <Cale> Where we pick the second list to be empty.
14:38 <sullyj3> raek: oh, that's pretty cool! thanks!
14:39 <Cale> raek: Well, you can also just use it to explicitly quantify type variables, ScopedTypeVariables will make those variables you quantify explicitly scope over the rest of the definition (so they can be used in type signatures in a where clause, or elsewhere)
14:39 <WhereIsMySpoon> Cale: hm..ok
14:40 <raek> it can be used for all sorts of exciting things. I like how it is used in the ST monad to ensure that the intermediate state is never leaked (so that the operations can be implemented as in-place mutation).
14:40 <Cale> WhereIsMySpoon: But to be honest, this is part of the reason why I like to think about this a little bit differently
14:40 <raek> s/it/rank n types/
14:41 <WhereIsMySpoon> Cale: how so
14:41 yellowj joined
14:41 <Cale> WhereIsMySpoon: and instead, regard functions of lists as being a sort of list-like type in themselves, if we restrict ourselves to working with functions which add elements to the beginning of another list
14:43 <Cale> The difference being that there is a faster way to "concatenate" two functions of type [a] -> [a] than there is to concatenate a pair of lists of type [a]
14:43 <Cale> So, just to reiterate that,
14:43 <WhereIsMySpoon> Cale: the functions have to evaluate some time though
14:43 <Cale> sure
14:43 <WhereIsMySpoon> so eventually it will be concatenating a pair of lists
14:44 <Cale> But when they do, xs ++ ys will take O(length xs) time, but f . g will take O(1) time.
14:44 <WhereIsMySpoon> i dont understand this
14:44 <WhereIsMySpoon> f.g needs to be evaluated
14:44 <Cale> sure, but it evaluates in a single step -- (.) isn't recursive
14:44 <WhereIsMySpoon> how can the evaluation of some functions that will do the same thing take less time than doing it
14:44 <Cale> (f . g) x = f (g x)
14:45 <Cale> This rewrite happens, it takes *some* time, but that amount of time is always the same.
14:45 <Cale> Regardless of what the functions are.
14:45 <WhereIsMySpoon> sorry, not understanding
14:45 <Cale> Or you could write that as f . g = \x -> f (g x)
14:45 <Cale> if you prefer
14:45 <WhereIsMySpoon> that doenst help
14:45 <Cale> So, let's try it
14:45 <WhereIsMySpoon> i dont know what \x means
14:45 <Cale> oh, that's a lambda
14:46 <WhereIsMySpoon> oh right
14:46 <Cale> (\x -> expr) is the function which, given x, produces the result expr
14:46 <Cale> So f . g is the function which given some x, will produce the result f (g x)
14:47 <Cale> It takes a constant amount of time to construct this function in memory, independently of what our two functions were.
14:47 <WhereIsMySpoon> so does (f.g)x = f $ g x ?
14:47 <Cale> yes
14:47 <WhereIsMySpoon> right
14:47 <WhereIsMySpoon> but ++ is one function
14:47 <WhereIsMySpoon> not two
14:48 <Cale> ++ takes two lists
14:48 <WhereIsMySpoon> sure
14:48 <Cale> and we're turning those lists into functions, and (++) into (.)
14:48 <Cale> instead of computing
14:48 <Cale> > [1,2,3] ++ [4]
14:48 <lambdabot> [1,2,3,4]
14:48 <Cale> we could always compute
14:48 <Cale> > ([1,2,3]++) . (4:) $ []
14:48 <lambdabot> [1,2,3,4]
14:49 <Cale> Now, here we still end up doing the same thing -- (++) got involved there.
14:49 <WhereIsMySpoon> > ([1,2,3] . ++) 4
14:49 <lambdabot> <hint>:1:12: error: parse error on input ‘++’
14:49 <Cale> So on its own, that wouldn't be advantageous.
14:49 <WhereIsMySpoon> > ([1,2,3] . ++) [4]
14:49 <lambdabot> <hint>:1:12: error: parse error on input ‘++’
14:49 <Cale> But the point is, we can get away with nothing but (.) and (x:) and id
14:50 <WhereIsMySpoon> oh wait, a list isnt a function
14:50 aarvar joined
14:50 <Cale> right, not directly
14:50 <WhereIsMySpoon> :t (4:)
14:50 <lambdabot> Num a => [a] -> [a]
14:51 <Cale> But we can always replace a list of type [a] with the function [a] -> [a] that adds its elements to the beginning of another list
14:51 <WhereIsMySpoon> :t ([1,2,3]++) . (4:)
14:51 <lambdabot> Num a => [a] -> [a]
14:51 <Cale> and the point is that this new representation has a fast concatenation operation -- which is composition
14:51 romank joined
14:52 <Cale> and we can get back to a simple list in the end by applying our final function [a] -> [a] to the empty list
14:52 uglyfigurine joined
14:52 <WhereIsMySpoon> > ([1,2,3]++) . (4:)
14:52 <lambdabot> <[Integer] -> [Integer]>
14:52 <WhereIsMySpoon> right..thats a function
14:53 <WhereIsMySpoon> i am reading, just trying to understand
14:53 <Cale> yeah
14:53 <WhereIsMySpoon> > (([1,2,3]++) . (4:)) []
14:53 <lambdabot> [1,2,3,4]
14:54 <WhereIsMySpoon> ok
14:54 <Cale> So if the identity function id is analogous to the empty list
14:54 <Cale> and (x:) is analogous to [x]
14:54 <Cale> and (.) is analogous to (++)
14:54 <Cale> we can take the naive reverse you wrote:
14:54 <Cale> reverse [] = []
14:55 <Cale> reverse (x:xs) = reverse xs ++ [x]
14:55 <Cale> and, on the right hand side, replace [] by id, [x] by (x:) and (++) by (.)
14:55 <Cale> reverse' [] = id
14:55 <WhereIsMySpoon> does ‘id’ have some special meaning
14:55 nickolay joined
14:55 <Cale> reverse' (x:xs) = reverse' xs . (x:)
14:55 <Cale> id x = x
14:55 <WhereIsMySpoon> > id 2
14:55 <lambdabot> 2
14:55 <Cale> it's the identity function
14:56 <WhereIsMySpoon> > id Bool
14:56 <lambdabot> error:
14:56 <lambdabot> • Data constructor not in scope: Bool
14:56 <lambdabot> • Perhaps you meant variable ‘bool’ (imported from Data.Bool)
14:56 <Cale> > id True
14:56 <lambdabot> True
14:56 <WhereIsMySpoon> > id [1,2,3]
14:56 <lambdabot> [1,2,3]
14:56 <sullyj3> :k id
14:56 <lambdabot> error: Not in scope: type variable ‘id’
14:56 <WhereIsMySpoon> dafuq is it doing
14:56 <Cale> :t id
14:56 <lambdabot> a -> a
14:56 <WhereIsMySpoon> @src id
14:56 <lambdabot> id x = x
14:56 <WhereIsMySpoon> oh
14:56 <Cale> I gave the source already :)
14:56 <Cale> It's pretty short, so perhaps you missed it
14:57 <WhereIsMySpoon> im having trouble with that first bit
14:57 <WhereIsMySpoon> the identity function id === []
14:57 <Cale> So, as a function on lists, id just leaves the list alone, that is, it doesn't add any elements to it
14:57 <WhereIsMySpoon> right
14:58 <Cale> We're replacing lists with functions that just add the elements we would have had to the beginning of another list
14:58 <Cale> So the empty list turns into the identity function
14:58 <WhereIsMySpoon> ok
14:59 <Cale> The singleton list [x] turns into the function (x:) which adds x to the beginning of any other list
14:59 <Cale> and concatenation of lists turns into composition of functions
14:59 <Cale> We can also use this trick to get efficient tree traversals, if we care to define a type of binary trees or something
15:00 <Cale> e.g. if we have data BinTree = Tip | Branch (BinTree a) a (BinTree a)
15:00 <WhereIsMySpoon> Cale: reverse' [] = id
15:00 <WhereIsMySpoon> Cale: reverse' (x:xs) = reverse' xs . (x:)
15:00 <WhereIsMySpoon> so
15:00 <WhereIsMySpoon> if we unwrap this
15:00 <Cale> okay
15:02 <WhereIsMySpoon> because of the way that stack unwinding goes bottom up with the recursion, we end up with the head x at the bottom of the stack?
15:02 <Cale> Let's just evaluate it by following the equations
15:02 <Cale> (in the actual details, Haskell implementations don't tend to have a call stack, they're a little weirder than that)
15:02 <Cale> reverse' [1,2,3]
15:03 <Cale> = reverse' [2,3] . (1:)
15:03 <WhereIsMySpoon> you missed the empty list
15:03 <Cale> yeah, I'm computing a function
15:03 <WhereIsMySpoon> right
15:03 Gigi joined
15:03 <WhereIsMySpoon> ok
15:03 <Gigi> hey
15:03 seangrove joined
15:03 <Cale> = (reverse' [3] . (2:)) . (1:)
15:03 <Gigi> i'm trying to install stack but it doesnt seem to work
15:04 <Cale> = ((reverse' [] . (3:)) . (2:)) . (1:)
15:04 <WhereIsMySpoon> i see
15:04 <WhereIsMySpoon> then [] gets applied
15:04 <Cale> = ((id . (3:)) . (2:)) . (1:)
15:04 <Cale> yeah
15:04 <WhereIsMySpoon> and its 3:2:1:[]
15:04 <Cale> yep
15:04 <WhereIsMySpoon> i see, this actually now seems very similar to my way
15:05 <WhereIsMySpoon> except instead of computing ++, you’re composing functions
15:05 <Cale> yeah!
15:05 <WhereIsMySpoon> i see, and because composing functions is much faster than actually computing it each time, its much faster when theyr eput together?
15:05 <Cale> yeah
15:05 <WhereIsMySpoon> christ
15:05 <WhereIsMySpoon> k done
15:05 <Cale> It ends up taking linear time overall, rather than quadratic
15:05 <WhereIsMySpoon> never again
15:06 <WhereIsMySpoon> pls
15:06 <WhereIsMySpoon> :P
15:06 <Cale> haha
15:06 dni- joined
15:06 <Cale> Well, now that we have this hammer, might as well find some nails
15:06 <WhereIsMySpoon> :P
15:06 <WhereIsMySpoon> i will try to keep it in mind
15:06 <ski> left-associating `++' is inefficient. left-associating `.' isn't
15:07 <Cale> Back when I started working for a company in 2009 that was working on an action RPG in Haskell, their map editor was using way too much memory and time baking the final resource file.
15:07 <WhereIsMySpoon> maybe you could suggest some simple problems to solve using function composition instead of naive computation?
15:07 <Cale> I saw that it was basically doing a whole lot of concatenation of ByteStrings
15:07 <Cale> and so before really taking the time to understand exactly why it was slow, I tried replacing those with functions ByteString -> ByteString
15:07 <Cale> in the same way we just did
15:08 <WhereIsMySpoon> heh
15:08 <WhereIsMySpoon> cool :)
15:08 <Cale> it went from requiring several GB of memory and 30 minutes, to a few MB and 5 seconds.
15:08 <Akii> wow
15:08 <* ski> . o O ( `Endo' )
15:08 <Cale> yep
15:09 <Cale> Now there's Builder, which is effectively a fancier version of this same trick (with some other tricks mixed in)
15:09 <Akii> I just thought about "I bet this is a concept; I bet they also use that when implementing foldr"
15:10 <Cale> WhereIsMySpoon: another good example is tree traversals
15:10 <Cale> data Tree a = Tip | Branch (Tree a) a (Tree a)
15:10 <Cale> Suppose we have this binary tree data type
15:11 <Cale> If we write the standard in-order traversal:
15:11 <Cale> inorder Tip = []
15:11 <Cale> inorder (Branch l x r) = inorder l ++ [x] ++ inorder r
15:11 <Cale> this suffers from exactly the same problem as reverse
15:11 <Cale> and the solution is exactly the same too
15:11 <Cale> inorder' Tip = id
15:12 <Cale> inorder' (Branch l x r) = inorder' l . (x:) . inorder' r
15:12 <Akii> http://hackage.haskell.org/package/base-
15:12 <Cale> inorder t = inorder' t []
15:13 <Cale> Basically, any time you're building up a list by doing a bunch of recursive concatenation of other lists, this is likely to be a handy thing to do to get better performance.
15:13 <ski> (note that it was the first recursive call of `inorder', to the left of `++', that was problematic. the second was not a problem)
15:13 <Cale> right
15:13 <Cale> er
15:13 <Cale> yeah, if that list is long, it will be problematic
15:14 im0nde joined
15:14 <ski> if you see `foo ... = foo ... ++ ...', then this should ring a bell that you're probably doing something inefficient
15:16 <WhereIsMySpoon> Cale: sorry youve lost me again with that data Tree a = ….
15:16 <WhereIsMySpoon> i think im done being fried today anyway
15:16 colt44 joined
15:16 <WhereIsMySpoon> thanks
15:16 <Cale> ah, that's a definition of a binary tree data type
15:16 <WhereIsMySpoon> lets leave it here
15:16 <Cale> but yeah, if you're unfamiliar, save it for later :)
15:16 <WhereIsMySpoon> i have less than a days worth of haskell
15:16 <WhereIsMySpoon> :)
15:17 <Akii> 1.5 years into and can hardly follow
15:17 <Akii> foldl f z t = appEndo (getDual (foldMap (Dual . Endo . flip f) t)) z
15:17 <Cale> haha
15:17 <Akii> is this the same concept?
15:17 <Cale> yeah, roughly
15:18 <Cale> We could be more direct about that...
15:18 <Akii> cool, now I know what to look at next
15:20 mengu joined
15:26 <Cale> @let myFoldl f z xs = foldr (\y ys a -> ys (f a y)) id xs z -- Akii
15:26 <lambdabot> Defined.
15:26 <Cale> Note there that ys is not actually a list, but rather the function we obtain by folding over the remainder of the list
15:26 netheranthem joined
15:26 <Cale> and a is effectively an accumulated state
15:27 <Akii> (I've to go soon, back later tho)
15:31 <Akii> yep interesting
15:31 cschneid_ joined
15:36 conal joined
15:36 netheranthem joined
15:40 lewis joined
15:52 galderz joined
15:53 <Guest65850> how do i create a new file ?
15:56 <Iceland_jack> :t writeFile
15:56 <Iceland_jack> https://hackage.haskell.org/package/base-
15:56 <lambdabot> FilePath -> String -> IO ()
15:56 <Iceland_jack> :t writeFile "/tmp/empty.txt"
15:56 <lambdabot> String -> IO ()
15:56 <Iceland_jack> :t writeFile "/tmp/empty.txt" ""
15:56 <lambdabot> IO ()
15:58 acarrico joined
16:08 <Guest65850> Directory /Users/me/my-project/ already exists. Aborting.
16:08 <Guest65850> why does it do this
16:08 <Guest65850> how do I access that again or delete ?
16:16 uglyfigu_ joined
16:20 uglyfigurine joined
16:22 mengu joined
16:23 nibble joined
16:24 fotonzade joined
16:24 <srhb> Guest65850: What arguments did you give writeFile exactly?
16:24 <srhb> Guest65850: And you can delete it from your terminal. if it's empty, use rmdir /Users/me/my-project
16:29 juanpaucar joined
16:31 kadoban joined
16:33 <Guest65850> srnb i copy and pasted it in
16:34 <Guest65850> but it gives me command not found
16:34 <srhb> Guest65850: What did you copy paste into where?
16:34 <Guest65850> i have no idea how it works :D i just managed to download stack
16:34 <Guest65850> in the terminal
16:34 <srhb> Guest65850: And what did you paste into the terminal?
16:35 <Guest65850> :t writeFile "/tmp/empty.txt"
16:35 <lambdabot> String -> IO ()
16:35 <srhb> Guest65850: Assuming your terminal is just running your shell (bash, perhaps?) that won't work. It's a ghci command.
16:35 <Guest65850> String -> IO () -bash: syntax error near unexpected token `('
16:35 <srhb> Right.
16:35 <Guest65850> ok
16:35 <srhb> You need to run ghci for that to work.
16:35 <Guest65850> ok
16:36 <Guest65850> stack ghci
16:36 <Guest65850> right?
16:36 <srhb> Guest65850: Let me check, I don't use stack personally.
16:36 <srhb> Yes, that looks like it will work.
16:37 <Guest65850> ok it just echos it
16:37 <srhb> echos what?
16:37 <Guest65850> :t writeFile "/tmp/empty.txt"
16:37 <lambdabot> String -> IO ()
16:37 <Guest65850> and also
16:37 <Guest65850> String -> IO ()
16:37 <srhb> Yes, :t is short for :type and it tells you the type of the following expression
16:38 <Guest65850> oh
16:38 <srhb> If you want to create the file, type in `writeFile "/tmp/empty.txt" ""` without the outer quotes
16:38 <Guest65850> <interactive>:3:1: error: • No instance for (Show (String -> IO ())) arising from a use of ‘print’ (maybe you haven't applied a function to enough arguments?) • In a stmt of an interactive GHCi command: print it
16:38 juanpaucar joined
16:38 <Guest65850> ok
16:39 <Guest65850> Variable not in scope: txt :: FilePath -> b0
16:39 WhereIsMySpoon joined
16:39 WhereIsMySpoon joined
16:39 <srhb> What did you type in now?
16:39 <Guest65850> writeFile /tmp/empty.txt
16:40 <srhb> Only remove the outer quotes
16:40 <srhb> verbatim, the following:
16:40 <srhb> writeFile "/tmp/empty.txt" ""
16:40 <srhb> Meaning, write to the file /tmp/empty.txt the contents empty string
16:40 <Guest65850> ok that doesnt return anything
16:40 <srhb> Then all is good
16:41 <Guest65850> thank you :)
16:41 <srhb> By the way, be careful with that command
16:41 <srhb> Or function, rather
16:41 <srhb> If you tell it to write anything to any existing file, it will happily overwrite whatever you have permissions to.
16:42 mattyw joined
16:42 juanpaucar joined
16:42 <Guest65850> okay, i'll try to be
16:43 <Guest65850> not that i really know what i'm doing anyways
16:43 <srhb> Guest65850: Experimenting is great, just wanted to make sure you knew the risks :D
16:43 juanpaucar joined
16:44 <Guest65850> so now i still didnt create a file, or did i?
16:44 <srhb> You did :)
16:45 <Guest65850> if so, what is it called and how could i access it
16:45 <srhb> It's in /tmp and it's called empty.txt
16:45 <srhb> You could check via a terminal (that is just running your shell, not ghci) by typing ls /tmp
16:45 <Guest65850> ok so if i put in :load empty.txt
16:45 <Guest65850> it will come up
16:46 <srhb> Guest65850: No, :load tells ghci to load a Haskell source file (or module.)
16:46 <srhb> And it's neither (it's an empty file)
16:46 grdryn joined
16:47 <srhb> If you wanted to create a Haskell source file, its name should end in .hs
16:47 <Guest65850> ok so i could put in putStrLn "hello world"
16:47 <Guest65850> would it still be empty?
16:47 <srhb> put in what where?
16:47 <srhb> In that same file?
16:47 <Guest65850> yes?
16:48 <Guest65850> by the sounds of it i shouldnt :D
16:48 <srhb> You still need it to be named .hs in order to use it as a Haskell source file
16:48 <Guest65850> yes how do i do that
16:48 <srhb> And you wouldn't normally write Haskell source code through ghci like this
16:48 aarvar left
16:48 <srhb> Do you have a text editor of choice?
16:48 <Guest65850> yes
16:48 <srhb> And I do mean *text* - not a word processor or anything like that.
16:49 <srhb> Well, using a text editor you can create a Haskell source file anywhere (in a location that you know) and you can load it in ghci with the command `ghci /path/to/file` in your terminal
16:50 <srhb> I should say /path/to/file.hs :-)
16:55 dni- joined
16:55 WhereIsMySpoon joined
16:55 WhereIsMySpoon joined
16:57 pilne joined
17:00 iAmerikan joined
17:16 eacameron joined
17:23 mengu joined
17:28 <Guest65850> @srnb ok i made a file in atom
17:28 <lambdabot> Source not found. Where did you learn to type?
17:28 <Guest65850> @srhb ok i made a file in atom
17:28 <lambdabot> Source not found. Maybe if you used more than just two fingers...
17:28 juanpaucar joined
17:29 <srhb> Guest65850: @ activates lambdabot, just write srhb: to highlight me :)
17:29 <srhb> Guest65850: And good!
17:29 <Guest65850> kk :)
17:29 <srhb> Guest65850: Did you name it something ending in .hs and save it somewhere you know?
17:30 <Guest65850> yes
17:31 <srhb> Guest65850: Great! Then I suppose stack ghci /thatpath/yourfile.hs should work, if it's a valid Haskell source file :)
17:32 <Guest65850> i'm guessing "yourfile.hs" is the what i named it
17:32 <srhb> Guest65850: Yes, and /thatpath/ is the path to the directory you saved it in.
17:32 <Guest65850> but to i change the value "thatpath" to anything , or does that just stay
17:32 <Guest65850> ok
17:35 <Guest65850> File does not exist or is not a regular file
17:36 <lewis> > map(*2) [1..5]
17:36 <lambdabot> [2,4,6,8,10]
17:39 <srhb> Guest65850: What did you type in exactly?
17:40 <Guest65850> path/Users/jill/Desktop/myfirst.hs
17:40 <srhb> Guest65850: It's always helpful if you include that. :)
17:40 <srhb> Guest65850: You probably meant /Users/jill/Desktop/myfirst.hs
17:40 <srhb> Guest65850: On a unix-like filesystem, / (or "root") is the path under which *all* directories and files live. There's nothing "above" that.
17:40 <Guest65850> <interactive>:2:1: error: parse error on input ‘/’
17:41 <Guest65850> gives me that
17:41 <srhb> Try :load
17:41 <srhb> Before the path :)
17:42 <Guest65850> [1 of 1] Compiling Main ( /Users/jill/Desktop/myfirst.hs, interpreted ) Ok, modules loaded: Main. *Main>
17:42 <srhb> Wonderful :)
17:42 <Guest65850> yay
17:43 texasmynsted joined
17:43 <srhb> So now if you have a definition in the file, you can refer to it by name to ask for its type, evaluate it and whatnot.
17:43 <srhb> And you can use :reload or :r to reload the file once you've made changes.
17:44 <Guest65850> ok :)
17:44 <Guest65850> thanks so much for your help
17:45 uglyfigurine joined
17:45 <srhb> You're very welcome. Hope you have happy haskell hadventures.
17:49 mengu joined
18:00 peterbecich joined
18:00 kaychaks joined
18:04 juanpaucar joined
18:05 juanpaucar joined
18:06 juanpauc_ joined
18:12 <mb013619> so i did a 'cabal install ghc-mod', my PATH includes '~/.cabal/bin', i can run ghc-mod from the terminal, but 'which ghc-mod' returns 0
18:12 <mb013619> any ideas? i'm stumped
18:12 <mb013619> no aliases
18:14 <MarcelineVQ> did you do the install in a sandbox?
18:14 <mlehmk> try command -v instead of which
18:14 halogenandtoast joined
18:17 <geekosaur> if $PATH includes *literal* ~/.cabal/bin then it likely won't work right
18:17 <mb013619> MarcelineVQ: maybe
18:17 <geekosaur> use $HOME instead when setting it (and no single quotes or you prevent either one from being expanded and things go wrong)
18:19 <mb013619> geekosaur: sure, but ~/bin in $PATH works, so ~/.cabal/bin should as well, i'll change it out, but if i can run it then 'which' should not return 0
18:22 <mb013619> geekosaur: well it worked... ¯\_(ツ)_/¯
18:22 <mb013619> thx
18:22 NoCreativity joined
18:23 <geekosaur> bash in particular is weird about when it does ~
18:24 romank joined
18:24 <geekosaur> ...but, even if bash sometimes handles it, other programs will not, leading to things being found by bash but not other programs
18:25 <geekosaur> it's best to avoid the issue rather than get surprised by weird behavior
18:25 ubsan joined
18:26 iAmerikan joined
18:26 <mb013619> yeah, i've seen problems with it before, especially since Mac OSX is weird with path case sensitivity
18:33 erisco joined
18:35 saussure joined
18:36 diegs_ joined
18:44 dni- joined
18:49 juanpaucar joined
18:49 peterbecich joined
18:49 saussure joined
18:56 juanpaucar joined
19:08 mengu joined
19:14 lewis joined
19:14 brailsmt joined
19:22 tusj joined
19:25 iAmerikan joined
19:30 peterbec` joined
19:36 brailsmt joined
19:46 uglyfigurine joined
19:48 uglyfigurine joined
19:49 takle_ joined
19:51 govg joined
19:59 diegs_ joined
20:02 patbecich joined
20:02 patbecic` joined
20:11 juanpaucar joined
20:11 ralu joined
20:13 peterbec` joined
20:16 tusj joined
20:23 uglyfigurine joined
20:27 herr_jth joined
20:28 herr_jth joined
20:28 romank joined
20:30 herr_jth joined
20:33 dni- joined
20:33 juanpaucar joined
20:40 a3f joined
20:40 a3f joined
20:40 acarrico joined
20:49 eHammarstrom joined
20:51 im0nde joined
20:51 <eHammarstrom> Hello, I am wondering if there is a prettier base case for this function http://lpaste.net/355820
20:52 <kadoban> eHammarstrom: Seems fine. What do you mean prettier?
20:53 <eHammarstrom> It just didn't _feel_ very haskell, but I am not familiar with haskell yet.
20:55 <kadoban> Well, normally you'd write this function using other primitives (one of the folds for instance), or just use ``product`` that already exists in base, but other than that it looks fairly fine. The third line could end: = x * lsProduct xs , the parens aren't necessary, but other than that.
20:57 <eHammarstrom> I see, the functional way is new to me. I assume I will stumble upon folding soon, reading Programming in Haskell and doing the exercises / experimenting
21:00 <kadoban> Yeah, it's something you're bound to run into eventually. In short, folds are a slightly more structured way to do many kinds of recursion.
21:06 <thang1> eHammarstrom: lsProduct should be equivalent to "foldr (*) 1"
21:06 <thang1> @let lsProduct [] = 1; lsProduct (x:xs) = x * (lsProduct xs)
21:06 <lambdabot> Defined.
21:06 <thang1> lsProduct [1..10]
21:06 <thang1> > lsProduct [1..10]
21:06 <lambdabot> 3628800
21:07 <thang1> > foldr (*) 1 [1..10]
21:07 <lambdabot> 3628800
21:07 <thang1> eHammarstrom: is that elegant enough for you? :p
21:08 <eHammarstrom> Looks nice, I'll get there ;)
21:11 zero_byte joined
21:12 <thang1> The intuition behind "folds" is that you have some data structure (we'll pick lists), and you want to operate on that data structure in a way that "folds" it into some single answer
21:12 <thang1> So in the case of product, you have a * b = c (you take two numbers and fold it into one answer), and you want to repeatedly fold a data structure using some operatio in order to find a global property of the data structure
21:12 <eHammarstrom> So, it's like the Clojure equivalent of apply?
21:13 <thang1> Pretty much. Unless I'm horribly misremembering what apply does :p
21:14 <thang1> The cool part about folds is that people figured out that you do this sort of thing so often, it was abstracted into a "fold" command rather than explicit recursion. The even cooler part is that eventually people figured out you can fold an arbritrary data structure as long as you can traverse it in a defined way
21:14 <thang1> (example: in order traversal of binary tree)
21:14 <eHammarstrom> (apply max [1 2 3]) = (max (max (max 1) 2) 3)
21:14 <thang1> ah yup that's foldr
21:15 <eHammarstrom> I am really interested in the theory of haskell, and I assume the programming books don't teach this. Can you recommend any literature?
21:15 <thang1> foldl is (max 1 (max 2 (max 3))) iirc (it's left associative instead of right associative)
21:16 <eHammarstrom> I see
21:16 <thang1> theory of haskell? like this sort of fold concept and how haskell has generic concepts for things?
21:16 <kadoban> What sort of theory?
21:16 <thang1> Haskell has its own theory but it generally pertains to Haskell specific things like how the compiler works (laziness, strictness, how the compiler interprets things, yadda yadda).
21:17 <thang1> Haskell borrows tons of theory from things like category theory, functional programming in general, and research people have done into programming language design (especially with types)
21:17 dxld joined
21:18 <thang1> That being said, a lot of the knowledge that I have of haskell (I'd say 90% or so) I've gotten from the "Haskell From First Principles" book
21:18 <thang1> Chapter 1 is lambda calculus (which is the theoretical underpinning of haskell. There is nothing in haskell that can't be written out by hand as lambda calculus). Chapters 2-31ish go over damn near everything you ever wanted to know about haskell and functional programming :p
21:19 <eHammarstrom> Theory of haskell might've been a bad wording, theory behind haskell. But yes, category theory seems interesting. I do like math but I haven't really seen a language being based on it in a literal way
21:19 <eHammarstrom> I've read the Lambda Calculus chapter of that book
21:20 <kadoban> Haskell just borrows a couple of ideas from category theory. I wouldn't personally say it's based on it.
21:20 <thang1> Right, which is why I said it borrows a lot of theory :p
21:20 <thang1> https://wiki.haskell.org/Hask -- That being said...
21:21 <thang1> Of course, the obvious rebuttal to that is this: http://math.andrej.com/2016/08/06/hask-is-not-a-category/
21:21 <eHammarstrom> I do not get why I have not stumbled upon category theory at Uni yet, is it not well established? Maybe it is too specific of a maths area?
21:22 <thang1> No it's really that universities don't teach it for shit. It never ceases to bug me. I'm even at a university that's got a fairly strong haskell and fp presence and nobody teaches category theory here
21:23 <eHammarstrom> I'll have a FP course in haskell next year this time of the year. That is far to distant for my current interest
21:23 <thang1> It's an axiomatic foundation for mathematics that's differnt than set theory and is useful for different things
21:24 <thang1> A lot of unis tend to shy away from category theory because you don't really /use/ it for a lot of stuff in math. Like at least with real or complex analysis you're gonna use that stuff constantly in your following math classes. Category theory is just kinda something you learn and then all the sudden halfway through your masters you start using it and seeing it everywhere
21:25 <eHammarstrom> I see, starting my masters in September
21:26 <thang1> (even computer science barely uses it heavily unless you're doing some deep PhD kinda research into type theories or applications of category theory into programming. It's sort of orthogonal to turing completness and computation in general so it doesn't really get talked about in the same way)
21:26 <thang1> You doing your masters in CS?
21:27 <Cale> I'm not sure I'd casually refer to category theory as an axiomatic foundation for mathematics. It has a very different flavour than that usually. There are axiomatic foundations for mathematics based upon it...
21:28 <thang1> You're right, I'm being sloppy with that. M'bad :p
21:29 <eHammarstrom> So, it all works a bit different here in Sweden. We apply for 5 years directly so I will get a M.Sc. in Engineering, Information and Communication Engineering Technologies (ICT I guess) but my masters is in CS but my B.Sc. is in ICT
21:29 <thang1> ahh got it, that makes sense
21:29 <eHammarstrom> So yes, pure CS masters, but not officially because of the system?
21:30 <eHammarstrom> Does not make a lot of sense to me :)
21:30 <Cale> It's more often regarded as an overarching superstructure which various branches of mathematics can be fit into, but I usually like to think of it as simply a sibling to things like group theory -- it's the study of a particular sort of algebraic structures, of which there are many instances throughout mathematics.
21:30 fotonzade joined
21:31 <thang1> That's how I like to think of it too (although I've never concretly seen it stated like that). it makes the most sense to me that way :p
21:36 <colt44> kadoban: what do you mean by "folds are a slightly more structured way to do many kinds of recursion"?
21:37 romank joined
21:38 <thang1> basically what I explained. Any time you want to get a singular answer or global property out of a data structure you can use a fold.
21:40 <thang1> "what's the sum of everything in the data structure?" => fold (+). "What's the product of everything in the data structure?" => fold (*). "does this element 'e' exist in a data structure?" => fold ("true if 'e' matches, otherwise keep folding)
21:40 <kadoban> colt44: http://www.cs.nott.ac.uk/~pszgmh/fold.pdf explains it better than I'll be able to
21:42 <colt44> kadoban: I know the paper. I thought you could have meant something different. Just wanted to be sure I wasn't missing anything :)
21:43 takle joined
21:43 <kadoban> Ah, naw I'm not that clever :)
21:46 <eHammarstrom> kadoban: thanks for the paper!
21:46 juanpaucar joined
21:47 <kadoban> It's quite a good one, enjoy. Though personally it took me quite a while to understand most of it.
21:48 juanpaucar joined
21:53 hiratara joined
21:55 <Bare> Is there a reason you wouldn't map elem 'e' instead of folding in that example?
21:56 saussure joined
21:56 <eHammarstrom> Is it preferred to use 4 space or 8 space tabs in Haskell?
21:56 <geekosaur> 2 or 4 would be common. 8's too big, and in general we avoid tabs anyway
21:57 <geekosaur> because the compiler expects a tab stop to be a multiple of 8 columns always, and editors often don't agree
21:57 <thang1> Bare: map would give you a list of [False, False, False, False, ... True, ... False, False...]
21:57 <Cale> Essentially everyone uses spaces (at least if they ever plan on collaborating with others), and usually 2 spaces are enough as indentation, but whatever looks good.
21:57 <eHammarstrom> geekosaur, yes I was wondering because I wanted to convert tab to x spaces. Using 4 atm
21:57 <Bare> Ah that's true, I was thinking of just a string
21:57 romank joined
21:58 <Cale> I don't really pay attention to it so much -- so long as things line up in a way which works.
21:58 <thang1> With elem you just care whether or not something exists in the data structure; it's a "global property" of the data structure, hence a fold :p
21:58 saussure joined
21:58 <eHammarstrom> Cale: I see
21:58 <thang1> In fact, even with a string, since you work "characterwise" with strings, you would still get a list of [True, False, False, ...] with a string using elem if it was done with map instead of fold
21:58 <Cale> You should configure your editor to expand tabs immediately -- I like setting it on 2 spaces just so it's like a faster spacebar and I can get anywhere I need to be a bit quicker.
21:59 takle joined
21:59 nullcone joined
21:59 <eHammarstrom> Cale: yeah, I set it to 4 spaces
21:59 <Cale> (It matters how things line up vertically, but not so much how much things are indented)
22:01 juanpaucar joined
22:02 <Bare> Wouldn't that result require several strings?
22:04 <geekosaur> @src String
22:04 <lambdabot> type String = [Char]
22:09 saussure joined
22:10 juanpaucar joined
22:22 dni- joined
22:24 mjora7 joined
22:25 saussure joined
22:27 im0nde_ joined
22:31 hiratara joined
22:33 texasmynsted joined
22:39 takle joined
22:40 lewis joined
22:41 mjora7 left
22:43 saussure joined
22:52 louispan joined
22:53 saussure joined
22:58 mengu joined
23:09 louispan joined
23:11 saussure joined
23:14 juanpaucar joined
23:18 juanpaucar joined
23:23 juanpaucar joined
23:24 juanpaucar joined
23:25 juanpaucar joined
23:25 juanpaucar joined
23:29 saussure joined
23:31 saussure joined
23:38 saussure joined
23:41 prophile joined
23:44 prophile joined
23:48 saussure joined
23:50 aarvar joined
23:52 halogenandtoast joined
23:54 acarrico joined
23:56 mr_sm1th joined
23:57 cschneid_ joined
23:57 saussure joined