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.