Home liberachat/#haskell: Logs Calendar

Logs on 2022-09-24 (liberachat/#haskell)

00:00:04 × harveypwca quits (~harveypwc@2601:246:c180:a570:3828:d8:e523:3f67) (Quit: Leaving)
00:01:34 nate2 joins (~nate@98.45.169.16)
00:04:52 × berberman_ quits (~berberman@user/berberman) (Ping timeout: 246 seconds)
00:04:54 berberman joins (~berberman@user/berberman)
00:08:20 × Enrico63 quits (~Enrico63@81.109.143.226) (Ping timeout: 252 seconds)
00:08:20 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 244 seconds)
00:08:22 × chomwitt quits (~chomwitt@2a02:587:dc14:f500:a8f6:62e0:a0fa:7808) (Ping timeout: 246 seconds)
00:09:13 EashanHatti parts (~Thunderbi@c-24-126-44-70.hsd1.wv.comcast.net) ()
00:11:48 × waleee quits (~waleee@2001:9b0:213:7200:cc36:a556:b1e8:b340) (Ping timeout: 264 seconds)
00:14:48 × son0p quits (~ff@2800:e2:f80:867:cac2:6501:5166:e177) (Ping timeout: 264 seconds)
00:15:46 × gurkenglas quits (~gurkengla@p548ac72e.dip0.t-ipconnect.de) (Ping timeout: 265 seconds)
00:16:00 × jero98772 quits (~jero98772@2800:484:1d80:d8ce:3490:26c5:1782:da8c) (Ping timeout: 264 seconds)
00:17:02 × TonyStone quits (~TonyStone@2603-7080-8607-c36a-61f2-c7b2-cd95-6846.res6.spectrum.com) (Remote host closed the connection)
00:18:46 TonyStone joins (~TonyStone@cpe-74-76-51-197.nycap.res.rr.com)
00:19:58 matthewmosior joins (~matthewmo@173.170.253.91)
00:20:20 ddellacosta joins (~ddellacos@143.244.47.100)
00:26:15 × jgeerds_ quits (~jgeerds@55d46bad.access.ecotel.net) (Ping timeout: 252 seconds)
00:35:39 jmorris joins (uid537181@id-537181.uxbridge.irccloud.com)
00:40:05 × auri quits (~auri@fsf/member/auri) ()
00:45:44 Batzy_ is now known as Batzy
00:48:09 × ec quits (~ec@gateway/tor-sasl/ec) (Ping timeout: 258 seconds)
00:49:44 ec joins (~ec@gateway/tor-sasl/ec)
00:52:24 auri joins (~auri@fsf/member/auri)
00:59:49 Guest85 joins (~Guest85@45.144.115.145)
01:00:26 <Guest85> interpreter' (coor:coors) x y print
01:00:27 <Guest85>  | coor == [] = show print
01:00:27 <Guest85>  | coor == "left" = interpreter' coors (x-1) y print
01:00:28 <Guest85>  | coor == "right" = interpreter' coors (x+1) y print
01:00:28 <Guest85>  | coor == "up" = interpreter' coors x (y+1) print
01:00:29 <Guest85>  | coor == "down" = interpreter' coors x (y-1) print
01:00:29 <Guest85>  | coor == "printX" = interpreter' coors x y (print++[x])
01:00:30 <Guest85>  | coor == "printY" = interpreter' coors x y (print++[y])
01:00:30 <Guest85>  | True = interpreter' coors x y print
01:00:40 <Guest85> why does this get "Non-exhaustive patterns in function interpreter"
01:00:42 <Guest85> ?
01:02:23 <geekosaur> because it doesn't handle an empty list of coordinates
01:02:31 <geekosaur> (cood:coors) must be nonempty
01:02:39 <geekosaur> *(coor:coors)
01:03:40 × nate2 quits (~nate@98.45.169.16) (Ping timeout: 246 seconds)
01:03:46 <dsal> I think I'd get rid of the explicit recursion there and just use fold.
01:04:43 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 246 seconds)
01:04:46 <EvanR> as is the algorithm will crash when (if) the stream of instructions ends
01:05:12 <EvanR> if it's supposed to be infinite you could shut it up by using a Stream
01:05:19 <ski> may be good recursion practice
01:06:08 <Guest85> I thought that's what I was doing, recursion through the coordinate list
01:06:13 rockymarine joins (~rocky@user/rockymarine)
01:06:26 <EvanR> try running it on an empty list
01:06:30 <Guest85>  | (coor:coors) == [] = show print     I changed it to that and still get the non-exhaustive patterns error
01:06:41 <dsal> Yeah, you are. I'd just not have done the recursion explicitly. I think it'd be clearer.
01:06:43 <Guest85> how would I use fold instead?
01:06:47 <ski> `coor == []' is testing if the first string is the empty string. not testing if you're fed an empty list of strings
01:06:50 <EvanR> (coor:coords) == [] is impossible
01:06:53 <dsal> Guest85: In order to construct (coor:coors) you'd still have to have `coor` and `coors`
01:06:57 wroathe joins (~wroathe@206-55-188-8.fttp.usinternet.com)
01:06:57 × wroathe quits (~wroathe@206-55-188-8.fttp.usinternet.com) (Changing host)
01:06:57 wroathe joins (~wroathe@user/wroathe)
01:07:09 <dsal> (well, `coors` could be `[]`)
01:07:28 <EvanR> : and [] are two different constructors
01:07:34 <EvanR> it's like saying 0 == 1
01:08:03 <dsal> Guest85: It'd be good to understand what you've got now. But you basically have three state variables you're keeping and your updating one of them each time you get to a particular string, so `move :: String -> State -> State`
01:08:17 <ski> > (coor:coords) == []
01:08:19 <lambdabot> False
01:09:15 <dsal> Then you could write `move "left" state = state{x = x - 1}` and then just fold over that.
01:10:33 × albet70 quits (~xxx@2400:8902::f03c:92ff:fe60:98d8) (Remote host closed the connection)
01:11:01 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 246 seconds)
01:11:04 <dsal> Alternatively, you could just get rid of the guards and write `interpreter' [] _ _ p = show p; interpreter' ("left":xs) x y p = interpreter' (x - 1) y p; ...` -- that might make it clearer.
01:11:31 <dsal> (er, I didn't recurse there, but something like that)
01:12:44 <dsal> I just find it easier to think about, build, and test the "how do you do one thing" part and then build something to do the "how do you do many things" on top of that.
01:13:45 × ddellacosta quits (~ddellacos@143.244.47.100) (Ping timeout: 265 seconds)
01:15:06 <Guest85> interpreter' (coor:coors) x y print
01:15:07 <Guest85>  | coor == [] = show print
01:15:07 <Guest85>  | coors == [] = show print
01:15:08 <Guest85>  | coor == "left" = interpreter' coors (x-1) y print
01:15:08 <Guest85>  | coor == "right" = interpreter' coors (x+1) y print
01:15:09 <Guest85>  | coor == "up" = interpreter' coors x (y+1) print
01:15:09 <Guest85>  | coor == "down" = interpreter' coors x (y-1) print
01:15:10 <Guest85>  | coor == "printX" = interpreter' coors x y (print++[x])
01:15:10 <Guest85>  | coor == "printY" = interpreter' coors x y (print++[y])
01:15:11 <Guest85>  | True = interpreter' coors x y print
01:15:32 <ski> please use more than one defining equation
01:15:43 <ski> (like dsal suggested)
01:15:57 <Guest85> rather than guards?
01:16:00 <Guest85> *Set3a> interpreter' ["up","up","right","right","right","printY","printX","printX","printY"] 0 0 []
01:16:01 <Guest85> "[2,3,3]"
01:16:05 <Guest85> doesn't show the last print
01:16:34 <ski> you could use guards for the strings, still .. although i think it's better (clearer) to not use guards for those, either
01:16:39 albet70 joins (~xxx@2400:8902::f03c:92ff:fe60:98d8)
01:16:57 <dsal> Guest85: You're telling it not to run the last one.
01:17:00 <ski> "doesn't show the last print" -- because your termination condition is incorrect
01:18:25 <ski> if you're checking `coors' for being empty, you're not checking whether the input list is empty. you're checking whether its *tail* is empty. so, when you then stop, you're ignoring `coor', which is then the last element
01:18:34 nate2 joins (~nate@98.45.169.16)
01:18:35 × qrpnxz quits (~qrpnxz@fsf/member/qrpnxz) (Quit: WeeChat 3.5)
01:19:03 <geekosaur> `coors = []` means stop before the last item. you need to check if the list is empty as opposed to bveing (coor:coors) — by the time you hit that it is too late
01:19:27 <EvanR> coor:coords doesn't match []
01:19:43 <ski> `coor:coors', in this defining equation, is the input list (which is required to be non-empty, because the pattern `coor:coors' only match non-empty lists). `coor' is the current element, and `coors' is the list of elements after the current ones
01:21:16 <ski> Guest85 : have you defined simpler list recursions ?
01:22:03 <Guest85> interpreter' [] x y print = []
01:22:11 <Guest85> put that as a second defining equation
01:22:20 <ski> good
01:22:31 <Guest85>  | coor == [] = show print
01:22:39 <Guest85> kept that as the termination condition
01:22:45 <Guest85> *Set3a> interpreter' ["up","up","right","right","right","printY","printX","printX","printY"] 0 0 []
01:22:46 <Guest85> ""
01:22:50 <ski> (i'd put it first .. but it doesn't really matter, in this case, except for style/aesthetic reasons)
01:23:01 rockymarine joins (~rocky@user/rockymarine)
01:23:34 <ski> well, you're now ignoring your carefully built up "result so far", in that base case
01:23:37 × vglfr quits (~vglfr@145.224.100.249) (Ping timeout: 246 seconds)
01:23:39 <ski> namely `print' is ignored
01:25:07 <Guest85> I'm stumped.. how is it being ignored?
01:25:19 <ski> your result is literally `[]'
01:25:25 <ski> `print' is not mentioned in the result
01:25:39 <ski> so, `print' is getting ignored, in your base case defining equation
01:26:18 <ski> interpreter' [] x y print = []
01:26:19 <ski> ^^
01:26:25 <ski> that result
01:27:38 <Guest85> ok I see that, maybe I can't use guards with this
01:27:52 <ski> you can. that is unrelated to this issue
01:28:10 ski wouldn't use guards here
01:28:13 <ski> but you can, if you want to
01:28:21 × Null_A_ quits (~null_a@2601:645:8700:ac10:1005:19fc:119b:3387) (Remote host closed the connection)
01:28:32 <monochrom> I'm going to comment on the higher-level issue.
01:28:56 Null_A joins (~null_a@2601:645:8700:ac10:c06c:ee8:e627:7270)
01:29:26 <Guest85> ok so I made the base case = show print
01:29:28 <Guest85> works now
01:29:58 <Guest85> finally lol, thanks for the help
01:30:01 Null_A_ joins (~null_a@2601:645:8700:ac10:588d:dcc4:cf71:c2f0)
01:30:30 <ski> it's also not good to repeatedly add to the end of `print'
01:30:32 <Guest85> I'll look at the other methods dsal mentioned
01:30:48 <ski> that will cause quadratic complexity, rather than the expected linear one
01:31:51 <Guest85> not familiar with that term. is it not optimized this way?
01:32:03 <dsal> Guest85: your should definitely understand what you've got there in any case
01:32:35 <ski> the reason is that if you have `(((as ++ bs) ++ cs) ++ ds) ++ es', then the innermost (leftmost) `++' will first traverse `as', making a copy of its cons cells, putting `bs' at the end of that (without traversing `bs')
01:33:08 <ski> then the next `++' will traverse the result of `as ++ bs'. so, effectively traversing `as' again (well, the copy of `as', but it's the same length), and then also `bs'
01:33:34 × jrm quits (~jrm@user/jrm) (Read error: Connection reset by peer)
01:33:36 × Null_A quits (~null_a@2601:645:8700:ac10:c06c:ee8:e627:7270) (Ping timeout: 244 seconds)
01:33:41 <ski> then, the next `++' will traverse `(as ++ bs) ++ cc', so again (effectively) traversing `as' and `bs', and then also `cs'
01:33:50 jrm joins (~jrm@user/jrm)
01:34:13 limberdelt joins (~limberdel@gateway/vpn/pia/limberdelt)
01:34:21 <Guest85> what's a better way of doing it?
01:34:32 <ski> so .. in the end, you effectively end up traversing `as' four times, `bs' three times, `cs' two times', `ds' one time, and `es' zero times (all of them traversed once again, when the caller traverses the result list)
01:34:42 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 260 seconds)
01:35:08 <ski> better is to do `as ++ (bs ++ (cs ++ (ds ++ es)))'. right-associated calls to `++', rather than left-associated ones
01:35:17 <ski> now, how does this relate to your definition ?
01:35:25 × jrm quits (~jrm@user/jrm) (Read error: Connection reset by peer)
01:35:25 <ski> well, you have recursive calls like
01:35:28 <Guest85> what if I did ([x]++print) and reversed the list at the end?
01:35:33 <ski> interpreter' coors x y (print++[x])
01:35:40 jrm joins (~jrm@user/jrm)
01:36:21 × jrm quits (~jrm@user/jrm) (Remote host closed the connection)
01:36:29 <ski> so `print++[x]' becomes the new `print' in the next call, and then may get more things added to the end of it. so you'll end up with `(..(([] ++ [x0]) ++ [x1])..) ++ [xn]'
01:36:36 <ski> Guest85 : yes, that's one standard solution
01:37:25 ubert1 joins (~Thunderbi@91.141.58.249.wireless.dyn.drei.com)
01:37:40 <ski> in this case, there's also another straightforward solution, that is probably actually (slightly) better (more flexible, possibly a little bit more efficient, although not a huge difference, unlike the associatedness thing) in this case
01:38:48 <ski> that solution is : instead of collecting your output, keeping it all to yourself until the end, when you publish it .. you simply publish each piece of it at the time you decide it should be part of the output list
01:39:24 × ubert quits (~Thunderbi@77.119.207.90.wireless.dyn.drei.com) (Ping timeout: 264 seconds)
01:39:24 ubert1 is now known as ubert
01:40:54 <Guest85> not sure how to accomplish that
01:41:09 <ski> (this is possible because (a) you're always publishing your list, there's no possible bailing-out at the end, in your code. so you could just as well be publishing as you go; and (b) because you're generating the output numbers in the order you want to have them in the result list (rather than say in reversed order, or in some other permutation of the order))
01:41:17 <Guest85> change the print conditionals so they show the x and y values? how would I terminate it then
01:41:42 <ski> well .. perhaps you could first try to implement your last idea, to see through how it would work
01:42:03 <ski> it is good practice, because this can often be a useful tactic to apply
01:42:45 <ski> (it's just that, in this case, i think the alternative i was roughly sketching at, is preferrable)
01:43:26 <Guest85> I did change it to the right-associated calls with the reverse
01:43:43 <ski> where/how did you place the `reverse' ?
01:43:50 <Guest85> interpreter' [] x y print = show print
01:43:51 <Guest85> interpreter' (coor:coors) x y print
01:43:51 <Guest85>  | coor == [] = show $ reverse print
01:43:52 <Guest85>  | coor == "left" = interpreter' coors (x-1) y print
01:43:52 <Guest85>  | coor == "right" = interpreter' coors (x+1) y print
01:43:53 <Guest85>  | coor == "up" = interpreter' coors x (y+1) print
01:43:53 <Guest85>  | coor == "down" = interpreter' coors x (y-1) print
01:43:54 <Guest85>  | coor == "printX" = interpreter' coors x y ([x]++print)
01:43:54 <Guest85>  | coor == "printY" = interpreter' coors x y ([y]++print)
01:43:55 <Guest85>  | True = interpreter' coors x y print
01:43:59 pgray__ joins (~pgray@c-24-143-114-36.customer.broadstripe.net)
01:44:18 <ski> btw (unrelated), try this query :
01:44:25 <ski> *Set3a> interpreter' ["up","up","right","right","right","","printY","printX","printX","printY"] 0 0 []
01:44:43 × pgray quits (~pgray@c-24-143-114-36.customer.broadstripe.net) (Ping timeout: 252 seconds)
01:44:51 <ski> (also try the original query from above)
01:45:51 × crns quits (~netcrns@user/crns) (Ping timeout: 268 seconds)
01:46:11 <ski> (well, i guess possibly a bit related)
01:46:31 ski idly wonders what comment monochrom is building up to
01:46:56 matthewmosior joins (~matthewmo@173.170.253.91)
01:47:00 fef joins (~thedawn@user/thedawn)
01:47:13 <Guest85> it trips up with the ""
01:47:19 <Guest85> *Set3a> interpreter' ["up","up","right","right","right","printY","printX","printX","printY"] 0 0 []
01:47:20 <Guest85> "[2,3,3,2]"
01:47:20 <ski> why ?
01:47:25 <Guest85> that's correct
01:47:27 crns joins (~netcrns@p4ff5e2e3.dip0.t-ipconnect.de)
01:47:28 × crns quits (~netcrns@p4ff5e2e3.dip0.t-ipconnect.de) (Changing host)
01:47:28 crns joins (~netcrns@user/crns)
01:47:56 <ski> why does the former trip up with the `""' ?
01:49:34 <Guest85> gets terminated hmm
01:51:41 <Guest85> fixed it
01:51:49 <Guest85>  | coor == [] && coors == [] = show $ reverse print
01:52:34 <ski> how many terminating cases do you have ?
01:52:52 <Guest85> just one
01:52:54 <ski> no
01:52:55 <Guest85> interpreter' [] x y print = show print
01:52:56 <Guest85> interpreter' (coor:coors) x y print
01:52:56 <Guest85>  | coor == [] && coors == [] = show $ reverse print
01:52:57 <Guest85>  | coor == "left" = interpreter' coors (x-1) y print
01:52:57 <Guest85>  | coor == "right" = interpreter' coors (x+1) y print
01:52:58 <Guest85>  | coor == "up" = interpreter' coors x (y+1) print
01:52:58 <Guest85>  | coor == "down" = interpreter' coors x (y-1) print
01:52:59 <Guest85>  | coor == "printX" = interpreter' coors x y ([x]++print)
01:52:59 <Guest85>  | coor == "printY" = interpreter' coors x y ([y]++print)
01:53:00 <Guest85>  | True = interpreter' coors x y print
01:53:06 <ski> that's not just one
01:53:58 × segfaultfizzbuzz quits (~segfaultf@23-93-74-212.fiber.dynamic.sonic.net) (Remote host closed the connection)
01:54:14 <ski> (where are the terminating cases ?)
01:55:12 <Guest85> the first equation and the first guard
01:55:15 <ski> yes
01:55:27 <ski> do you need two different terminating cases ?
01:55:50 <Guest85> if I remove the 1st equation, it gives that non-exhaustive pattern error
01:55:51 <ski> when is the first one reached ? when is the second one reached ?
01:56:19 <Guest85> if I provide an empty list
01:56:31 <ski> first or second ?
01:56:37 <Guest85> 1st. tho honestly the 1st guard looks like it should catch that too
01:56:50 × nate2 quits (~nate@98.45.169.16) (Ping timeout: 244 seconds)
01:57:09 <ski> second defining equation is only used for non-empty lists. first defining equation is only used for empty lists
01:57:44 <ski> `coor:coors'is a non-empty list. there's no way, if you pass an empty list, it's going to get into that defining equation
01:58:07 <ski> (similarly, `[]' in the first defining equation is an empty list, won't match if you pass a non-empty list)
01:58:22 <Guest85> the : makes it non-empty?
01:58:26 <ski> yes
01:58:37 <Guest85> ok
01:58:40 <ski> > null []
01:58:41 <lambdabot> True
01:58:50 <ski> > null (undefined : undefined)
01:58:51 <lambdabot> False
01:58:53 × limberdelt quits (~limberdel@gateway/vpn/pia/limberdelt) (Quit: Leaving)
01:59:06 limberdelt joins (~limberdel@gateway/vpn/pia/limberdelt)
01:59:12 <ski> (works with any valid expressions in place of those two `undefined's)
01:59:41 <Guest85> gotcha
01:59:46 <Guest85> learning, thanks
01:59:48 <EvanR> this is puzzling me, I tried to move `reverse .' to the inside of the function on its right, but that changes the behavior https://paste.tomsmeding.com/qSBpMnX0
02:01:08 king_gs joins (~Thunderbi@2806:103e:29:ac5e:a16e:4ac9:a89b:4d)
02:01:29 <ski> EvanR : `unpackChars' is recursive
02:01:36 <ski> perhaps you meant `f' to be recursive
02:01:45 <EvanR> lol yes
02:01:59 × king_gs quits (~Thunderbi@2806:103e:29:ac5e:a16e:4ac9:a89b:4d) (Client Quit)
02:01:59 <EvanR> no help from the compiler there
02:02:25 <ski> (seeing what you think you wrote, instead of what you actually wrote, i imagine)
02:03:10 <EvanR> I just refused to read the code because moving `reverse .' over shouldn't change anything
02:03:15 jero98772 joins (~jero98772@2800:484:1d80:d8ce:9fc6:bfaf:da6f:bda1)
02:03:26 <EvanR> and unpackChars was working without it, despite being wrong
02:03:29 <ski> Guest85 : so, when is the second terminating case reached ?
02:03:37 ski nods
02:05:16 × berberman quits (~berberman@user/berberman) (Ping timeout: 246 seconds)
02:07:25 × johnjaye quits (~pi@173.209.64.74) (Ping timeout: 265 seconds)
02:08:10 <Guest85> when it has iterated through the entire list and both coor and coors are empty
02:08:17 <ski> yes
02:08:28 <ski> when is both `coor' and `coors' empty ?
02:09:03 <Guest85> it will go through it since it's recursive
02:09:19 <Guest85> until it reaches the end of the list
02:09:27 <ski> (perhaps this feels like a somewhat silly question, hard to answer without stating back the same .. but i think thinking about it may help to understand better what your code is doing)
02:09:31 <ski> no
02:09:52 <ski> at this point, the current list it is considering is `coor:coors', which is definitely not an empty list
02:10:21 <ski> it will have passed by some number of previous elements in the list, doing recursive calls on successive tails
02:10:35 <ski> but when it reaches this case, the current list tail it's looking at is not empty
02:10:56 <ski> what does the guard terminating condition say ?
02:11:32 <Guest85> coor and coors are undefined?
02:11:32 <ski> ("the end of the list" is always an empty list .. just making this clear, if perhaps it wasn't)
02:11:47 <ski> well, let's look at the guard and corresponding expression
02:11:58 <ski>  | coor == [] && coors == [] = show $ reverse print
02:12:25 <ski> this triggers when the guard `coor == [] && coors == []' is `True' ..
02:12:30 <ski> .. which happens exactly when ?
02:13:49 <ski> (you basically said it before, as part of a longer statement you made)
02:14:07 <Guest85> that it iterated through it?
02:14:31 <ski> it has iterated through some number of elements (possibly zero of them), before reaching this point
02:15:01 <ski> let's say it goes into this terminating case. what must have happened, what must be true, of the current list it's looking at, for it to select this guard ?
02:15:26 <ski> (hint : it's not that the current list is empty, that's already been ruled out)
02:16:02 <Guest85> not sure
02:16:16 <Guest85> I simplified it though by removing that guard and it still works as intended
02:16:16 <Guest85> interpreter' [] x y print = show $ reverse print
02:16:17 <Guest85> interpreter' (coor:coors) x y print
02:16:17 <Guest85>  | coor == "left" = interpreter' coors (x-1) y print
02:16:18 <Guest85>  | coor == "right" = interpreter' coors (x+1) y print
02:16:18 <Guest85>  | coor == "up" = interpreter' coors x (y+1) print
02:16:19 <Guest85>  | coor == "down" = interpreter' coors x (y-1) print
02:16:20 <Guest85>  | coor == "printX" = interpreter' coors x y ([x]++print)
02:16:20 <Guest85>  | coor == "printY" = interpreter' coors x y ([y]++print)
02:16:20 <Guest85>  | True = interpreter' coors x y print
02:16:27 <ski> `coor == [] && coors == []' is true when ..
02:16:38 <Guest85> coor and coors are empty
02:16:41 <ski> .. <something> and <something> is true
02:16:42 <ski> yes !
02:17:22 <ski> that is, when the current list is `[] : []'. which is the same as `[[]]'. or, since this is a list of `String's, this is also the same as `"" : []' and as `[""]'
02:17:50 <ski> so, it would *only* select that guard, if the *last* `String' in the list was the empty `String', `""' !
02:17:53 <ski> do you see this ?
02:18:10 <dsal> (slightly confusing since you're using a string as a list here)
02:18:17 ski nods
02:18:28 <ski> (`String's in Haskell are lists of `Char'acters)
02:19:55 × td_ quits (~td@muedsl-82-207-238-210.citykom.de) (Ping timeout: 252 seconds)
02:20:47 ski looks at Guest85
02:21:00 <Guest85> so it's an empty list
02:21:13 <ski> `[] : []' is not an empty list
02:21:34 <ski> it's a list containing a single element, which, yes, is an empty list/`String'
02:21:42 td_ joins (~td@muedsl-82-207-238-005.citykom.de)
02:21:54 × gff_ quits (~gff@user/gff) (Ping timeout: 265 seconds)
02:22:22 nate2 joins (~nate@98.45.169.16)
02:22:25 <ski> and since you're traversing a list, stripping off one element at a time, it'll (eventually) get there, when the original list of `String's *ends* with the last `String' being the empty `String'
02:22:28 <Guest85> it's an empty list in a list of lists
02:22:32 <ski> yes
02:22:42 <ski> so, the guard
02:22:49 <ski>  | coor == [] && coors == [] = show $ reverse print
02:23:08 <ski> was mostly useless, since you'll probably not call this function often with the last `String' being empty
02:23:18 <ski> now, consider the previous version of this guard
02:23:28 <ski> | coor == [] = show $ reverse print
02:23:30 finn_elija joins (~finn_elij@user/finn-elija/x-0085643)
02:23:30 × FinnElija quits (~finn_elij@user/finn-elija/x-0085643) (Killed (NickServ (Forcing logout FinnElija -> finn_elija)))
02:23:30 finn_elija is now known as FinnElija
02:23:39 gff_ joins (~gff@user/gff)
02:23:51 <ski> this triggers when the current list, which is `coor:coors', is actually `[]:coors'
02:24:14 <Guest85> just the head of the list is empty
02:24:37 <ski> and since we have walked over some number of elements before this, this means that this case will trigger *whenever* we see an empty `String', in *any* position, in the list of `String's
02:24:48 <ski> which was why my example
02:24:55 <ski> *Set3a> interpreter' ["up","up","right","right","right","","printY","printX","printX","printY"] 0 0 []
02:25:04 <ski> tripped over the `""', terminating too early
02:25:17 <ski> you see this now ?
02:25:25 <Guest85> yes
02:25:28 <ski> ok, good
02:25:40 ftoy joins (~fucktoy@S01069050ca4e3573.cg.shawcable.net)
02:25:42 <ftoy> hello boys
02:25:42 <ski> now, your last attempted change above, is the correct one
02:26:00 <ski> we don't need to terminate when we see an empty `String' at the end of the list
02:26:14 <ski> and we certainly don't need to terminate whenever we see an empty `String' anywhere in the list
02:26:26 <ski> we would like to terminate when there's no more elements to process
02:26:33 <ski> which is exactly what the other terminating case
02:26:38 <ski> interpreter' [] x y print = show $ reverse print
02:26:39 <ski> does
02:26:53 × nate2 quits (~nate@98.45.169.16) (Ping timeout: 252 seconds)
02:27:27 <ski> (we reach this, after handing some number of previous elements, as long as there was no other terminating case that we reached first, stopping us from getting to the very end, and stopping with this case there)
02:27:33 <ski> hello ftoy
02:27:48 <ski> (s/handing/handling/)
02:28:07 <ski> Guest85 : next question. how/where do you call interpreter' in your code ?
02:28:09 <Guest85> ok thanks ski for the detailed explanation, have a better understanding now
02:28:26 <Guest85> I call it throughout
02:28:33 <ski> in many places ?
02:28:56 <ski> do you always call it like
02:29:06 <ski> interpreter' <some list here> 0 0 []
02:29:06 <ski> ?
02:29:17 <Guest85> it's going to be a helper function
02:29:25 <ski> is there any interpreter (without a prime) ?
02:29:35 ski nods
02:30:03 <ski> so this helper is only (directly) called from a worker/wrapper function, correct ?
02:30:11 <Guest85> correct
02:30:47 <ski> could you show how it is calling the above function ?
02:31:18 <ski> (i'd like to make a specific point, regarding this, and what you did, above)
02:31:46 <Guest85> interpreter x = interpreter' x 0 0 []
02:31:49 <ski> good
02:32:11 <ftoy> ski: wow, youre sure smart
02:32:13 <ski> it's good practice to isolate the initialization of "worker parameters" (accumulators, here), in this way
02:32:25 <ski> now, i wanted to say :
02:33:12 <ski> instead of placing your terminating action (finally reversing the list at the end), in the terminating case(s) of the helper/worker, you *could* also have put that in the wrapper
02:33:30 <ski> (sorry, before i said "worker/wrapper". it's the helper which is the worker. the wrapper is not)
02:34:29 <ski> in your case, since the `reverse' happens to `print' before you pass it to `show', you'd then also have to move the `show' to the wrapper .. but that would be ok, since noone else is calling interpreter' anyway, so noone relies on it, and not the wrapper, calling `show'
02:35:19 nate2 joins (~nate@98.45.169.16)
02:35:28 <ski> one reason one might want to do such a thing is in case one actually have multiple terminating conditions (and want to `reverse' in each case). so instead of putting multiple calls to `reverse' into the worker, you just put one into the `wrapper', as "finalization", together with the "initialization" it already does
02:35:45 <ski> in your case, either works fine, since there's just one terminating case of the worker/helper
02:35:52 <ski> Guest85 : all clear ?
02:36:24 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 265 seconds)
02:37:47 <ski> there was one more thing which i wanted to talk about (if you care to hear about it, atm. perhaps you're starting to get tired or overwhelmed, and have enough for the moment to chew on. that'd be fine)
02:38:22 <Guest85> how would I put the terminating condition in the wrapper if the worker function recurses on interpreter'?
02:38:37 <ski> you'd have :
02:38:47 <ski> interpreter x = show (reverse (interpreter' x 0 0 []))
02:38:48 vglfr joins (~vglfr@145.224.100.249)
02:38:54 <ski> and then, for the helper :
02:39:03 <ski> interpreter' [] x y print = print
02:39:09 <ski> (that's all)
02:39:15 <Guest85> ah ok
02:40:13 <ski> namely, i mentioned another way to still avoid the left-associated calls to `++' (which yields unreasonable/unexpected inefficiency), but instead of keeping your intended output elements to yourself all until the end (when you always publish/return them), you could public each one of them, as you go
02:40:39 <ski> if you're up for it, we could talk about this idea for a bit, how it'd work
02:40:51 × fef quits (~thedawn@user/thedawn) (Ping timeout: 258 seconds)
02:40:54 <Guest85> I'm getting a type error and I'm not sure why
02:40:58 × jero98772 quits (~jero98772@2800:484:1d80:d8ce:9fc6:bfaf:da6f:bda1) (Ping timeout: 246 seconds)
02:41:03 <Guest85> interpreter :: [String] -> [String]
02:41:04 <Guest85> interpreter x = interpreter' x 0 0 []
02:41:04 <Guest85> interpreter' [] x y print = show $ reverse print
02:41:05 <Guest85> interpreter' (coor:coors) x y print
02:41:05 <Guest85>  | coor == "left" = interpreter' coors (x-1) y print
02:41:06 <Guest85>  | coor == "right" = interpreter' coors (x+1) y print
02:41:06 <Guest85>  | coor == "up" = interpreter' coors x (y+1) print
02:41:07 <Guest85>  | coor == "down" = interpreter' coors x (y-1) print
02:41:07 <Guest85>  | coor == "printX" = interpreter' coors x y ([x]++print)
02:41:08 <Guest85>  | coor == "printY" = interpreter' coors x y ([y]++print)
02:41:08 <Guest85>  | True = interpreter' coors x y print
02:41:11 <Guest85> Set3a.hs:315:17: error:
02:41:11 <Guest85>     • Couldn't match type ‘Char’ with ‘[Char]’
02:41:12 <Guest85>       Expected type: [String]
02:41:12 <Guest85>         Actual type: String
02:41:13 <Guest85>     • In the expression: interpreter' x 0 0 []
02:41:13 <Guest85>       In an equation for ‘interpreter’:
02:41:14 <Guest85>           interpreter x = interpreter' x 0 0 []
02:41:14 <Guest85>     |
02:41:15 <Guest85> 315 | interpreter x = interpreter' x 0 0 []
02:41:39 <dolio> Don't do that. :þ
02:41:44 <ski> `show' gives a `String', but you've declared `interpreter' to have result type `[String]'
02:41:54 polykernel[m] joins (~polykerne@user/polykernel)
02:43:08 × raym quits (~raym@user/raym) (Quit: going to travel back home)
02:43:26 × terrorjack quits (~terrorjac@2a01:4f8:1c1e:509a::1) (Quit: The Lounge - https://thelounge.chat)
02:44:02 <Guest85> ah ok I fixed it
02:44:04 <Guest85> interpreter' [] x y print = map show $ reverse prin
02:44:12 ski glances sideways
02:44:21 <ski> .. that's one way to fix the type error
02:44:47 terrorjack joins (~terrorjac@2a01:4f8:1c1e:509a::1)
02:45:27 × jmorris quits (uid537181@id-537181.uxbridge.irccloud.com) (Quit: Connection closed for inactivity)
02:45:31 <Guest85> how could I do it the other way, publish them as it recurses through the function?
02:46:01 <ski> well, i could try to illustrate the general idea, with some other functions. sounds okay ?
02:46:11 <Guest85> ok
02:47:11 <ski> consider first a quite simple function that traverses an input list, namely "compute the product of all the numbers in the list"
02:47:22 × ftoy quits (~fucktoy@S01069050ca4e3573.cg.shawcable.net) (Quit: Client closed)
02:47:31 <ski> product :: [Integer] -> Integer
02:47:42 <ski> we might start with
02:47:48 <ski> product ns = ..ns..
02:48:11 <ski> (`..ns..' indicating a "hole", code we haven't written yet, but which we imagine will probably need to use `ns')
02:48:45 <ski> but then we realize that we can't move forward at this point, unless we look at the list, checking if there's at least one number to process there
02:49:03 <ski> so, the obvious thing to do is to split cases, into empty list, and non-empty list
02:49:34 <ski> (i'm spelling out intermediate steps that you'd probably only do in your head, if you'd even think about them explicitly, for clarity/emphasis of the process)
02:49:51 <ski> so, we replace the above tentative defining equation with these two :
02:49:53 rockymarine joins (~rocky@user/rockymarine)
02:49:57 <ski> product [ ] = ...
02:50:07 <ski> product (n:ns) = ..n..ns..
02:50:25 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 265 seconds)
02:50:55 <ski> now, we might again decide we need to know whether `ns' is empty or not .. after all, we need not just the first number, but all (?) of them, for the product
02:51:31 <ski> but this is where the magic of recursion steps in and stops you, asking you if you can spot a subproblem that looks like the whole main problem you're trying to solve
02:52:39 <ski> namely, we were originally trying to compute the product of a list. after determining (in one case), that it has a first element `n', and a list of remaining elements `ns' (which might be empty), we can consider an illustrative example like `product [2,3,5,7]'
02:52:54 jero98772 joins (~jero98772@2800:484:1d80:d8ce:3490:26c5:1782:da8c)
02:52:55 <ski> in that example, `n' will become `2', and `ns' will become `[3,5,7]'
02:53:09 fef joins (~thedawn@user/thedawn)
02:53:10 <ski> and, what we're trying to compute is `2 * 3 * 5 * 7'
02:53:51 <ski> now, `3 * 5 * 7' is a subproblem of the problem of computing `2 * 3 * 5 * 7', from the input list `[2,3,5,7]'
02:54:10 <ski> and we already have the sublist `[3,5,7]' of the input list
02:54:57 <ski> so, the magic of recursion tells us that we can just trust that `product [3,5,7]' (calling recursively on a "smaller" input, one that's "closer" to terminating condition(s) will work correctly, do it's thing, without worrying about it, or how it'll work
02:55:51 <ski> so, we have `n = 2', and we just assume that for `ns = [3,5,7]', a recursive call `product ns = product [3,5,7]' will compute `3 * 5 * 7' for us
02:56:39 <ski> now, what's left is to piece together `2' and `3 * 5 * 7' together, to the desired result `2 * 3 * 5 * 7', and express this generally, for any input, not just for this particular example
02:57:17 <ski> so since `n = 2' and `product ns = 3 * 5 * 7', it seems `n * product ns = 2 * 3 * 5 * 7' should do it
02:57:38 <ski> so, that's what we put as body of our recursive defining equation. both together now look like :
02:57:46 <ski> product [ ] = ...
02:57:59 <ski> product (n:ns) = n * product ns
02:58:47 <Guest85> I understand how to do those recursive expressions
02:58:56 <Guest85> how's it apply to the interpreter function?
02:58:59 <ski> what remains is to finish the base case, the terminating case. after some thought, one may convince oneself that the proper thing to put there is `1', as the product of zero numbers. this will cause the result of out example to be `2 * 3 * 5 * 7 * 1', but that's ok
02:59:04 <Guest85> other than the recursion
02:59:11 <ski> we could also, if we wanted to, add a special case for `0'
02:59:17 <ski> product (0:_ ) = 0
02:59:25 <ski> (another, early, terminating case)
02:59:53 <ski> yea .. i just wanted to spell out the recursive process a bit in detail. i'll omit most of that now
03:00:35 <ski> note that now `product [2,3,5,7]' generates `2 * (3 * (5 * (7 * 1)))' .. which is right-associated
03:00:42 <ski> if you look at the expansion
03:00:50 <ski> product [2,3,5,7]
03:00:56 <ski> = 2 * product [3,5,7]
03:01:05 <ski> = 2 * (3 * product [5,7])
03:01:12 <ski> = 2 * (3 * (5 * product [7]))
03:01:22 <ski> = 2 * (3 * (5 * (7 * product [])))
03:01:26 <ski> = 2 * (3 * (5 * (7 * 1)))
03:01:27 <ski> = 2 * (3 * (5 * 7))
03:01:35 <ski> = 2 * (3 * 35)
03:01:38 <ski> = 2 * 105
03:01:41 <ski> = 210
03:01:49 × jero98772 quits (~jero98772@2800:484:1d80:d8ce:3490:26c5:1782:da8c) (Remote host closed the connection)
03:02:18 <ski> you'll see the stack, the context around the recursive call, growing, until the base case, and then multiplications being done in reverse, on the "way back up"
03:02:41 <Guest85> hmm
03:02:43 <ski> .. we might want to avoid needlessly using stack space, when we can reasonably avoid doing so
03:02:57 <ski> the obvious solution, as you already should know, is to introduce an accumulator parameter
03:03:14 <ski> product ns = productTimes ns 1
03:03:37 <ski> the idea is that `productTimes ns acc' will compute `acc * productTimes ns'
03:03:45 <ski> er, sorry, `acc * product ns'
03:04:09 burnsidesLlama joins (~burnsides@119247164140.ctinets.com)
03:04:11 <ski> but now we let the helper, `productTimes', do the recursion, and multiplying into the accumulator in each step
03:04:19 <ski> productTimes [ ] acc = acc
03:04:36 <ski> productTimes (n:ns) acc = productTimes (acc * n) acc
03:04:46 <ski> now the same example will reduce as
03:04:52 <ski> product [2,3,5,7]
03:05:00 <ski> = productTimes [2,3,5,7] 1
03:05:09 <ski> = productTimes [3,5,7] (1 * 2)
03:05:12 <ski> = productTimes [3,5,7] 2
03:05:17 <ski> = productTimes [5,7] (2 * 3)
03:05:21 <ski> = productTimes [5,7] 6
03:05:28 <ski> = productTimes [7] (6 * 5)
03:05:33 <ski> = productTimes [7] 30
03:05:39 <ski> = productTimes [] (30 * 7)
03:05:42 <ski> = productTimes [] 210
03:05:45 <ski> = 210
03:06:01 <ski> and you can now see no extra stack space is used, so everything is fine ..
03:06:03 <ski> .. or is it ?
03:06:07 × wroathe quits (~wroathe@user/wroathe) (Ping timeout: 252 seconds)
03:06:10 × vglfr quits (~vglfr@145.224.100.249) (Ping timeout: 246 seconds)
03:06:45 <dolio> It's is not.
03:06:51 <ski> (also you can see we're doing the multiplications from the other end of the list, and doing them on the "down", instead of the "up")
03:06:54 <ski> yes
03:07:00 <ski> in a strict language, we'd be done here
03:07:11 <ski> but in a non-strict language, what actually happens here is :
03:07:20 <ski> product [2,3,5,7]
03:07:28 <ski> = productTimes [2,3,5,7] 1
03:07:33 <ski> = productTimes [3,5,7] (1 * 2)
03:07:37 × mvk quits (~mvk@2607:fea8:5ce3:8500::778c) (Ping timeout: 244 seconds)
03:07:39 <ski> = productTimes [5,7] ((1 * 2) * 3)
03:07:45 <ski> = productTimes [7] (((1 * 2) * 3) * 5)
03:07:51 <ski> = productTimes [] ((((1 * 2) * 3) * 5) * 7)
03:07:56 <ski> = (((1 * 2) * 3) * 5) * 7
03:08:00 <ski> = ((2 * 3) * 5) * 7
03:08:04 <ski> = (6 * 5) * 7
03:08:08 <ski> = 30 * 7
03:08:12 <ski> = 210
03:09:25 <ski> so, while we're not building up stack, we *are* building up an unevaluated expression with multiplications, in the accumulator, and only evaluating that (*now* using the stack we didn't use before) at the end, after reaching the base case and returning
03:09:30 <ski> Guest85 : makes sense ?
03:09:41 × burnsidesLlama quits (~burnsides@119247164140.ctinets.com) (Ping timeout: 244 seconds)
03:10:09 <Guest85> yeah but isn't that left-associated
03:10:38 <ski> sure. we're not getting an unreasonable quadratic rather than expected linear complexity here
03:10:56 <ski> what we *are* getting is an unexpected linear, rather than constant, space complexity
03:11:47 <Guest85> how is this not building up stack?
03:11:55 <ski> so, the solution is to actually make sure to evaluate each version of `acc', as we go, rather than only doing it at the end
03:12:14 <ski> we're not evaluating it, because it might have been that we actually didn't need it at the end
03:12:20 vglfr joins (~vglfr@145.224.100.249)
03:12:38 × [itchyjunk] quits (~itchyjunk@user/itchyjunk/x-7353470) (Remote host closed the connection)
03:13:04 <Guest85> ok
03:13:04 <ski> but in this case, we're always needing it at the end. and we'll be needing to evaluate each part of the multiplication expression. so we might as well be doing it directly, as we're adding in each new multiplication
03:13:16 <ski> one way to do this is to simply add the case
03:13:29 <ski> productTimes (0:_ ) acc = 0
03:13:33 <ski> before the recursive case
03:13:58 <ski> er, sorry, that's incorrect. we wanted to ensure `acc' was evaluated, not `n'
03:14:14 <ski> productTimes _ 0 = 0
03:14:16 <ski> would work
03:15:13 <ski> one could also do it in other ways. e.g. replacing the `acc' parameter with `!acc', which will ensure it will be evaluated. one could also call the function `seq' which is for such things
03:15:55 matthewmosior joins (~matthewmo@173.170.253.91)
03:16:51 <ski> (btw, i should add that ofter (though not always) the compiler could actually spot that `acc' would be needed in the end, and so making sure to evaluate it as we went directly, without we having to do anything. but that's not a guarantee. if we want guarantee, we probably have to do it ourselves, like above, unless we can predict when the compiler optimizes like this .. which might change between versions,
03:16:57 <ski> and optimization levels)
03:17:49 <ski> anyway, the first version of `product' i'd call the direct recursive version. the second version (the fixed one) is the accumulating version, or the tail-recursive version
03:18:18 edrx parts (~Eduardo@2804:56c:d2dc:ac00:dab8:211d:d4eb:fa94) (Killed buffer)
03:18:28 <ski> now consider another function. a function that, given a positive `Integer', will give a list of all its (positive) divisors
03:19:00 <ski> so `divisors 6' should be `[6,3,2,1]' (let's say it should give them in descending order)
03:19:26 <ski> Guest85 : ok, so far ?
03:20:27 luffy joins (~chenqisu1@183.217.203.170)
03:20:49 <Guest85> yeah, I've heard of tail recursion
03:20:51 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 260 seconds)
03:20:55 <ski> good
03:21:00 <Guest85> not much on strictness tho
03:21:10 <ski> let's define, as a helper
03:21:21 <ski> divides :: Integer -> Integer -> Bool
03:21:31 <ski> d `divides` n = n `mod` d == 0
03:21:55 × xff0x quits (~xff0x@2405:6580:b080:900:c9c6:ea14:444b:6072) (Ping timeout: 246 seconds)
03:22:18 <ski> then for `divisors n', we want to consider all the `Integer's from `n' down to `1', and only include those which actually divides `n' in the output list
03:22:34 <ski> so, we will need to get that sequence of `Integer's
03:22:44 <ski> one way to do that is to count down from `n' towards `1'
03:22:56 <ski> this could be one accumulator parameter, of a helper function
03:22:59 × machinedgod quits (~machinedg@d198-53-218-113.abhsia.telus.net) (Quit: Lost terminal)
03:23:25 <ski> and, so far, it seems we need no more accumulating parameters, so that gives :
03:23:36 <ski> divisors :: Integer -> [Integer]
03:23:49 × luffy quits (~chenqisu1@183.217.203.170) (Max SendQ exceeded)
03:23:52 <ski> divisors n = divisorsFrom n n
03:23:55 <ski> where
03:24:08 <ski> divisorsFrom :: Integer -> Integer -> [Integer]
03:24:26 <ski> (hiding the helper/worker inside a `where' of the wrapper)
03:25:07 <ski> let's say the first parameter (for a change) is the counter that we count down. the second is `n', which we'll need to check divisibility with
03:25:19 <ski> base case is when we've counted down to `1' already
03:25:27 luffy joins (~chenqisu1@183.217.203.170)
03:25:30 <ski> divisorsFrom 1 n = ..n..
03:25:52 <ski> in this case, the only divisor that we have to report is `1' itself, so
03:25:58 <ski> divisorsFrom 1 _ = [1]
03:26:14 × vglfr quits (~vglfr@145.224.100.249) (Quit: Quit)
03:26:19 <ski> next case is when we haven't reached the bottom
03:26:27 vglfr joins (~vglfr@145.224.100.249)
03:26:30 <ski> divisorsFrom i n = ..i..n..
03:28:17 <ski> (we could check here that `i' is actually greater (rather than less) than `1'. that would catch the mistake of calling with zero or negative counter. but since the helper is only supposed to be called from the worker, perhaps we don't need to worry ? well, initial value of `i' is `n', and `n' could still be `0' or negative. but if we want to check that, it's better to do it, once, to begin with, in the
03:28:23 <ski> wrapper, than to do it, every time in the loop, in the worker)
03:28:47 <ski> but, we do want to check if `i' is a divisor .. actually, let me rename it to `d', for consistency with the definition of `divides'
03:28:50 <ski> so
03:28:53 × luffy quits (~chenqisu1@183.217.203.170) (Max SendQ exceeded)
03:28:56 <ski> divisorsFrom d n
03:29:25 <ski> | d `divides` n = ..d..n..
03:29:45 <ski> | otherwise = ..d..n..
03:29:59 luffy joins (~chenqisu1@183.217.203.170)
03:30:26 <ski> in one case, we skip `d', calling recursively on `d-1'. in the other case we emit `d', and call recursive on `d-1'
03:30:29 <ski> divisorsFrom d n
03:30:42 <ski> | d `divides` n = d : divisorsFrom (d-1) n
03:30:51 <ski> | otherwise = divisorsFrom (d-1) n
03:31:01 <ski> Guest85 : this makes sense ?
03:31:04 frost joins (~frost@user/frost)
03:32:02 <Guest85> yes
03:32:18 <ski> now, a couple of minor points
03:32:25 <ski> looking at the base case
03:32:34 <ski> divisorsFrom 1 _ = [1]
03:32:48 <ski> we could actually "push back" this to one step lower, if we wanted to :
03:32:52 <ski> divisorsFrom 0 _ = []
03:33:28 <ski> that way the `1' divisor (which will always be a divisor) will be handled the same way, by the same code, that's handling all the other divisors, and added to the result in the same way
03:33:56 <ski> often, it can be a good thing to try to push back base cases to even simpler cases like this, even ones that might feel "useless"
03:35:11 <ski> (it can improve modularity of code, not having to make special cases elsewhere, when you do realize you can actually generate such a "useless" call. and it can add to number of useful reasoning and refactoring laws you can apply to your code. this also applies to data type design, not just to recursive functions)
03:35:17 × fef quits (~thedawn@user/thedawn) (Ping timeout: 258 seconds)
03:36:07 <Guest85> nods
03:36:42 <ski> however, in this case, it doesn't really matter, since `divisorsFrom' is only called from `divisors' anyway, noone will call `divisorsFrom' with `d' being `0', unless we do it ourselves (from `divisors' .. and if we want to handle `0', we actually ought to give a list of all integers, not the empty list .. so `divisorsFrom 0 _ = []' would be incorrect from that standpoint)
03:37:11 <ski> besides, we also added an extra call to `divides', which we *know* will always succeed
03:37:25 <ski> so, since there' not really any upside here, and there is a downside, we might not want to do this
03:37:34 <ski> (but it's a good consideration to have in mind)
03:37:48 <ski> now, let's do "the same" that we did for `product'
03:38:10 <ski> namely, instead of having a direct recursive solution, let's make an accumulative / tail-recursive solution
03:38:26 <ski> oh, actually, there was one other point i wanted to make first
03:38:44 <ski> there's no need to pass `n' around as a parameter to `divisorsFrom' .. we never change it
03:39:20 <ski> and since `divisorsFrom' is defined in a `where' attached to the `divisors' defining equation, it can just "grab `n' in the air", from that outer defining equation
03:39:26 <ski> which gives
03:39:38 <ski> divisors n = divisorsFrom n
03:39:43 <ski> where
03:39:52 <ski> divisorsFrom d
03:39:56 <ski> | d `divides` n = d : divisorsFrom (d-1)
03:40:02 <ski> | otherwise = divisorsFrom (d-1)
03:40:11 <ski> ok, anyway ..
03:40:57 <Guest85> I think this solution is what you're getting at
03:40:58 <Guest85> interpreter :: [String] -> [String]
03:40:58 <Guest85> interpreter commands = go 0 0 commands
03:40:59 <Guest85>   where go x y ("up":commands) = go x (y+1) commands
03:40:59 <Guest85>         go x y ("down":commands) = go x (y-1) commands
03:41:00 <Guest85>         go x y ("left":commands) = go (x-1) y commands
03:41:00 <Guest85>         go x y ("right":commands) = go (x+1) y commands
03:41:01 <Guest85>         go x y ("printX":commands) = show x : go x y commands
03:41:01 <Guest85>         go x y ("printY":commands) = show y : go x y commands
03:41:02 <Guest85>         go x y []                  = []
03:41:02 <Guest85>         go x y (_:commands)        = "BAD" : go x y commands
03:41:08 <Guest85> that uses tail recursion, no?
03:41:14 <ski> well
03:41:25 <ski> it's not a purely tail-recursive version, no
03:41:35 <ski> (although i think you're starting to get where i'm heading)
03:41:51 × codaraxis__ quits (~codaraxis@user/codaraxis) (Ping timeout: 260 seconds)
03:41:54 <ski> that version of `go' has both tail-recursive calls, and non-tail-recursive calls
03:42:12 <ski> (i should say "non-tail recursive calls", actually)
03:42:39 <ski> let's go through the motions for `divisors' quickly, and i'll get to the main point
03:42:43 <ski> we get
03:42:46 <Guest85> k
03:43:27 <ski> divisors n = reverse (divisorsFromAppend n [])
03:43:30 <ski> where
03:43:51 <ski> divisorsFrom 1 acc = 1 : acc
03:44:02 <ski> divisorsFrom d acc
03:44:46 <ski> | d `divides` n = divisorsFromAppend (d-1) (d : acc)
03:44:51 xff0x joins (~xff0x@2405:6580:b080:900:87ff:1eaa:6690:ed86)
03:45:03 <ski> | otherwise = divisorsFromAppend (d-1) acc
03:45:16 <ski> (sorry, replace `divisorsFrom' with `divisorsFromAppend' there)
03:45:42 <ski> so, we're adding items in backwards order (adding in front rather than at end to avoid left-nested `++'s), so we need to `reverse' at the end
03:45:59 <ski> .. or we could just count up from `1' towards `n' instead, and not have to `reverse'
03:46:15 <ski> anyway, the idea should hopefully be clear
03:46:30 <ski> now, which is better, the direct or the accumulating version ?
03:47:30 <ski> note that the accumulating version keeps all the generated items to itself, in `acc', until it reaches the base case, where it releases `1 : acc' as the result that is returned back to `divisors' (and then passed through `reverse' unless we change to count up instead of down)
03:47:46 <Guest85> depends?
03:48:21 <ski> while, the *direct* recursive version will actually make the items it's producing available to its caller (including the caller of `divisors') *as* it is progressing through its loop
03:49:43 fef joins (~thedawn@user/thedawn)
03:49:49 <ski> e.g. if you do `takeWhile (> 2) (divisors 6)', then `takeWhile' will skip looking at the rest of the list after the `2' in the result `[6,3,2,1]'. because Haskell is non-strict, this means that the recursive calls that would have produced `[1]' in this case never happens !
03:50:00 × fef quits (~thedawn@user/thedawn) (Client Quit)
03:50:34 <ski> so, `takeWhile' is able to abort our `divisorsFrom' loop, when it pleases, being able to decide after each output element it has been fed whether it cares to look for more or not
03:50:36 <Guest85> non-strict == lazy? as to why Haskell can work infinite lists
03:51:12 <ski> but this *can't* happen for the tail-recursive version (because there the recursive calls are not "guarded" by the list constructor `:', which is non-strict)
03:51:32 <ski> lazy is a particular implementation strategy to realize non-strict evaluation
03:51:51 king_gs joins (~Thunderbi@2806:103e:29:ac5e:a16e:4ac9:a89b:4d)
03:51:52 matthewmosior joins (~matthewmo@173.170.253.91)
03:51:55 <Guest85> interpreter :: [String] -> [String]
03:51:55 <Guest85> interpreter x = interpreter' x 0 0
03:51:56 <Guest85> interpreter' [] x y = []
03:51:56 <Guest85> interpreter' (coor:coors) x y
03:51:57 <Guest85>  | coor == "left" = interpreter' coors (x-1) y
03:51:57 <Guest85>  | coor == "right" = interpreter' coors (x+1) y
03:51:58 <Guest85>  | coor == "up" = interpreter' coors x (y+1)
03:51:58 <Guest85>  | coor == "down" = interpreter' coors x (y-1)
03:51:59 <Guest85>  | coor == "printX" = show x : interpreter' coors x y
03:51:59 <Guest85>  | coor == "printY" = show y : interpreter' coors x y
03:52:00 <Guest85>  | True = interpreter' coors x y
03:52:10 <ski> lazy (aka by-need) in particular means that a computation that is done will cache its result, so that it's not redone
03:53:09 <Guest85> so for this the direct recursion are here:
03:53:25 <Guest85>  | coor == "printX" = show x : interpreter' coors x y
03:53:25 <Guest85>  | coor == "printY" = show y : interpreter' coors x y
03:53:33 <Guest85> and the tail recursion here?:
03:53:36 <ski> Haskell does *not* require an implementation to be lazy (but most of them are. there was some that sometimes did speculative evaluation, passing off some computation that wasn't demanded yet to an idle processor core, in the hope that it will be needed in the future. but this needs to be coupled with a timeout, to not get stuck in an infinite loop. it should still behave as if didn't evaluate it, in case it
03:53:37 <Guest85>  | coor == "left" = interpreter' coors (x-1) y
03:53:38 <Guest85>  | coor == "right" = interpreter' coors (x+1) y
03:53:38 <Guest85>  | coor == "up" = interpreter' coors x (y+1)
03:53:39 <Guest85>  | coor == "down" = interpreter' coors x (y-1)
03:53:42 <ski> was never needed)
03:54:07 <ski> well. you can't really do much about those tai-recursions
03:54:34 <ski> they aren't really problems anyway, you're not building up an accumulator further in them (and you weren't, in your previous accumulating version)
03:55:13 <ski> it's these last two cases, for `"printX"' and `"printY"', which are the cases where we could apply this improvement, by going from accumulating, to direct (specifically guarded) recursion
03:56:22 <ski> note that the key difference between `divisors' and `product' is that in the case of `product' we had `n * product ns', and `*' is strict (will need to get value of both operands) (at least for the usual numeric types. you could make non-strict numeric types, where it could be better to use the non-tail recursive version)
03:56:38 <ski> while for `divisors' we had `d : divisorsFrom (d-1)'
03:56:43 <ski> `:' is non-strict
03:57:30 <Guest85> I kind of understand
03:57:36 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 265 seconds)
03:57:43 <Guest85> lost that other solution with fold
03:57:51 <ski> it stops right there, and returns control to the caller (`takeWhile' in my example above), which can then decide whether it wants to look at (the head `d' and) the tail `divisorsFrom (d-1)' .. only when/if `takeWhile' (or whatever your caller is) looks there, will the recursive call happen
03:57:54 <Guest85> somebody here had mentioned earlier
03:58:25 <ski> so, the direct recursive version of `divisors' acts like a "generator", that will present one element at a time to its caller, and the caller can abort
03:58:57 <ski> while the tail-recursive version is "bulky", not incremental, will always run to the end of its loop, before relinguishing control back to the caller
03:59:17 <Guest85> so in general tail recursion is sloweR?
03:59:20 <ski> ok .. i think this was basically what i wanted to cover here
03:59:28 <ski> it depends
03:59:37 <ski> sometimes tail-recursion is better
03:59:39 <ski> sometimes not
03:59:53 <Guest85> makes sense, thanks for going into such detail
04:00:02 <ski> in a strict functional language, tail-recursion would more commonly be the best choice
04:01:13 <ski> (sometimes the direct recursive version, the version you get when analyzing recursively, naïvely, without thinking about tail-recursion or accumulation, would automatically become tail-recursive, accumulative, possibly even without you realizing you're actually doing an accumulator)
04:02:20 <ski> (also, note that you can have an accumulating argument, without being tail-recursive (e.g. some, or all, recursive calls being non-tail calls). but the reason why people often try to consciously *introduce* accumulators are usually because they want a tail-recursive version)
04:02:53 <ski> Haskell lists are non-strict. someone said that it's often good to think of them not as a data structure, but as a "loop, waiting to happen"
04:03:35 <ski> it's this fact, them being non-strict (the data constructor `:' being non-strict), which enables you do to incremental, pieces-at-a-time, rather than bulky, all-at-once, algorithms
04:04:41 <ski> it's also possible to do such things in strict languages, with explicit delaying recursive calls behind function abstractions (lambdas / thunks) .. but it's a bit more noisy, usually, and there's less support (e.g. from compiler optimizations, and from library functions) for it
04:05:31 <ski> hence why tail-recursion is commonly more emphasized in strict languages (supporting tail recursion) like SML,Erlang,Scheme,OCaml,F#,Prolog,..
04:05:31 × vglfr quits (~vglfr@145.224.100.249) (Read error: Connection reset by peer)
04:05:51 <ski> but tail-recursion is *still* good to know about, and sometimes use, in Haskell as well
04:06:25 vglfr joins (~vglfr@145.224.100.249)
04:06:55 <Guest85> it's covered in some of the material I'm going through
04:07:06 <Guest85> I'm doing the Haskell MOOC, that's where I got that problem to solve
04:07:36 <ski> (it should also be said that tail-recursion, that gives an iterative process, basically a "loop", is sometimes inferior to a non-tail recursive version, for algorithmic reasons. e.g. merge sort and quick sort are better than insertion sort, selection sort, shell sort, even though the former are non-tail recursive, and the latter would be expressed as tail-recursive. this is because of the superior
04:07:42 <ski> *algorithm* for the former)
04:07:58 <ski> (and this holds true also in strict languages)
04:10:18 <ski> Guest85 : i hope it wasn't too painful to read the first part of my exposition, where i went into quite a bit more detail about recursive thinking, and associating reduction traces to different space complexity (stack usage), in a visual way. ime,it's not always that people get to hear about that kind of thing (although maybe you had seen that before). after that, i picked up pace a bit more
04:11:02 <Guest85> I've seen it broken down before to explain recursion
04:11:08 <ski> good
04:11:59 <ski> (in any case, i wanted both the `product' example, and the `divisors' example, to show how in one case tail-recursion was better, while in the other case it wasn't)
04:13:10 <ski> now, as i already mentioned, i would match on the strings in the "head" (the left-hand-side, the definiens, the thing to be defined, to the left of the `='s), rather than checking equality in guards
04:13:16 <ski> but that's more of a style thing
04:14:30 <ski> (also, instead of outputting `"BAD"' as a single item, and then still continuing to process the rest, i might decide to abort the whole process instead .. but one could decide differently here, depending of requirements and other considerations)
04:15:20 <ski> btw, if you wanted to, you could use `++' instead of `:' .. if you wanted to get a single `String' as result, instead of a list of `String's
04:15:21 <Guest85> that's what they did in the model solution, I just find guards easier right now
04:15:26 ski nods
04:15:31 <ski> then go with that
04:15:58 × vglfr quits (~vglfr@145.224.100.249) (Ping timeout: 265 seconds)
04:16:19 <ski> most important is that the code is understandable and as clear as reasonable to the intended reader(s) .. which is you, at this moment
04:16:22 matthewmosior joins (~matthewmo@173.170.253.91)
04:17:09 <ski> (one could opt to make it less clear than possible, e.g. to improve efficiency, or perhaps in some cases to improve composability and modularity)
04:17:45 <ski> Guest85 : anything more you're wondering about ?
04:18:26 <Guest85> not at the moment, though surely I will in the future
04:18:34 <Guest85> I'm off to sleep now, thanks again
04:18:46 <ski> ok, i hope this was fun and edifying
04:18:52 <Guest85> nods (:
04:19:01 <ski> (don't forget to have fun when learning ! it helps greatly with learning)
04:19:30 <Guest85> I'm going to practice a bit with TidalCycles again, that's always fun
04:19:39 <ski> you're welcome
04:19:45 × califax quits (~califax@user/califx) (Ping timeout: 258 seconds)
04:19:45 × adanwan quits (~adanwan@gateway/tor-sasl/adanwan) (Ping timeout: 258 seconds)
04:19:45 <ski> well, good night, then
04:19:51 <Guest85> night
04:20:11 × Guest85 quits (~Guest85@45.144.115.145) (Quit: Client closed)
04:21:50 adanwan joins (~adanwan@gateway/tor-sasl/adanwan)
04:21:51 califax joins (~califax@user/califx)
04:22:26 × ChaiTRex quits (~ChaiTRex@user/chaitrex) (Ping timeout: 258 seconds)
04:23:18 ChaiTRex joins (~ChaiTRex@user/chaitrex)
04:36:12 vglfr joins (~vglfr@145.224.100.100)
04:45:17 × limberdelt quits (~limberdel@gateway/vpn/pia/limberdelt) (Remote host closed the connection)
04:49:49 × nate2 quits (~nate@98.45.169.16) (Ping timeout: 265 seconds)
05:02:30 × hgolden quits (~hgolden@cpe-172-251-233-141.socal.res.rr.com) (Remote host closed the connection)
05:02:49 × mtjm quits (~mutantmel@2604:a880:2:d0::208b:d001) (Remote host closed the connection)
05:03:58 hgolden joins (~hgolden@cpe-172-251-233-141.socal.res.rr.com)
05:04:01 mtjm joins (~mutantmel@2604:a880:2:d0::208b:d001)
05:08:08 kenran joins (~kenran@200116b82bfc8c00506b0bf76983b11b.dip.versatel-1u1.de)
05:15:26 nate2 joins (~nate@98.45.169.16)
05:18:07 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 252 seconds)
05:18:41 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 260 seconds)
05:19:52 × nate2 quits (~nate@98.45.169.16) (Ping timeout: 246 seconds)
05:28:14 causal joins (~user@50.35.83.177)
05:30:37 takuan joins (~takuan@178-116-218-225.access.telenet.be)
05:34:00 × hgolden quits (~hgolden@cpe-172-251-233-141.socal.res.rr.com) (Remote host closed the connection)
05:35:23 hgolden joins (~hgolden@cpe-172-251-233-141.socal.res.rr.com)
05:35:49 × king_gs quits (~Thunderbi@2806:103e:29:ac5e:a16e:4ac9:a89b:4d) (Remote host closed the connection)
05:36:07 king_gs joins (~Thunderbi@2806:103e:29:ac5e:a16e:4ac9:a89b:4d)
05:36:40 × jao quits (~jao@cpc103048-sgyl39-2-0-cust502.18-2.cable.virginm.net) (Ping timeout: 246 seconds)
05:37:27 × johnw quits (~johnw@76-234-69-149.lightspeed.frokca.sbcglobal.net) (Quit: ZNC - http://znc.in)
05:45:10 matthewmosior joins (~matthewmo@173.170.253.91)
05:45:10 rockymarine joins (~rocky@user/rockymarine)
05:47:50 nate2 joins (~nate@98.45.169.16)
05:48:50 × hgolden quits (~hgolden@cpe-172-251-233-141.socal.res.rr.com) (Remote host closed the connection)
05:49:22 burnsidesLlama joins (~burnsides@119247164140.ctinets.com)
05:50:11 hgolden joins (~hgolden@cpe-172-251-233-141.socal.res.rr.com)
05:52:38 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 265 seconds)
05:53:07 × nate2 quits (~nate@98.45.169.16) (Ping timeout: 265 seconds)
05:56:53 coot joins (~coot@213.134.176.158)
06:04:45 bilegeek joins (~bilegeek@2600:1008:b042:1805:f458:6de8:d801:df30)
06:04:53 gmg joins (~user@user/gehmehgeh)
06:05:09 × coot quits (~coot@213.134.176.158) (Quit: coot)
06:05:21 coot joins (~coot@213.134.176.158)
06:08:31 × kenran quits (~kenran@200116b82bfc8c00506b0bf76983b11b.dip.versatel-1u1.de) (Quit: WeeChat info:version)
06:11:43 jinsun__ joins (~jinsun@user/jinsun)
06:11:44 × jinsun quits (~jinsun@user/jinsun) (Killed (molybdenum.libera.chat (Nickname regained by services)))
06:11:44 jinsun__ is now known as jinsun
06:13:19 rockymarine joins (~rocky@user/rockymarine)
06:13:43 mbuf joins (~Shakthi@49.204.135.71)
06:18:23 × bontaq` quits (~user@ool-45779fe5.dyn.optonline.net) (Ping timeout: 268 seconds)
06:18:30 Enrico63 joins (~Enrico63@81.109.143.226)
06:21:25 × Ram-Z quits (~Ram-Z@li1814-254.members.linode.com) (Remote host closed the connection)
06:21:51 Ram-Z joins (~Ram-Z@li1814-254.members.linode.com)
06:22:38 jinsun__ joins (~jinsun@user/jinsun)
06:22:39 jinsun is now known as Guest5343
06:22:39 × Guest5343 quits (~jinsun@user/jinsun) (Killed (sodium.libera.chat (Nickname regained by services)))
06:22:39 jinsun__ is now known as jinsun
06:23:13 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 246 seconds)
06:23:36 nate2 joins (~nate@98.45.169.16)
06:24:34 × sympt quits (~sympt@user/sympt) (Read error: Connection reset by peer)
06:26:59 edrx joins (~Eduardo@2804:56c:d2dc:ac00:dab8:211d:d4eb:fa94)
06:27:27 <edrx> hi all - in this expression
06:27:29 <edrx> createProcess (proc "ls" []) { std_out = CreatePipe }
06:28:05 <edrx> what is, syntactically, the "{ std_out = CreatePipe }"?
06:28:31 × nate2 quits (~nate@98.45.169.16) (Ping timeout: 252 seconds)
06:32:46 <sm> edrx: a record update, setting the stdout field of a record type returned by proc
06:33:09 × gmg quits (~user@user/gehmehgeh) (Ping timeout: 258 seconds)
06:33:56 <sm> uh, or maybe returned by createProcess
06:34:28 waldo joins (~waldo@user/waldo)
06:35:10 machinedgod joins (~machinedg@d198-53-218-113.abhsia.telus.net)
06:36:23 gmg joins (~user@user/gehmehgeh)
06:39:14 × coot quits (~coot@213.134.176.158) (Quit: coot)
06:39:26 coot joins (~coot@213.134.176.158)
06:40:12 <edrx> sm: thanks! =)
06:43:21 edrx parts (~Eduardo@2804:56c:d2dc:ac00:dab8:211d:d4eb:fa94) (Killed buffer)
06:49:41 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 260 seconds)
06:50:39 × burnsidesLlama quits (~burnsides@119247164140.ctinets.com) (Remote host closed the connection)
06:52:55 MoC joins (~moc@user/moc)
06:59:14 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
07:02:42 matthewmosior joins (~matthewmo@173.170.253.91)
07:06:55 × kimjetwav quits (~user@2607:fea8:235e:b600:3a8e:383d:7069:4bec) (Remote host closed the connection)
07:06:59 × Sgeo quits (~Sgeo@user/sgeo) (Read error: Connection reset by peer)
07:07:05 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 265 seconds)
07:21:12 matthewmosior joins (~matthewmo@173.170.253.91)
07:23:59 × kitty4 quits (~kitty@096-039-147-043.res.spectrum.com) (Quit: WeeChat 3.5)
07:26:26 burnsidesLlama joins (~burnsides@119247164140.ctinets.com)
07:26:55 × luffy quits (~chenqisu1@183.217.203.170) (Ping timeout: 246 seconds)
07:27:17 gurkenglas joins (~gurkengla@p548ac72e.dip0.t-ipconnect.de)
07:28:50 luffy joins (~chenqisu1@183.217.203.170)
07:30:46 × burnsidesLlama quits (~burnsides@119247164140.ctinets.com) (Ping timeout: 246 seconds)
07:33:16 titibandit joins (~titibandi@xdsl-87-78-162-143.nc.de)
07:35:17 × king_gs quits (~Thunderbi@2806:103e:29:ac5e:a16e:4ac9:a89b:4d) (Quit: king_gs)
07:36:46 chomwitt joins (~chomwitt@2a02:587:dc14:f500:27b7:f613:f2be:f46f)
07:37:59 `2jt joins (~jtomas@88.17.232.105)
07:43:17 <c_wraith> sm: returned by proc. record update binds more tightly than function application
07:43:45 × machinedgod quits (~machinedg@d198-53-218-113.abhsia.telus.net) (Quit: Lost terminal)
07:47:01 × Maeda quits (~Maeda@91-161-10-149.subs.proxad.net) (Quit: leaving)
07:47:58 nate2 joins (~nate@98.45.169.16)
07:50:44 zeenk joins (~zeenk@2a02:2f04:a311:2d00:6865:d863:4c93:799f)
07:53:21 × nate2 quits (~nate@98.45.169.16) (Ping timeout: 268 seconds)
08:04:14 × bilegeek quits (~bilegeek@2600:1008:b042:1805:f458:6de8:d801:df30) (Quit: Leaving)
08:06:06 × Enrico63 quits (~Enrico63@81.109.143.226) (Ping timeout: 252 seconds)
08:07:04 × titibandit quits (~titibandi@xdsl-87-78-162-143.nc.de) (Remote host closed the connection)
08:23:18 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 244 seconds)
08:24:22 razetime joins (~quassel@117.254.35.116)
08:26:02 × mjs2600 quits (~mjs2600@c-24-91-3-49.hsd1.vt.comcast.net) (Quit: ZNC 1.8.2 - https://znc.in)
08:26:17 mjs2600 joins (~mjs2600@c-24-91-3-49.hsd1.vt.comcast.net)
08:28:03 × luffy quits (~chenqisu1@183.217.203.170) (Ping timeout: 252 seconds)
08:32:49 luffy joins (~chenqisu1@183.217.203.170)
08:33:48 burnsidesLlama joins (~burnsides@119247164140.ctinets.com)
08:33:54 × ft quits (~ft@p3e9bc57b.dip0.t-ipconnect.de) (Quit: Lost terminal)
08:34:32 × luffy quits (~chenqisu1@183.217.203.170) (Max SendQ exceeded)
08:35:50 luffy joins (~chenqisu1@183.217.203.170)
08:37:43 × ChaiTRex quits (~ChaiTRex@user/chaitrex) (Remote host closed the connection)
08:38:19 ChaiTRex joins (~ChaiTRex@user/chaitrex)
08:39:25 × burnsidesLlama quits (~burnsides@119247164140.ctinets.com) (Ping timeout: 252 seconds)
08:39:47 nate2 joins (~nate@98.45.169.16)
08:40:18 × luffy quits (~chenqisu1@183.217.203.170) (Remote host closed the connection)
08:40:46 luffy joins (~chenqisu1@183.217.203.170)
08:41:37 × ec quits (~ec@gateway/tor-sasl/ec) (Remote host closed the connection)
08:41:49 × luffy quits (~chenqisu1@183.217.203.170) (Remote host closed the connection)
08:42:20 luffy joins (~chenqisu1@183.217.203.170)
08:43:03 × MoC quits (~moc@user/moc) (Quit: Konversation terminated!)
08:43:27 × razetime quits (~quassel@117.254.35.116) (Ping timeout: 252 seconds)
08:43:29 ec joins (~ec@gateway/tor-sasl/ec)
08:44:29 matthewmosior joins (~matthewmo@173.170.253.91)
08:44:37 × nate2 quits (~nate@98.45.169.16) (Ping timeout: 246 seconds)
08:44:47 MoC joins (~moc@user/moc)
08:46:51 beteigeuze joins (~Thunderbi@p5090d00a.dip0.t-ipconnect.de)
08:51:03 acidjnk joins (~acidjnk@p200300d6e7137a440dc2598308a8f039.dip0.t-ipconnect.de)
08:55:36 razetime joins (~quassel@117.254.35.116)
08:56:54 × ec quits (~ec@gateway/tor-sasl/ec) (Remote host closed the connection)
08:57:25 ec joins (~ec@gateway/tor-sasl/ec)
08:57:33 × hrberg quits (~quassel@171.79-160-161.customer.lyse.net) (Quit: https://quassel-irc.org - Chat comfortably. Anywhere.)
09:02:37 hrberg joins (~quassel@171.79-160-161.customer.lyse.net)
09:04:06 × tzh quits (~tzh@c-24-21-73-154.hsd1.or.comcast.net) (Quit: zzz)
09:04:50 burnsidesLlama joins (~burnsides@119247164140.ctinets.com)
09:08:14 jgeerds_ joins (~jgeerds@55d46bad.access.ecotel.net)
09:13:19 × gurkenglas quits (~gurkengla@p548ac72e.dip0.t-ipconnect.de) (Ping timeout: 246 seconds)
09:17:22 × eggplantade quits (~Eggplanta@108-201-191-115.lightspeed.sntcca.sbcglobal.net) (Remote host closed the connection)
09:20:23 jakalx parts (~jakalx@base.jakalx.net) ()
09:22:09 × vglfr quits (~vglfr@145.224.100.100) (Read error: Connection reset by peer)
09:22:21 vglfr joins (~vglfr@145.224.100.100)
09:24:15 ft joins (~ft@p3e9bc57b.dip0.t-ipconnect.de)
09:30:44 Logio joins (em@kapsi.fi)
09:32:04 × razetime quits (~quassel@117.254.35.116) (Ping timeout: 265 seconds)
09:32:19 razetime joins (~quassel@117.193.1.121)
09:42:41 jakalx joins (~jakalx@base.jakalx.net)
09:42:43 × jgeerds_ quits (~jgeerds@55d46bad.access.ecotel.net) (Ping timeout: 246 seconds)
09:46:30 michalz joins (~michalz@185.246.207.221)
09:46:37 × zeenk quits (~zeenk@2a02:2f04:a311:2d00:6865:d863:4c93:799f) (Quit: Konversation terminated!)
09:49:57 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 265 seconds)
09:56:21 × razetime quits (~quassel@117.193.1.121) (Quit: https://quassel-irc.org - Chat comfortably. Anywhere.)
09:58:57 × MoC quits (~moc@user/moc) (Quit: Konversation terminated!)
10:01:29 Lycurgus joins (~juan@user/Lycurgus)
10:02:02 kuribas joins (~user@ptr-17d51endqa8qjfim10g.18120a2.ip6.access.telenet.be)
10:12:12 × Lycurgus quits (~juan@user/Lycurgus) (Quit: Exeunt juan@acm.org)
10:14:05 × econo quits (uid147250@user/econo) (Quit: Connection closed for inactivity)
10:17:50 jgeerds_ joins (~jgeerds@55d46bad.access.ecotel.net)
10:17:51 eggplantade joins (~Eggplanta@108-201-191-115.lightspeed.sntcca.sbcglobal.net)
10:18:03 matthewmosior joins (~matthewmo@173.170.253.91)
10:20:32 Midjak joins (~Midjak@82.66.147.146)
10:22:20 × eggplantade quits (~Eggplanta@108-201-191-115.lightspeed.sntcca.sbcglobal.net) (Ping timeout: 265 seconds)
10:22:39 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 244 seconds)
10:23:37 × zaquest quits (~notzaques@5.130.79.72) (Read error: Connection reset by peer)
10:24:29 thyriaen joins (~thyriaen@2a02:8109:8340:686c:7383:e0e2:ad95:9fce)
10:26:35 Tuplanolla joins (~Tuplanoll@91-159-69-34.elisa-laajakaista.fi)
10:27:42 __monty__ joins (~toonn@user/toonn)
10:32:46 × mbuf quits (~Shakthi@49.204.135.71) (Ping timeout: 246 seconds)
10:33:24 beteigeuze1 joins (~Thunderbi@89.187.168.45)
10:34:16 × kuribas quits (~user@ptr-17d51endqa8qjfim10g.18120a2.ip6.access.telenet.be) (Ping timeout: 260 seconds)
10:34:52 × beteigeuze quits (~Thunderbi@p5090d00a.dip0.t-ipconnect.de) (Ping timeout: 246 seconds)
10:34:53 beteigeuze1 is now known as beteigeuze
10:35:34 matthewmosior joins (~matthewmo@173.170.253.91)
10:40:00 zaquest joins (~notzaques@5.130.79.72)
10:41:10 × jargon quits (~jargon@184.101.186.15) (Remote host closed the connection)
10:52:08 × bitdex quits (~bitdex@gateway/tor-sasl/bitdex) (Quit: = "")
11:04:30 Enrico63 joins (~Enrico63@81.109.143.226)
11:11:34 × thyriaen quits (~thyriaen@2a02:8109:8340:686c:7383:e0e2:ad95:9fce) (Remote host closed the connection)
11:19:10 × frost quits (~frost@user/frost) (Quit: Ping timeout (120 seconds))
11:20:31 alternateved joins (~user@staticline-31-183-146-203.toya.net.pl)
11:29:48 × fjMSX quits (~hypni2p@2.92.213.55) (Ping timeout: 264 seconds)
11:32:01 fjMSX joins (~hypni2p@2.92.213.55)
11:35:00 ellensol joins (~ellen@178-78-210-152.customers.ownit.se)
11:36:28 × `2jt quits (~jtomas@88.17.232.105) (Ping timeout: 246 seconds)
11:39:36 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 260 seconds)
11:41:17 × jmdaemon quits (~jmdaemon@user/jmdaemon) (Ping timeout: 252 seconds)
11:41:22 × acidjnk quits (~acidjnk@p200300d6e7137a440dc2598308a8f039.dip0.t-ipconnect.de) (Ping timeout: 246 seconds)
11:45:49 zeenk joins (~zeenk@2a02:2f04:a311:2d00:6865:d863:4c93:799f)
11:46:29 Lycurgus joins (~juan@user/Lycurgus)
11:51:25 matthewmosior joins (~matthewmo@173.170.253.91)
11:55:12 MoC joins (~moc@user/moc)
11:58:12 [itchyjunk] joins (~itchyjunk@user/itchyjunk/x-7353470)
11:58:36 MoC parts (~moc@user/moc) ()
12:04:13 Oiyqlk joins (~rscastilh@191-214-26-24.user.veloxzone.com.br)
12:05:32 × zeenk quits (~zeenk@2a02:2f04:a311:2d00:6865:d863:4c93:799f) (Quit: Konversation terminated!)
12:17:24 × Oiyqlk quits (~rscastilh@191-214-26-24.user.veloxzone.com.br) ()
12:19:10 × notzmv quits (~zmv@user/notzmv) (Ping timeout: 246 seconds)
12:21:42 × alternateved quits (~user@staticline-31-183-146-203.toya.net.pl) (Remote host closed the connection)
12:22:58 nate2 joins (~nate@98.45.169.16)
12:24:34 × nek0 quits (~nek0@2a01:4f8:222:2b41::12) (Quit: The Lounge - https://thelounge.chat)
12:27:34 × nate2 quits (~nate@98.45.169.16) (Ping timeout: 246 seconds)
12:32:50 × Lycurgus quits (~juan@user/Lycurgus) (Ping timeout: 265 seconds)
12:42:09 nek0 joins (~nek0@2a01:4f8:222:2b41::12)
12:44:42 jao joins (~jao@cpc103048-sgyl39-2-0-cust502.18-2.cable.virginm.net)
12:50:03 `2jt joins (~jtomas@88.17.232.105)
12:52:58 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
12:54:34 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 244 seconds)
12:59:56 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
13:06:53 × burnsidesLlama quits (~burnsides@119247164140.ctinets.com) (Remote host closed the connection)
13:09:40 matthewmosior joins (~matthewmo@173.170.253.91)
13:11:48 Oiyqlk joins (~rscastilh@191-214-26-24.user.veloxzone.com.br)
13:14:24 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 265 seconds)
13:16:13 × luffy quits (~chenqisu1@183.217.203.170) (Ping timeout: 246 seconds)
13:17:21 burnsidesLlama joins (~burnsides@119247164140.ctinets.com)
13:19:52 × chexum quits (~quassel@gateway/tor-sasl/chexum) (Quit: No Ping reply in 180 seconds.)
13:22:01 chexum joins (~quassel@gateway/tor-sasl/chexum)
13:29:04 kenran joins (~kenran@200116b82bfc8c00279f08e2bd7a5ad3.dip.versatel-1u1.de)
13:38:40 matthewmosior joins (~matthewmo@173.170.253.91)
13:41:58 × Enrico63 quits (~Enrico63@81.109.143.226) (Ping timeout: 252 seconds)
13:48:22 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
13:52:03 Guest13 joins (~Guest13@2001:9e8:33f8:8e00:38fe:ac62:3541:d7d4)
13:55:25 <Guest13> Hi, I always get the error
13:55:26 <Guest13>  error: Variable not in scope: chain :: t0 -> t
13:55:26 <Guest13> when running the function (Collatz function from a tutorial)
13:55:27 <Guest13> chain :: (Integral a) => a -> [a]
13:55:27 <Guest13> chain 1 = [1]
13:55:28 <Guest13> chain n
13:55:28 <Guest13>     | even n = n:chain (n `div` 2)
13:55:29 <Guest13>     | odd n = n:chain (n*3 + 1)
13:55:29 <Guest13> never saw the error before, what does it mean? Can anybody help?
13:56:04 <geekosaur> are you doing this in ghci?
13:56:17 <Guest13> yes
13:56:41 <Guest13> made a function in an hs file, loaded it in ghci and tried to run it there
13:56:42 <geekosaur> the whole thing has to be done in a single group, either on one line or using multiline input with :{ :}
13:56:51 <geekosaur> it will work better if you put it in a file, though
13:57:59 <Guest13> thanks for your help
13:58:43 <Guest13> but what is the meaning of the error? I'm trying to learn and understand Haskell at the moment.
14:01:27 acidjnk joins (~acidjnk@p200300d6e7137a44e06f3424b17412c0.dip0.t-ipconnect.de)
14:01:44 × vglfr quits (~vglfr@145.224.100.100) (Read error: Connection reset by peer)
14:02:11 <geekosaur> I'd think "Variable not in scope" is pretty obvious; because ghci doesn't group related lines together by itself, it can't find `chain` when it needs it
14:02:13 × jao quits (~jao@cpc103048-sgyl39-2-0-cust502.18-2.cable.virginm.net) (Remote host closed the connection)
14:02:46 <geekosaur> the rest of it is its best guess as the intended type, which it will usually get wrong because it doesn't know enough; you can ignore it for now
14:03:47 × burnsidesLlama quits (~burnsides@119247164140.ctinets.com) (Remote host closed the connection)
14:04:03 vglfr joins (~vglfr@145.224.100.100)
14:05:38 <Guest13> Okay, thanks for your help. It helped to find the bug. I had to save and reload my file in ghci/VSCode. Now it works. I'm just stupid :(
14:05:47 <geekosaur> ah
14:06:21 <geekosaur> I haven't used ghci from inside vscode yet, but similar things can happen with emacs; keeping two processes in sync like that is difficult at best
14:06:21 <Guest13> So there has been no chain function at all (y)
14:06:42 <ski> `:reload' (or `:r') can be used to reload files in the interactor
14:06:52 <Guest13> thanks(y)
14:06:55 <geekosaur> I would guess it sent `n:chain (n `div` 2)` to ghci without the rest of it
14:06:55 <ski> sounds consistent with the error message, Guest13
14:08:04 <geekosaur> hm, no, that would add a Num and Integral constraint to the rather useless type it reported.
14:08:26 × Oiyqlk quits (~rscastilh@191-214-26-24.user.veloxzone.com.br) ()
14:08:27 jao joins (~jao@cpc103048-sgyl39-2-0-cust502.18-2.cable.virginm.net)
14:08:37 <ski> usually i do changes, save, do `:r' in the interactor, then either investigate errors, starting over, or (possibly) try out example expressions before starting over
14:09:52 <ski> hm, i guess e.g. `chain n' would do
14:10:34 <Guest13> *Main> chain 10
14:10:35 <Guest13> [10,5,16,8,4,2,1]
14:10:36 <Guest13> works fine now!
14:10:36 <Guest13> Thanx again for your help!
14:11:29 <ski> hm .. one could factor out the common "put input parameter as first element in output list" part, from all the three cases
14:12:26 × chexum quits (~quassel@gateway/tor-sasl/chexum) (Remote host closed the connection)
14:12:46 chexum joins (~quassel@gateway/tor-sasl/chexum)
14:15:25 × vglfr quits (~vglfr@145.224.100.100) (Remote host closed the connection)
14:16:09 vglfr joins (~vglfr@145.224.100.100)
14:19:49 × vglfr quits (~vglfr@145.224.100.100) (Remote host closed the connection)
14:20:23 vglfr joins (~vglfr@145.224.100.100)
14:21:38 eggplantade joins (~Eggplanta@108-201-191-115.lightspeed.sntcca.sbcglobal.net)
14:22:36 × vglfr quits (~vglfr@145.224.100.100) (Read error: Connection reset by peer)
14:22:56 × Guest13 quits (~Guest13@2001:9e8:33f8:8e00:38fe:ac62:3541:d7d4) (Quit: Client closed)
14:23:03 Athas_ joins (athas@2a01:7c8:aaac:1cf:5a6a:37a5:b994:6597)
14:23:36 odnes joins (~odnes@ppp089210198232.access.hol.gr)
14:23:56 × Athas quits (athas@sigkill.dk) (Ping timeout: 244 seconds)
14:24:11 Enrico63 joins (~Enrico63@81.109.143.226)
14:25:11 vglfr joins (~vglfr@145.224.100.100)
14:25:52 × eggplantade quits (~Eggplanta@108-201-191-115.lightspeed.sntcca.sbcglobal.net) (Ping timeout: 246 seconds)
14:28:39 × Midjak quits (~Midjak@82.66.147.146) (Read error: Connection reset by peer)
14:34:00 × sagax quits (~sagax_nb@user/sagax) (Ping timeout: 264 seconds)
14:37:14 burnsidesLlama joins (~burnsides@119247164140.ctinets.com)
14:40:16 wroathe joins (~wroathe@206-55-188-8.fttp.usinternet.com)
14:40:16 × wroathe quits (~wroathe@206-55-188-8.fttp.usinternet.com) (Changing host)
14:40:16 wroathe joins (~wroathe@user/wroathe)
14:40:59 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 244 seconds)
14:41:37 × burnsidesLlama quits (~burnsides@119247164140.ctinets.com) (Ping timeout: 246 seconds)
14:52:57 Sgeo joins (~Sgeo@user/sgeo)
14:54:39 matthewmosior joins (~matthewmo@173.170.253.91)
14:59:17 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 265 seconds)
15:00:25 nate2 joins (~nate@98.45.169.16)
15:08:01 × Athas_ quits (athas@2a01:7c8:aaac:1cf:5a6a:37a5:b994:6597) (Quit: ZNC 1.8.2 - https://znc.in)
15:09:28 Athas joins (athas@2a01:7c8:aaac:1cf:5a6a:37a5:b994:6597)
15:10:24 × euandreh quits (~euandreh@179.214.113.107) (Ping timeout: 265 seconds)
15:14:41 × chexum quits (~quassel@gateway/tor-sasl/chexum) (Remote host closed the connection)
15:15:38 chexum joins (~quassel@gateway/tor-sasl/chexum)
15:16:17 matthewmosior joins (~matthewmo@173.170.253.91)
15:16:48 × waldo quits (~waldo@user/waldo) (Quit: quit)
15:17:38 waldo joins (~waldo@user/waldo)
15:17:46 euandreh joins (~euandreh@179.214.113.107)
15:18:46 × kenran quits (~kenran@200116b82bfc8c00279f08e2bd7a5ad3.dip.versatel-1u1.de) (Quit: WeeChat info:version)
15:22:26 × Enrico63 quits (~Enrico63@81.109.143.226) (Ping timeout: 252 seconds)
15:34:09 ddellacosta joins (~ddellacos@143.244.47.68)
15:38:31 sagax joins (~sagax_nb@user/sagax)
15:39:39 weier joins (~z@219.70.204.146)
15:40:24 × weier quits (~z@219.70.204.146) (Client Quit)
15:41:28 × vglfr quits (~vglfr@145.224.100.100) (Ping timeout: 246 seconds)
15:48:37 chexum_ joins (~quassel@gateway/tor-sasl/chexum)
15:50:26 × sudden quits (~cat@user/sudden) (Ping timeout: 260 seconds)
15:51:23 burnsidesLlama joins (~burnsides@119247164140.ctinets.com)
15:51:54 rockymarine joins (~rocky@user/rockymarine)
15:52:49 × chexum quits (~quassel@gateway/tor-sasl/chexum) (Ping timeout: 258 seconds)
15:54:12 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
15:55:23 × jgeerds_ quits (~jgeerds@55d46bad.access.ecotel.net) (Ping timeout: 252 seconds)
15:56:12 × burnsidesLlama quits (~burnsides@119247164140.ctinets.com) (Ping timeout: 264 seconds)
15:56:23 × odnes quits (~odnes@ppp089210198232.access.hol.gr) (Quit: Leaving)
16:03:00 × gentauro quits (~gentauro@user/gentauro) (Read error: Connection reset by peer)
16:03:49 × nate2 quits (~nate@98.45.169.16) (Ping timeout: 252 seconds)
16:08:26 gentauro joins (~gentauro@user/gentauro)
16:08:45 vglfr joins (~vglfr@145.224.100.190)
16:14:22 × ddellacosta quits (~ddellacos@143.244.47.68) (Ping timeout: 246 seconds)
16:18:38 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 244 seconds)
16:18:56 dsrt^ joins (~dsrt@173-160-76-137-atlanta.hfc.comcastbusiness.net)
16:20:28 eggplantade joins (~Eggplanta@108-201-191-115.lightspeed.sntcca.sbcglobal.net)
16:23:23 johnw joins (~johnw@2600:1700:cf00:db0:dd60:bc61:a3c9:2dac)
16:23:58 matthewmosior joins (~matthewmo@173.170.253.91)
16:26:59 × Vajb quits (~Vajb@2001:999:504:1841:9e47:1ec7:a52e:1d57) (Read error: Connection reset by peer)
16:27:24 Vajb joins (~Vajb@hag-jnsbng11-58c3a5-27.dhcp.inet.fi)
16:28:08 machinedgod joins (~machinedg@d198-53-218-113.abhsia.telus.net)
16:28:42 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 265 seconds)
16:31:31 × coot quits (~coot@213.134.176.158) (Ping timeout: 246 seconds)
16:31:56 khumba joins (~khumba@user/khumba)
16:32:46 coot joins (~coot@89-76-160-4.dynamic.chello.pl)
16:36:08 jakalx parts (~jakalx@base.jakalx.net) ()
16:36:13 jakalx joins (~jakalx@base.jakalx.net)
16:38:51 × `2jt quits (~jtomas@88.17.232.105) (Ping timeout: 260 seconds)
16:39:52 × Vajb quits (~Vajb@hag-jnsbng11-58c3a5-27.dhcp.inet.fi) (Read error: Connection reset by peer)
16:40:08 Vajb joins (~Vajb@2001:999:504:1841:9e47:1ec7:a52e:1d57)
16:41:19 × acidjnk quits (~acidjnk@p200300d6e7137a44e06f3424b17412c0.dip0.t-ipconnect.de) (Ping timeout: 246 seconds)
16:48:40 × wroathe quits (~wroathe@user/wroathe) (Ping timeout: 246 seconds)
16:50:50 acidjnk joins (~acidjnk@p200300d6e7137a459951f5994426b03a.dip0.t-ipconnect.de)
16:57:46 econo joins (uid147250@user/econo)
17:01:23 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
17:02:01 matthewmosior joins (~matthewmo@173.170.253.91)
17:02:33 jgeerds_ joins (~jgeerds@55d46bad.access.ecotel.net)
17:04:16 × coot quits (~coot@89-76-160-4.dynamic.chello.pl) (Quit: coot)
17:04:29 coot joins (~coot@89-76-160-4.dynamic.chello.pl)
17:09:05 × coot quits (~coot@89-76-160-4.dynamic.chello.pl) (Client Quit)
17:09:12 nate2 joins (~nate@98.45.169.16)
17:09:20 coot joins (~coot@89-76-160-4.dynamic.chello.pl)
17:10:25 phao joins (~phao@200-181-211-177.user3p.brasiltelecom.net.br)
17:11:30 × phao quits (~phao@200-181-211-177.user3p.brasiltelecom.net.br) (Client Quit)
17:17:48 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 264 seconds)
17:19:24 wroathe joins (~wroathe@50.205.197.50)
17:19:25 × wroathe quits (~wroathe@50.205.197.50) (Changing host)
17:19:25 wroathe joins (~wroathe@user/wroathe)
17:20:38 × pavonia quits (~user@user/siracusa) (Quit: Bye!)
17:23:14 <EvanR> I heard HashMap "is better" for string keys than Map. But, ... doesn't it need to hash the entire string argument, whereas Map only looks at enough string to discriminate enough keys
17:23:47 × coot quits (~coot@89-76-160-4.dynamic.chello.pl) (Quit: coot)
17:24:00 coot joins (~coot@89-76-160-4.dynamic.chello.pl)
17:24:46 <hpc> generally your keys are small and you have many of them
17:27:07 × ChaiTRex quits (~ChaiTRex@user/chaitrex) (Remote host closed the connection)
17:27:54 ChaiTRex joins (~ChaiTRex@user/chaitrex)
17:28:01 × coot quits (~coot@89-76-160-4.dynamic.chello.pl) (Client Quit)
17:28:15 coot joins (~coot@89-76-160-4.dynamic.chello.pl)
17:29:50 nate3 joins (~nate@98.45.169.16)
17:30:06 tzh joins (~tzh@c-24-21-73-154.hsd1.or.comcast.net)
17:30:45 <c_wraith> honestly, the way Map approaches Strings (via Ord) isn't great either.
17:31:08 <c_wraith> You'd really want some sort of trie to avoid repeated comparison of portions that don't matter
17:31:26 rockymarine joins (~rocky@user/rockymarine)
17:31:27 × nate2 quits (~nate@98.45.169.16) (Ping timeout: 252 seconds)
17:31:28 sudden joins (~cat@user/sudden)
17:31:29 <EvanR> yeah a trie seems better than either? at least for longer strings
17:31:41 <c_wraith> well. for when there are a lot of common prefixes
17:32:33 × nahcetan quits (~nate@98.45.169.16) (Ping timeout: 252 seconds)
17:34:03 nahcetan joins (~nate@98.45.169.16)
17:41:13 × euandreh quits (~euandreh@179.214.113.107) (Ping timeout: 265 seconds)
17:42:13 euandreh joins (~euandreh@179.214.113.107)
17:44:44 × nate3 quits (~nate@98.45.169.16) (Ping timeout: 268 seconds)
17:46:59 raym joins (~raym@user/raym)
17:49:44 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
17:50:23 × wroathe quits (~wroathe@user/wroathe) (Ping timeout: 265 seconds)
17:54:56 vorpuni joins (~pvorp@2001:861:3881:c690:488:11ee:612d:7b91)
18:02:23 wroathe joins (~wroathe@50.205.197.50)
18:02:24 × wroathe quits (~wroathe@50.205.197.50) (Changing host)
18:02:24 wroathe joins (~wroathe@user/wroathe)
18:06:21 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 260 seconds)
18:09:16 burnsidesLlama joins (~burnsides@119247164140.ctinets.com)
18:13:13 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
18:14:46 × burnsidesLlama quits (~burnsides@119247164140.ctinets.com) (Ping timeout: 246 seconds)
18:17:25 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 268 seconds)
18:18:54 zeenk joins (~zeenk@2a02:2f04:a311:2d00:6865:d863:4c93:799f)
18:18:58 × wroathe quits (~wroathe@user/wroathe) (Ping timeout: 246 seconds)
18:22:06 acidjnk_new joins (~acidjnk@p200300d6e7137a459951f5994426b03a.dip0.t-ipconnect.de)
18:22:24 × coot quits (~coot@89-76-160-4.dynamic.chello.pl) (Quit: coot)
18:25:25 coot joins (~coot@89-76-160-4.dynamic.chello.pl)
18:25:36 × acidjnk quits (~acidjnk@p200300d6e7137a459951f5994426b03a.dip0.t-ipconnect.de) (Ping timeout: 260 seconds)
18:25:39 × coot quits (~coot@89-76-160-4.dynamic.chello.pl) (Remote host closed the connection)
18:25:50 coot joins (~coot@89-76-160-4.dynamic.chello.pl)
18:28:57 rockymarine joins (~rocky@user/rockymarine)
18:29:06 nate3 joins (~nate@98.45.169.16)
18:29:07 × coot quits (~coot@89-76-160-4.dynamic.chello.pl) (Client Quit)
18:29:57 coot joins (~coot@89-76-160-4.dynamic.chello.pl)
18:30:07 × coot quits (~coot@89-76-160-4.dynamic.chello.pl) (Remote host closed the connection)
18:30:18 coot joins (~coot@89-76-160-4.dynamic.chello.pl)
18:31:00 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
18:35:04 QNX is now known as SystemV
18:35:17 × coot quits (~coot@89-76-160-4.dynamic.chello.pl) (Quit: coot)
18:35:20 matthewmosior joins (~matthewmo@173.170.253.91)
18:37:46 × nate3 quits (~nate@98.45.169.16) (Ping timeout: 268 seconds)
18:39:28 coot joins (~coot@89-76-160-4.dynamic.chello.pl)
18:39:44 × coot quits (~coot@89-76-160-4.dynamic.chello.pl) (Remote host closed the connection)
18:39:55 coot joins (~coot@89-76-160-4.dynamic.chello.pl)
18:40:51 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 268 seconds)
18:51:47 × Lord_of_Life quits (~Lord@user/lord-of-life/x-2819915) (Ping timeout: 265 seconds)
18:52:37 Lord_of_Life joins (~Lord@user/lord-of-life/x-2819915)
19:00:03 moonsheep joins (~user@user/moonsheep)
19:00:10 moonsheep parts (~user@user/moonsheep) ()
19:07:34 rockymarine joins (~rocky@user/rockymarine)
19:12:41 × tomgus1 quits (~tomgus1@2a02:c7e:4229:d900:dea6:32ff:fe3d:d1a3) (Read error: Connection reset by peer)
19:12:57 tomgus1 joins (~tomgus1@2e40cd7e.skybroadband.com)
19:13:21 raehik joins (~raehik@cpc95906-rdng25-2-0-cust156.15-3.cable.virginm.net)
19:21:36 × vglfr quits (~vglfr@145.224.100.190) (Remote host closed the connection)
19:22:18 vglfr joins (~vglfr@145.224.100.190)
19:22:20 × vglfr quits (~vglfr@145.224.100.190) (Remote host closed the connection)
19:22:29 moonsheep joins (~user@user/moonsheep)
19:24:12 vglfr joins (~vglfr@145.224.100.190)
19:24:18 × zeenk quits (~zeenk@2a02:2f04:a311:2d00:6865:d863:4c93:799f) (Quit: Konversation terminated!)
19:26:12 <moonsheep> How should I handle exceptions with mtl-style transformers? I understand the *proper* way to handle exceptions is to use 'bracket' and its siblings, but unfortunately bracket requires you to pass it an IO computation.
19:26:22 <moonsheep> Is there any reason bracket couldn't take a MonadIO?
19:27:05 <geekosaur> how does it manufacture a value for a State on failure?
19:27:08 <moonsheep> And either way, how should I go about handling exceptions inside monad stacks where IO is nested potentially several layers deep?
19:27:31 <moonsheep> geekosaur: hmm, fair enough
19:27:50 <moonsheep> What is my best bet then?
19:28:07 <moonsheep> Add a ton of boilerplate to thread my mtl stack into the bracket?
19:28:23 <[Leary]> moonsheep: Look into unliftio. It's created to be the answer to this question.
19:28:34 × vglfr quits (~vglfr@145.224.100.190) (Remote host closed the connection)
19:28:53 <moonsheep> Oh interesting, didn't know about it
19:29:02 <moonsheep> I'll give it a look
19:29:25 vglfr joins (~vglfr@145.224.100.190)
19:30:00 × vglfr quits (~vglfr@145.224.100.190) (Remote host closed the connection)
19:30:01 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 246 seconds)
19:31:12 <moonsheep> [Leary]: this seems to be exactly what I wanted, thanks!
19:32:43 vglfr joins (~vglfr@145.224.100.190)
19:33:58 <johnw> moonsheep: https://hackage.haskell.org/package/exceptions-0.10.5/docs/Control-Monad-Catch.html#v:bracket
19:34:19 <johnw> I don't think any MonadIO m is automatically a MonadMask m
19:34:52 `2jt joins (~jtomas@88.17.232.105)
19:34:56 <johnw> but yes, unliftio is a specialization of what MonadBaseControl does
19:35:32 × vglfr quits (~vglfr@145.224.100.190) (Remote host closed the connection)
19:35:55 vglfr joins (~vglfr@145.224.100.190)
19:36:57 × vglfr quits (~vglfr@145.224.100.190) (Remote host closed the connection)
19:37:38 vglfr joins (~vglfr@145.224.100.190)
19:37:46 × tomgus1 quits (~tomgus1@2e40cd7e.skybroadband.com) (Quit: ZNC 1.8.2+deb2 - https://znc.in)
19:38:55 tomgus1 joins (~tomgus1@2a02:c7e:4229:d900:dea6:32ff:fe3d:d1a3)
19:39:41 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 260 seconds)
19:41:20 <moonsheep> johnw: oh thanks, I think I'll go with unliftio though
19:43:36 × zaquest quits (~notzaques@5.130.79.72) (Remote host closed the connection)
19:44:34 rockymarine joins (~rocky@user/rockymarine)
19:47:26 pavonia joins (~user@user/siracusa)
19:48:13 × jgeerds_ quits (~jgeerds@55d46bad.access.ecotel.net) (Ping timeout: 246 seconds)
19:48:32 david joins (~david@2a01:e34:ec2b:d430:44a:f5ca:9867:d69d)
19:48:41 <david> Hello !
19:48:49 <david> I have a question
19:49:09 <geekosaur> ask!
19:49:16 <david> How can you map "* | undefined" to Just * | Nothing ?
19:49:31 <ski> no
19:49:34 <geekosaur> you can't treat undefined as a value
19:49:44 <david> ok
19:49:52 <david> let me try another way
19:50:09 <ski> `foo _ Nothing' defines `foo' to map `undefined' to `Nothing', but also everything else to `Nothing'
19:50:17 <david> I have a read implementation that maps a char to a value
19:50:42 <david> how could I handl the fact that a given char is not in the acceptable range for this function?
19:50:52 caryhartline joins (~caryhartl@2600:1700:2d0:8d30:cd27:ded2:4351:8688)
19:51:03 <EvanR> map char to Maybe value?
19:51:09 × raehik quits (~raehik@cpc95906-rdng25-2-0-cust156.15-3.cable.virginm.net) (Ping timeout: 268 seconds)
19:51:12 <ski> `foo Something = Just SomethingElse' makes `foo' map `Something' to `Just SomethingElse', but will map `undefined' to `undefined' (or more specifically, map any "undefined value" to an "undefined value")
19:51:37 kenran joins (~kenran@200116b82bfc8c0061dac18751f3996d.dip.versatel-1u1.de)
19:51:49 <david> EvanR: thank you, I will try this.
19:51:59 <ski> the only way to map `undefined' to something that's not undefined, is to map everything to that not-undefined something
19:52:12 <ski> otherwise, you'll always map undefined/bottom to undefined/bottom
19:52:30 <david> ok, crystal clear ski, thanks !
19:52:39 <ski> `Maybe Value' or maybe `[Value]' sounds like what you'd want, yea
19:52:40 <EvanR> as long as you only deal in "defineds" it's a lot simpler xD
19:53:03 <ski> you shouldn't think of `undefined' as a value which you can handle, recognize
19:53:21 <johnw> that would indeed be giving it some definition
19:53:56 <ski> it is unknown whether `head (filter oddPerfectNumber [0 ..])' will give a defined number or not
19:54:36 <EvanR> so you got your known defineds, known undefineds, and unknown (un)defined
19:55:37 <ski> you can have computations which you don't know whether they'll terminate. if you build one which you know won't terminate, then Haskell still won't know that (e.g. `last [0 ..]' or `filter odd [0,2 ..]'). Haskell can only try evaluate it, and keep going. "nontermination" is not observable
19:58:33 <ski> (then Haskell also throws in partiality, like `head []' into the "bottom" or "undefined values", because, well .. they are not giving back proper values to you. these do terminate (in the sense of aborting the computation, rather than giving a result value), but you can't observe this, in "pure Haskell" (you can catch it in `IO', if you really want/need to. but you probably should try to avoid that, if you
19:58:39 <ski> can. it's better if you can signal such failures in other ways, like `Nothing' or `[]'. using `IO' to catch it indicates a failure to use proper failure-signalling means. sometimes it may be necessary, but it's regrettable))
19:59:49 <EvanR> use head only if it won't fail
19:59:57 <EvanR> and sometimes not even then!
20:00:42 <ski> to a first approximation, from the point of view of Haskell's semantics, both `head []' (partiality) and `last [0 ..]' (nontermination) are treated as if they're interchangable, nondistinguishable. both are "undefined/bottom 'values'" (in fact, the variable `undefined' is bound to a partial computation (calling `error', i believe), rather than a non-terminating one)
20:00:53 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 265 seconds)
20:01:21 <ski> in `error "foo" + error "bar"', you can't depend on which of the two reasons for partiality that you'll get, if you catch this in `IO'
20:02:45 matthewmosior joins (~matthewmo@173.170.253.91)
20:02:48 <ski> @remember EvanR so you got your known defineds, known undefineds, and unknown (un)defined
20:02:48 <lambdabot> Done.
20:03:04 <EvanR> +s
20:03:34 <EvanR> I'd use correct spelling if I knew the quotation paparazzi showed up
20:03:42 <ski> @forget EvanR so you got your known defineds, known undefineds, and unknown (un)defined
20:03:43 <lambdabot> Done.
20:03:45 <ski> @remember EvanR so you got your known defineds, known undefineds, and unknown (un)defineds
20:03:46 <lambdabot> Nice!
20:03:47 <EvanR> lol
20:03:48 <ski> better ? :)
20:04:11 jnz joins (~jnz@81.143.79.83.dynamic.wline.res.cust.swisscom.ch)
20:04:16 jnz is now known as undefined
20:04:23 undefined is now known as jnz
20:04:37 <EvanR> rumsfeld would have made a great haskeller
20:04:59 ski . o O ( are there unknown knowns ? 9
20:05:42 <dolio> Yeah. That's what Star Wars is all about.
20:06:27 ski wouldn't know
20:07:02 <byorgey> dolio, lol
20:07:23 rockymarine joins (~rocky@user/rockymarine)
20:08:15 × coot quits (~coot@89-76-160-4.dynamic.chello.pl) (Quit: coot)
20:09:09 × jnz quits (~jnz@81.143.79.83.dynamic.wline.res.cust.swisscom.ch) (Remote host closed the connection)
20:09:21 <johnw> hi byorgey!
20:10:16 moonsheep parts (~user@user/moonsheep) (ERC 5.4 (IRC client for GNU Emacs 28.2))
20:10:16 <byorgey> hi johnw!
20:11:27 <ski> david : ooc, what's your `Read' implementation ?
20:11:39 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 244 seconds)
20:13:04 <ski> .. i guess you could think of bottoms as being "landmines" or "bear traps"
20:14:16 <ski> if you don't approach them, you're fine (like the `foo _ = Nothing', calling `foo undefined' doesn't look at `undefined')
20:14:39 <ski> but if you do investigate them (like `foo Something = Just SomethingElse', where `foo undefined' will try to check if `undefined' is `Something' as so trip over), you either blow up (partiality), or you're stuck (non-termination)
20:17:08 pera joins (~pera@user/pera)
20:17:48 jnz joins (~jnz@81.143.79.83.dynamic.wline.res.cust.swisscom.ch)
20:18:29 <DigitalKiwi> https://www.dropbox.com/s/s047emghqja7cc7/2019-07-18%2012.10.53.jpg?dl=0
20:19:51 jnz44 joins (~jnz@81.143.79.83.dynamic.wline.res.cust.swisscom.ch)
20:20:34 × albet70 quits (~xxx@2400:8902::f03c:92ff:fe60:98d8) (Remote host closed the connection)
20:20:45 <ski> sounds like someone's been into the Sierpinski space .. or maybe lattices or Boolean algebras
20:23:57 <EvanR> in haskell there is a bottom but no top. So it's like temperature. Some languages imagine that there's a complete universe of values and define the top. So they have absolute zero and infinite temperature there
20:24:10 <EvanR> so it's like temperature
20:26:41 albet70 joins (~xxx@2400:8902::f03c:92ff:fe60:98d8)
20:27:17 <hpc> some physical objects can temporarily behave like they have negative temperature
20:27:47 <hpc> i wonder if you can write a negative type
20:28:25 × jnz44 quits (~jnz@81.143.79.83.dynamic.wline.res.cust.swisscom.ch) (Quit: jnz44)
20:28:58 <byorgey> hpc: https://dl.acm.org/doi/pdf/10.1145/3434290
20:29:11 jnz73 joins (~jnz@81.143.79.83.dynamic.wline.res.cust.swisscom.ch)
20:29:13 × jnz73 quits (~jnz@81.143.79.83.dynamic.wline.res.cust.swisscom.ch) (Client Quit)
20:30:18 Lycurgus joins (~juan@user/Lycurgus)
20:31:01 jgeerds_ joins (~jgeerds@55d46bad.access.ecotel.net)
20:31:02 rockymarine joins (~rocky@user/rockymarine)
20:31:12 × jnz quits (~jnz@81.143.79.83.dynamic.wline.res.cust.swisscom.ch) (Remote host closed the connection)
20:31:42 <EvanR> negative types reverse time while fractional types reverse space. Got it
20:32:37 <EvanR> that's some dr strange shit
20:34:14 <Lycurgus> time is at least a scalar, 'space' is polysemous
20:34:14 × `2jt quits (~jtomas@88.17.232.105) (Ping timeout: 265 seconds)
20:34:42 Null_A joins (~null_a@2601:645:8700:ac10:1005:19fc:119b:3387)
20:34:47 × gmg quits (~user@user/gehmehgeh) (Quit: Leaving)
20:35:02 <Lycurgus> and by scalar I meant a single coherent concept
20:35:49 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 246 seconds)
20:37:38 <darkling> Depends on how fast you're moving.
20:37:49 jmdaemon joins (~jmdaemon@user/jmdaemon)
20:37:51 <Lycurgus> that time could be reversed is pretty much the shibboleth misextension of a concept or at least coequal with substantive space
20:38:01 × Null_A_ quits (~null_a@2601:645:8700:ac10:588d:dcc4:cf71:c2f0) (Ping timeout: 244 seconds)
20:39:02 <Lycurgus> with similar coherence which is why it so worked in mass media production
20:39:14 <Lycurgus> *it's
20:39:38 raehik joins (~raehik@cpc95906-rdng25-2-0-cust156.15-3.cable.virginm.net)
20:40:08 × dsrt^ quits (~dsrt@173-160-76-137-atlanta.hfc.comcastbusiness.net) (Remote host closed the connection)
20:40:20 waleee joins (~waleee@h-176-10-137-138.NA.cust.bahnhof.se)
20:41:55 <byorgey> "negative types reverse time" is of course just a cool-sounding slogan. More accurately, that paper proposes that negative types can be thought of as reversing control flow.
20:42:15 <EvanR> goto => comefrom
20:42:45 <Lycurgus> ah
20:42:58 ski . o O ( "The Two Dualities of Computation: Negative and Fractional Types" by Roshan P. James,Amr Sabry in ~2012 at <https://legacy.cs.indiana.edu/~sabry/papers/rational.pdf> ; "Fractional Types" by Roshan P. James,Zachary Sparks,Jacques Carette,Amr Sabry in ~2013 at <https://legacy.cs.indiana.edu/~sabry/papers/fractionals.pdf> )
20:43:09 ski . o O ( <https://mathoverflow.net/questions/100158/negative-objects-in-categories>,<https://golem.ph.utexas.edu/category/2009/08/the_pi_calculus.html>,<https://www.reddit.com/r/haskell/comments/6e7s58/negative_and_fractional_types_in_haskell/>,<https://www.reddit.com/r/haskell/comments/25ujqk/is_there_any_implementation_for_this_paper_about/> )
20:43:15 ski . o O ( "Fractional power of units of measures in F#" <https://stackoverflow.com/questions/11333135/fractional-power-of-units-of-measures-in-f> ; "Semi--vector spaces and units of measurement" by Josef Janyška,Marco Modugno,Raffaele Vitolo in 2007-10-05 at <https://arxiv.org/abs/0710.1313v1> )
20:47:26 wroathe joins (~wroathe@206-55-188-8.fttp.usinternet.com)
20:47:27 × wroathe quits (~wroathe@206-55-188-8.fttp.usinternet.com) (Changing host)
20:47:27 wroathe joins (~wroathe@user/wroathe)
20:47:38 Null_A_ joins (~null_a@c-73-93-244-42.hsd1.ca.comcast.net)
20:49:07 rockymarine joins (~rocky@user/rockymarine)
20:50:56 × Null_A quits (~null_a@2601:645:8700:ac10:1005:19fc:119b:3387) (Ping timeout: 244 seconds)
20:53:17 × kenran quits (~kenran@200116b82bfc8c0061dac18751f3996d.dip.versatel-1u1.de) (Quit: WeeChat info:version)
20:54:14 × matthewmosior quits (~matthewmo@173.170.253.91) (Remote host closed the connection)
20:54:21 matthewmosior joins (~matthewmo@173.170.253.91)
20:54:22 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 246 seconds)
20:59:43 × waldo quits (~waldo@user/waldo) (Quit: quit)
21:01:52 × Lycurgus quits (~juan@user/Lycurgus) (Quit: Exeunt juan@acm.org)
21:02:58 × szkl quits (uid110435@id-110435.uxbridge.irccloud.com) (Quit: Connection closed for inactivity)
21:04:41 × Ristovski quits (~Ristovski@hellomouse/perf/ristovski) (Ping timeout: 265 seconds)
21:06:10 rockymarine joins (~rocky@user/rockymarine)
21:09:53 Ristovski joins (~Ristovski@hellomouse/perf/ristovski)
21:13:48 × takuan quits (~takuan@178-116-218-225.access.telenet.be) (Remote host closed the connection)
21:14:19 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 246 seconds)
21:24:01 × raehik quits (~raehik@cpc95906-rdng25-2-0-cust156.15-3.cable.virginm.net) (Ping timeout: 265 seconds)
21:25:00 × acidjnk_new quits (~acidjnk@p200300d6e7137a459951f5994426b03a.dip0.t-ipconnect.de) (Ping timeout: 264 seconds)
21:29:00 rockymarine joins (~rocky@user/rockymarine)
21:30:58 <johnw> is this math spam? :)
21:31:00 × ubert quits (~Thunderbi@91.141.58.249.wireless.dyn.drei.com) (Ping timeout: 264 seconds)
21:31:47 <darkling> What other sort do you expect in this channel?
21:32:27 <johnw> constructions that approximate math until you start taking undefined into account...
21:33:12 <byorgey> math spam is when you send your proof of the collatz conjecture to 50 different professors.
21:33:26 <monochrom> Unpopular opinion: It is math that approximates your constructions!
21:34:10 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 265 seconds)
21:34:11 <johnw> Haskeller: "Hey, list is the free monoid!" Internet: "No, actually it isn't..."; Haskeller: "Hey, Hask is a category!" Internet: "Well, sorry to tell you, but..." ;-)
21:34:18 <monochrom> More unpopular opinion: Math is a social construct that is constructed to approximate other social constructs!
21:34:39 × wroathe quits (~wroathe@user/wroathe) (Ping timeout: 265 seconds)
21:35:27 <monochrom> I would s/Internet/A vocal fringe minority of pedants who happen to be on the Internet/
21:35:39 <johnw> Math is a set of axioms that we are thus far the most content with as an illusion of "truth".
21:36:19 <johnw> now I'm at the edge of math trolling
21:36:45 <johnw> I will return to writing some Haskell
21:36:45 <monochrom> In that case, was I at the edge of philosophy-of-math trolling? :)
21:36:51 <johnw> lol
21:36:54 <dolio> Yeah, most people get the role of math backwards.
21:37:35 <dolio> Like when they say that physicists can't do stuff because math says so.
21:37:37 nate3 joins (~nate@98.45.169.16)
21:37:51 <dolio> That means the math isn't correctly capturing what works in physics.
21:38:01 <darkling> byorgey: 50... then 25, 76, 38, 19, 58, 29, 88, ...?
21:40:26 <c_wraith> monochrom: trolling? no, that's what people I know with extensive training in math and philosophy say seriously. :P
21:40:29 <dolio> Or what doesn't work.
21:40:40 <dolio> Like all that excluded middle nonsense. :þ
21:40:54 × matthewmosior quits (~matthewmo@173.170.253.91) (Remote host closed the connection)
21:41:19 <monochrom> Ugh. Either I'm a wave function or I am not a wave function!
21:42:07 × Null_A_ quits (~null_a@c-73-93-244-42.hsd1.ca.comcast.net) ()
21:42:28 <monochrom> Oddly enough I volunteered to give an undergrad talk on intuitionistic logic and its Kripke semantics!
21:42:29 <darkling> Are you particular about it, though?
21:42:43 ski . o O ( "A vocal fringe minority of pedants who happen to be on the Internet" -- isn't that all of us ? )
21:42:53 <monochrom> I am not a pedant.
21:42:59 <ski> clearly you're both a wave function or a particle
21:43:15 <ski> (linear logic "par")
21:43:43 <ski> monochrom : hm, and relation to epistemic modal logic ?
21:44:02 <johnw> see, trolling successful
21:44:06 <monochrom> I don't know that one, so I won't go that far.
21:44:18 gurkenglas joins (~gurkengla@p548ac72e.dip0.t-ipconnect.de)
21:44:54 matthewmosior joins (~matthewmo@173.170.253.91)
21:46:36 <monochrom> OTOH I might end up doing that without knowing, when I try to give an intuition of Kripke's idea by "imagine you design an 4X game so you dictate the tech tree of the civ, i.e., the subjective truths of that civ, past present and future".
21:46:42 <DigitalKiwi> 16:42 monochrom: I am not a pedant. => X
21:46:45 <monochrom> Speaking of unknown knowns.
21:46:47 rockymarine joins (~rocky@user/rockymarine)
21:46:52 × matthewmosior quits (~matthewmo@173.170.253.91) (Remote host closed the connection)
21:46:59 matthewmosior joins (~matthewmo@173.170.253.91)
21:54:44 × michalz quits (~michalz@185.246.207.221) (Remote host closed the connection)
22:01:38 burnsidesLlama joins (~burnsides@119247164140.ctinets.com)
22:02:00 × vorpuni quits (~pvorp@2001:861:3881:c690:488:11ee:612d:7b91) (Remote host closed the connection)
22:06:04 × pera quits (~pera@user/pera) (Ping timeout: 265 seconds)
22:06:52 × burnsidesLlama quits (~burnsides@119247164140.ctinets.com) (Ping timeout: 244 seconds)
22:08:26 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 260 seconds)
22:09:48 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
22:20:28 rockymarine joins (~rocky@user/rockymarine)
22:22:26 × nate3 quits (~nate@98.45.169.16) (Ping timeout: 260 seconds)
22:25:19 wroathe joins (~wroathe@206-55-188-8.fttp.usinternet.com)
22:25:20 × wroathe quits (~wroathe@206-55-188-8.fttp.usinternet.com) (Changing host)
22:25:20 wroathe joins (~wroathe@user/wroathe)
22:25:25 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 265 seconds)
22:31:57 <EvanR> if I have a set of (Name, Either Name Value) where names have a literal value or forward to another name for their value (transitively), is there a slick way to solve all the values or fail due to a cycle
22:32:20 <EvanR> or is this full graph algorithm
22:33:46 × wroathe quits (~wroathe@user/wroathe) (Ping timeout: 246 seconds)
22:33:51 <monochrom> If you just need to do a name lookup and report either "I've found the value" or "I've found a cycle", it doesn't need to be a full graph algorithm.
22:34:08 <EvanR> well that replicated for each name would solve it
22:34:54 <monochrom> See https://en.wikipedia.org/wiki/Cycle_detection for some algorithms for detecting "eventually periodic" without much space.
22:35:17 <monochrom> Floyd's or Brent's.
22:35:21 <david> Let's say I have a list of Maybe that I want to process, how do I return a Maybe processedList?
22:35:33 <david> ie how to change [Maybe a] into a Maybe [a] ?
22:35:34 wroathe joins (~wroathe@206-55-188-8.fttp.usinternet.com)
22:35:34 × wroathe quits (~wroathe@206-55-188-8.fttp.usinternet.com) (Changing host)
22:35:35 wroathe joins (~wroathe@user/wroathe)
22:36:06 <geekosaur> % :t sequenceA @Maybe
22:36:06 <yahb2> sequenceA @Maybe :: Applicative f => Maybe (f a) -> f (Maybe a)
22:36:09 <david> ie how to change [a] into a Maybe [b] given you have a function that has type (a -> Maybe b)
22:36:21 <geekosaur> % :t sequenceA @[] @Maybe
22:36:21 <yahb2> sequenceA @[] @Maybe :: [Maybe a] -> Maybe [a]
22:36:37 <david> thanhks
22:36:52 <geekosaur> (you don't have to use the @s, just showing you it can do what you want)
22:36:59 rockymarine joins (~rocky@user/rockymarine)
22:37:17 bitdex joins (~bitdex@gateway/tor-sasl/bitdex)
22:37:27 <david> is there something more generic?
22:38:27 <david> ok it just work thank you
22:38:41 <monochrom> EvanR: Oh! You did ask about doing all names in one go. Yeah then a full graph algorithm is better.
22:39:40 <monochrom> Some modification of Floyd-Warshall or any all-pairs-shortest-paths algorithm will do. https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm
22:39:44 burnsidesLlama joins (~burnsides@119247164140.ctinets.com)
22:39:52 <geekosaur> sequenceA is pretty generic already
22:40:20 <geekosaur> alkthough it does occur to me to wonder if it does the right thing the first time it hits a Nothing. there's also asum…
22:40:26 <geekosaur> :t asum
22:40:27 <lambdabot> (Foldable t, Alternative f) => t (f a) -> f a
22:40:35 <EvanR> yeah I was thinking this is a matrix inverse or something
22:40:36 <geekosaur> :t asum @[] @Maybe
22:40:37 <lambdabot> error:
22:40:37 <lambdabot> Pattern syntax in expression context: asum@[]
22:40:37 <lambdabot> Did you mean to enable TypeApplications?
22:40:43 <geekosaur> % :t asum @[] @Maybe
22:40:44 <yahb2> <interactive>:1:1: error: ; • Variable not in scope: asum ; • Perhaps you meant ‘sum’ (imported from Prelude)
22:40:46 × wroathe quits (~wroathe@user/wroathe) (Ping timeout: 246 seconds)
22:40:49 <geekosaur> bah
22:41:03 <david> thanks geekosaur At that point it doesn't matter I should start buliding automatisms and learn on this
22:42:19 <geekosaur> % :t Control.Applicative.asum @[] @Maybe
22:42:19 <yahb2> <interactive>:1:1: error: ; Not in scope: ‘Control.Applicative.asum’ ; Perhaps you meant ‘Control.Applicative.liftA2’ (imported from Control.Applicative)
22:43:55 × burnsidesLlama quits (~burnsides@119247164140.ctinets.com) (Ping timeout: 246 seconds)
22:45:19 × rockymarine quits (~rocky@user/rockymarine) (Ping timeout: 246 seconds)
22:45:42 × __monty__ quits (~toonn@user/toonn) (Quit: leaving)
22:51:24 × chomwitt quits (~chomwitt@2a02:587:dc14:f500:27b7:f613:f2be:f46f) (Ping timeout: 264 seconds)
22:52:28 <david> what should I write to enable TypeSynonymInstances
22:52:42 <david> {#- GHC TypeSynonymInstances -#} ?
22:53:20 <monochrom> s/GHC/language/
22:53:37 <monochrom> And flip #-
22:53:47 <jackdk> % :t Data.Foldable.asum @[] @Maybe -- geekosaur
22:53:47 <yahb2> Data.Foldable.asum @[] @Maybe -- geekosaur :: [Maybe a] -> Maybe a
22:53:47 <monochrom> {-# language TypeSynonymInstances #-}
22:54:17 <geekosaur> wrong one, whoops
22:56:28 rockymarine joins (~rocky@user/rockymarine)
22:58:03 <janus> % asum []
22:58:03 <yahb2> <interactive>:110:1: error: ; • Variable not in scope: asum :: [a0] -> t ; • Perhaps you meant ‘sum’ (imported from Prelude)
22:58:10 <janus> % Data.Foldable.asum []
22:58:10 <yahb2> *** Exception: user error (mzero)
22:58:14 <janus> why is this partial?
22:58:26 <david> I still have some issue
22:58:56 <david> http://vpaste.net/3svlE
22:59:13 <janus> oooh it's mzero of IO
22:59:58 <EvanR> how about some fear uncertainty and doubt that IO is a valid MonadPlus
23:00:00 × sammelweis quits (~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10) (Quit: No Ping reply in 180 seconds.)
23:00:08 <janus> % Data.Foldable.asum [] :: [Int]
23:00:08 <yahb2> []
23:01:02 <janus> almost want to know why there is MonadPlus IO.. but i don't ;P
23:01:36 sammelweis joins (~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10)
23:02:09 <monochrom> Galactic wars have been fought over that. :)
23:05:38 nate3 joins (~nate@98.45.169.16)
23:09:36 × matthewmosior quits (~matthewmo@173.170.253.91) (Remote host closed the connection)
23:10:03 matthewmosior joins (~matthewmo@173.170.253.91)
23:10:10 × jgeerds_ quits (~jgeerds@55d46bad.access.ecotel.net) (Ping timeout: 246 seconds)
23:12:05 × nate3 quits (~nate@98.45.169.16) (Ping timeout: 252 seconds)
23:12:43 edrx joins (~Eduardo@2804:18:582f:9eb3:fe75:6517:93df:a9ea)
23:15:35 × david quits (~david@2a01:e34:ec2b:d430:44a:f5ca:9867:d69d) (Ping timeout: 244 seconds)
23:17:21 <edrx> hi all! two questions... 1) what are your favorite "free" Haskell tutorials? I am following Hutton's book, but I can't put links to the PDF that I have in the online version of my notes about it... and 2) is this the standard list of tutorials? https://wiki.haskell.org/Tutorials
23:17:23 redmp joins (~redmp@mobile-166-171-249-155.mycingular.net)
23:17:31 × redmp quits (~redmp@mobile-166-171-249-155.mycingular.net) (Client Quit)
23:17:54 jero98772 joins (~jero98772@2800:484:1d80:d8ce:efcc:cbb3:7f2a:6dff)
23:20:41 Lycurgus joins (~juan@user/Lycurgus)
23:26:33 <geekosaur> @where learn
23:26:33 <lambdabot> https://wiki.haskell.org/Learning_Haskell
23:26:40 <geekosaur> hm, not the one I wanted
23:27:11 × matthewmosior quits (~matthewmo@173.170.253.91) (Ping timeout: 260 seconds)
23:27:17 <geekosaur> @where books
23:27:18 <lambdabot> See `LYAH',`RWH',`YAHT',`SOE',`HR',`PIH',`TFwH',`wikibook',`PCPH',`HPFFP',`FSAF',`HftVB',`HTAC',`TwT',`FoP',`PFAD',`WYAH',`non-haskell-books'. Also https://www.extrema.is/articles/haskell-books,
23:27:18 <lambdabot> https://www.vex.net/~trebla/haskell/learn-sources
23:27:53 <ski> @where CIS194
23:27:53 <lambdabot> https://www.seas.upenn.edu/~cis194/spring13/lectures.html
23:28:36 <ski> edrx : we sometimes suggest this one ^, especially since it has excersices (unlike say LYAH)
23:29:03 <edrx> thanks! =)
23:30:31 <monochrom> My favourite free tutorial is the Gentle Introduction.
23:32:21 <EvanR> that's what I was going to say
23:34:16 <ski> @where tutorial
23:34:17 <lambdabot> http://www.haskell.org/tutorial/
23:35:11 <ski> that's the "Gentle" one (hint, some people don't consider it so "gentle". it assumes some basic familiarity with FP (like e.g. SML,OCaml,Erlang,Scheme))
23:35:27 <ski> @where Data61
23:35:27 <lambdabot> Data61 Functional Programming Course <https://github.com/data61/fp-course>,<https://qfpl.io/links/2017-october-fp-course/> by Tony Morris,Mark Hibberd. Also see the channel #qfpl
23:35:40 <ski> is a more advanced one (than CIS194)
23:35:57 <edrx> it's one of the first ones that I've downloaded =) now I'm trying to understand the makefile in https://www.haskell.org/tutorial/haskell-98-tutorial-sources.tar.gz to see how to compile the .lhs files...
23:36:37 <ski> it's also pretty old, so some things may have to be changed, especially if there's library imports (i don't recall, off-hand)
23:36:46 <edrx> yes, I guessed so
23:37:14 <ski> @where wikibook
23:37:15 <lambdabot> http://en.wikibooks.org/wiki/Haskell
23:37:22 <ski> @where HTAC
23:37:22 <lambdabot> "Haskell Tutorial and Cookbook" by Mark Watson in 2017-09-04 at <https://leanpub.com/haskell-cookbook>
23:37:24 × Lycurgus quits (~juan@user/Lycurgus) (Quit: Exeunt juan@acm.org)
23:37:33 <ski> (from the `books' list above)
23:38:17 × Tuplanolla quits (~Tuplanoll@91-159-69-34.elisa-laajakaista.fi) (Quit: Leaving.)
23:38:44 <ski> then there's some monad tutorials. (<https://wiki.haskell.org/Monad_tutorials_timeline> has a bunch of links)
23:40:02 <edrx> aha
23:41:11 <ski> my favorite (also somewhat dated, in terms of library operations) might be "What the hell are Monads?" by Noel Winstanley in 1999-02 at <https://www-users.mat.umk.pl/~fly/materialy/fp/haskell-doc/Monads.html>
23:41:54 <ski> there's a lot of monad tutorials out there, and i'd say most of them probably ranges from not too informative to misleading and bad
23:41:58 <ski> @where burrito
23:41:59 <lambdabot> http://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/
23:42:04 <ski> talks some about why
23:43:01 <monochrom> People love misinformative monad tutorials when they have eye candies.
23:43:12 <ski> as for some tutorials that cover a bit more than that Winstanley one (which might be the first non-paper general monad tutorial out there) :
23:43:35 <ski> @where AAM
23:43:35 <lambdabot> http://www.haskell.org/haskellwiki/All_About_Monads
23:43:40 <ski> @where MTSS
23:43:40 <lambdabot> "Monad Transformers Step by Step" by Martin Grabmüller in 2006-10-16 (draft) at <https://page.mi.fu-berlin.de/scravy/realworldhaskell/materialien/monad-transformers-step-by-step.pdf>
23:43:43 <ski> also see
23:43:50 <ski> @where Typeclassopedia
23:43:50 <lambdabot> http://www.haskell.org/haskellwiki/Typeclassopedia
23:43:52 <monochrom> People do not want an objective measure of understanding or truth. People want a subjective feeling of comfort.
23:43:59 <ski> which also covers `Functor' and `Applicative'
23:44:14 nate3 joins (~nate@98.45.169.16)
23:44:25 <monochrom> Now, on the other end of the spectrum, there are pedants who oppose the name "flatMap".
23:44:55 ski . o O ( ".. and in the darkness bind them" )
23:45:07 <monochrom> They need to know that Bart Jacabs in his draft probability theory book uses the name "flat" for join.
23:45:44 ski was just reading/skimming the first chapter of that book, the other day .. nice book, ty for the link
23:45:51 <monochrom> :)
23:45:51 <EvanR> if monads can "flat" does that mean comonads "curve"
23:46:12 <monochrom> No. Instead, "level up" >:)
23:46:13 <geekosaur> "popup" 🙂
23:46:14 ski suggested `scaffold :: w a -> w (w a)'
23:46:30 <c_wraith> unflatMap
23:46:30 <ski> (not sure how good that is, but imho it's certainly better than `duplicate' ..)
23:46:51 <EvanR> cool names
23:48:08 <ski> (`duplicate' suggests `w -> (w,w)', to me, a `Comonoid' operation .. possibly in another category (e.g. Kleisli), if you want, to avoid triviality)
23:48:55 <monochrom> unsafeDupableIO :: IO a -> IO (IO a)
23:49:02 mvk joins (~mvk@2607:fea8:5ce3:8500::778c)
23:50:25 × beteigeuze quits (~Thunderbi@89.187.168.45) (Ping timeout: 246 seconds)
23:51:03 <monochrom> class EndOfMainSequenceComonad m where gravitationalCollapse :: m a -> a; supernova :: m a -> m (m a)
23:51:15 matthewmosior joins (~matthewmo@173.170.253.91)
23:52:03 <geekosaur> that implies a black hole is m (m (… (m a…)
23:52:16 × edrx quits (~Eduardo@2804:18:582f:9eb3:fe75:6517:93df:a9ea) (Ping timeout: 260 seconds)
23:53:16 <monochrom> gravity : singularity :: types : occurs-check infinite type >:)
23:53:26 <EvanR> that looks like a collapsing neutron star inside an einstein rosen bridge!
23:53:53 <monochrom> negative types, fraction types, and astrophysics types :)
23:54:07 × [itchyjunk] quits (~itchyjunk@user/itchyjunk/x-7353470) (Ping timeout: 268 seconds)
23:58:01 [itchyjunk] joins (~itchyjunk@user/itchyjunk/x-7353470)

All times are in UTC on 2022-09-24.