Home liberachat/#haskell: Logs Calendar

Logs on 2023-12-04 (liberachat/#haskell)

00:00:15 <iqubic> I love the Church and state joke.
00:00:25 <ski> (note that the `s' in `exists s. ..s..' there can commonly be thought of as a "state type". e.g. as in OOP. existentials is one way to encode closures, and OOP objects. one can also do ADTs (abstract data types) with existentials, but that's a quite distinct use of them)
00:00:30 JeremyB99 joins (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069)
00:01:09 <iqubic> Do we even actually care about Yoneda and Coyoneda?
00:01:23 × JeremyB99 quits (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069) (Read error: Connection reset by peer)
00:01:25 <EvanR> we like to combine the church and the curry
00:01:55 <ski> practically, they can be used to delay `fmap'ping over a structure, collecgting the functions to map over, so that when you finally extract, you do all the `fmap's in one pass, instead of multiple traversals
00:02:08 <ski> iqubic ^
00:02:40 <iqubic> Right. That's cool.
00:03:02 <iqubic> fmap f . fmap g = fmap (f . g)
00:03:09 <ski> right
00:03:19 <iqubic> that's just a functor law.
00:03:29 <ski> and `Codensity' does something similar, for left-associated uses of `(>>=)'
00:03:54 <ski> this is similar to "difference lists", btw
00:04:17 <ski> (or keeping an extra accumulator parameter, to avoid having to add stuff to the end of a list, repeatedly)
00:04:28 <iqubic> runCodensity :: forall b. (a -> m b) -> m b
00:05:01 <iqubic> That's the sole constructor for a Codensity m a
00:05:21 × pretty_dumm_guy quits (trottel@gateway/vpn/protonvpn/prettydummguy/x-88029655) (Quit: WeeChat 3.5)
00:05:28 <ski> iqubic : consider a recursive definition like `data List a = Nil | Cons a (List a)'. we could "algebraically" write this as `List a = 1 + a * List a'
00:06:02 <iqubic> I agree. That's why we call it an ADT.
00:06:10 <ski> yea, basically
00:06:22 <geekosaur> @quote getSum.*sleep
00:06:22 <lambdabot> jle` says: let sleep = pure "zzz" in getSum sleep
00:06:28 <iqubic> The A stands for Algebraic.
00:07:12 <ski> now lets say we only really consider the *finite* length lists here. looking at `List a = 1 + a * List a', this is an equation in `List a', that has multiple solutions, though. one is the finite-length lists (this is the least solution). another is the possibly-finite streams (including infinite ones) (this is the greatest solution)
00:07:38 <iqubic> Yeah, that makes sense.
00:08:08 <ski> in order to be clear about which one we want, and to avoid having to write a recursive equation, we have notation where the least solution is written `mu r. 1 + a * r', and the greatest solution is written `nu r. 1 + a * r'
00:08:41 <ski> so, for the least, we get `List a = mu r. 1 + a * r', and for the greatest, we get `List a = nu r. 1 + a * r'
00:08:45 <EvanR> runCodensity :: Codensity m a -> (forall b. (a -> m b) -> m b)
00:08:48 <iqubic> Oh, that's a clever way to disambiguate the solutions.
00:09:00 <ski> think of `mu r. ..r..' and `nu r. ..r..' as being similar to `fix (\r -> ..r..)
00:09:16 <iqubic> I already kinda assumed that.
00:09:34 <ski> in (although, denotationally speaking, in Haskell, `fix' computes the least fixed point)
00:10:21 <ski> iqubic : anyway, there are now useful ways in which we can refactor recursive types, expressed as `mu' (least) or `nu' (greatest) fixed points
00:10:35 <iqubic> There are?
00:10:47 JeremyB99 joins (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069)
00:10:59 <ski> specifically, `mu r. ..r..' is equivalent to `forall r. (..r.. -> r) -> r', and `nu s. ..s..' is equivalent to `exists s. (s,s -> ..s..)'
00:11:32 <ski> let's take `mu r. 1 + a * r', aka `List a', from above. this would then be equivalent to `forall r. (1 + a * r -> r) -> r'
00:11:34 × JeremyB99 quits (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069) (Read error: Connection reset by peer)
00:12:11 <iqubic> Hmm... That makes sense.
00:12:17 <ski> but `X + Y -> Z' is equivalent to `(X -> Z) * (Y -> Z)' (`o^(m+n) = o^m * o^n')
00:12:35 <ski> so, that gets us to `forall r. (1 -> r) * (a * r -> r) -> r'
00:12:57 lg1889 joins (~lg188@82.18.98.230)
00:13:02 × lg188 quits (~lg188@82.18.98.230) (Read error: Connection reset by peer)
00:13:03 lg1889 is now known as lg188
00:13:04 <iqubic> I see how that works.
00:13:23 <ski> now we can use currying. `1 -> Z' is equivalent to `Z' (`o^1 = o'), and `X * Y -> Z' is equivalent to `X -> Y -> Z' (`o^(m*n) = (o^n)^m')
00:13:50 <iqubic> I follow you there.
00:13:56 <ski> that gets us to `forall r. r * (a -> r -> r) -> r'. and if we uncurry the outer function type, we get `forall r. r -> (a -> r -> r) -> r'
00:14:00 <ski> now, look at
00:14:20 <ski> foldr :: (a -> r -> r) -> r -> [a] -> r
00:14:43 <iqubic> Those two are very similar.
00:14:46 <ski> flip foldr :: r -> (a -> r -> r) -> [a] -> r
00:15:19 <ski> flip . flip foldr :: r -> [a] -> (a -> r -> r) -> r
00:15:32 <ski> flip (flip . flip foldr) :: [a] -> r -> (a -> r -> r) -> r
00:15:35 <ski> which is really
00:15:42 <ski> flip (flip . flip foldr) :: forall a. forall r. [a] -> r -> (a -> r -> r) -> r
00:15:46 <ski> which can be rewritten as
00:15:56 <ski> flip (flip . flip foldr) :: forall a. [a] -> (forall r. r -> (a -> r -> r) -> r)
00:16:11 <iqubic> Oh... That's really cool.
00:16:31 <ski> (since `... -> forall a. ..a..' is equivalent to `forall a. (... -> ..a..)' .. and `(exists a. ..a..) -> ...' is equivalent to `forall a. (..a.. -> ...)')
00:16:35 <iqubic> I'm shocked that the algebra woks like that.
00:17:07 <ski> so, `foldr' basically converts from `List a' to the form `forall r. r -> (a -> r -> r) -> r)'
00:17:08 × picnoir quits (~picnoir@about/aquilenet/vodoo/NinjaTrappeur) (Ping timeout: 268 seconds)
00:17:28 <ski> @type GHC.Base.build
00:17:28 <lambdabot> (forall b. (a -> b -> b) -> b -> b) -> [a]
00:17:37 <ski> is a function that does the opposite
00:17:40 <ski> defined as
00:17:47 <ski> build f = f (:) []
00:18:15 <iqubic> Oh, that's really cool
00:19:25 <ski> and there's specialization rules in GHC, amounting to `build' being inverse of `foldr' (and vice versa). namely `foldr cons nil (build f) = f cons nil' -- this is used for a type of "list fusion optimization" where we skip constructing intermediate lists, if we're going to `foldr' on them. we pass the `cons' (callback) and `nil' (starting point) directly to the "builder" `f' function
00:19:37 <iqubic> foldr and build are just converting between the two types. I think [a] and forall r. r -> (a -> r -> r) -> r) are isomorphic
00:19:43 <ski> yes
00:19:47 × johnw quits (~johnw@69.62.242.138) (Quit: ZNC - http://znc.in)
00:20:19 clwif^ joins (~cd@c-98-242-74-66.hsd1.ga.comcast.net)
00:20:59 <ski> so, many of the list-producing functions are "good producers" meaning they produce their output lists by calling `build', and many of the list-consuming functions are "good consumers" meaning they consume their input lists by calling `foldr' on them
00:21:19 <ski> (of course, many functions are both producers and consumers of lists, and so would use both `build' and `foldr')
00:21:19 <iqubic> That's really cool to know. And I know that there are many functions like this.
00:21:26 <iqubic> @type maybe
00:21:27 <lambdabot> b -> (a -> b) -> Maybe a -> b
00:21:40 <ski> @type either
00:21:41 <lambdabot> (a -> c) -> (b -> c) -> Either a b -> c
00:21:52 <iqubic> Yeah. Those work in the same way.
00:22:19 <iqubic> Those are the cosumers for Maybe a and Either a b
00:22:29 travgm joins (~travgm@2600:100e:a121:d6af:56b:4880:133:700e)
00:22:54 <ski> they are the folds/catamorphisms, for `Maybe' and `Either', just as `foldr' is the one for `[]', yes
00:23:26 <iqubic> Right. Catamorpism was the word I was thinking of.
00:23:46 × wroathe quits (~wroathe@user/wroathe) (Quit: leaving)
00:23:56 <ski> (they also happen to be the "case" functions for `Maybe' and `Either'. `foldr' is not the "case" function for `[]', because `[]' is recursive. its case would have type `(a -> [a] -> r) -> r -> [a] -> r', with `[a]' rather than `r' as argument type in the callback)
00:24:13 <iqubic> @type unfoldr
00:24:14 <ski> catamorphisms "tear down structure". anamorphisms "build up structure"
00:24:14 <lambdabot> (b -> Maybe (a, b)) -> b -> [a]
00:24:39 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:d9f3:ec2f:a760:e0fe) (Remote host closed the connection)
00:24:43 <ski> yes, if we think of `[a]' as the greatest fixed point, then that `unfoldr' is its unfold/anamorphism
00:24:45 <iqubic> I assume that unfoldr uses build somehow?
00:25:21 mobivme joins (~mobivme@112.201.111.217)
00:25:23 <ski> note that `(s -> Maybe (a,s)) -> s -> [a]' may be more suggestive, thinking of `s' as a "state" or "seed" (think like random-generator seed, e.g.) type
00:25:30 <ski> hm, dunno
00:25:46 × misterfish quits (~misterfis@87.215.131.102) (Ping timeout: 245 seconds)
00:26:07 <ski> anyway, say you take now `data Stream a = Cons {head :: a,tail :: Stream a}', abstractly `Steram a = a * Stream a'. here we definitely want the greatest fixed point interpretation (since there are no finite streams here, and so there would be zero finite values)
00:26:21 <ski> so, `Stream a = nu s. a * s'
00:26:36 × travgm quits (~travgm@2600:100e:a121:d6af:56b:4880:133:700e) (Ping timeout: 245 seconds)
00:26:36 × chomwitt quits (~chomwitt@2a02:587:7a09:c300:1ac0:4dff:fedb:a3f1) (Ping timeout: 245 seconds)
00:27:06 <iqubic> This uses nu instead of mu, because there are no least fixed points.
00:27:16 <ski> if we expand this, using the equivalence above, we get `exists s. s * (s -> a * s)' .. the first `s' part is the "object instance state". the second part is a "method" taking the instance state, and produces an output of type `a', and a new instance state
00:27:43 <ski> well, the least fixed point exists, but is empty, not interesting
00:27:49 <ski> (is basically `Void')
00:28:11 <iqubic> Yes, that's kinda what I meant, but you phrased it much better.
00:29:11 <iqubic> How does using `exsist s. s * (s -> a * s)` change things? We have `exists' now, instead of `forall'
00:30:08 <ski> now, imagine we want to represent a type of queues, of elements of type `a'. a `Queue a' has some private internal state (of unknown/forgotten/hidden/abstract/opaque/skolem type) `s', and some methods. namely one for enequeueing an `a' onto the queue, and one for dequeueing an `a' from the queue (if it's non-empty, otherwise we get a failure indication)
00:31:04 <ski> this suggests `Queue a' should be `exists q. q * (a * q -> q) * (q -> Maybe (q * a))' (enqueue to the left, dequeue from the right)
00:31:44 <iqubic> Sure. That's a reasonable guess to make.
00:31:48 <ski> iqubic : yes. a value of type `forall a. ..a..' is a polymorphic value, works for *all* possible specific choices of type to use for `a', that the user/caller may pick
00:32:12 <iqubic> I know that.
00:32:24 <ski> while the producer/implementor must make sure that the code works for all possible `a', doesn't attempt to look into values of type `a', doesn't assume anything about the type
00:32:25 <iqubic> But thanks for clarifying
00:33:01 <iqubic> So, we're trying to model these queues.
00:33:31 <ski> while, for a value of type `exists a. ..a..', this is an "abstract" value, we know there is *some* type `a', but we don't know which. the user/caller/consumer now must be prepared to handle all possible types, for `a', can't make assumptions about `a', does *not* get to pick `a'. instead, the producer/implementor/callee gets to pick `a'
00:34:19 <ski> so, in `[exists a. ..a..]', the different elements in the list may have picked different `a's, so you can't assume them to be compatible. only within a single `exists a. ..a..' can you asssume the `a's are the same
00:34:47 <ski> and, in `String -> Int -> IO (exists a. ..a..)', the choice of which `a' to use may depend on the arguments, and also in this case on the I/O interaction
00:34:51 <iqubic> Oh! That's a really good way to explain the difference.
00:35:30 <ski> basically, `exists' and `forall' are "opposite", wrt requirements and capabilities, as it pertains to user/caller/consumer vs. implementor/callee/producer
00:35:40 picnoir joins (~picnoir@about/aquilenet/vodoo/NinjaTrappeur)
00:35:55 <iqubic> I get that now.
00:36:07 <ski> for `exists', callee picks, and caller must handle any choice. for `forall', callee must handle any choice, and caller picks
00:36:15 <ski> ok
00:36:23 <ski> so, let's imagine
00:36:37 <ski> data Queue a = MkQueue (exists q. q * (a * q -> q) * (q -> Maybe (q * a)))
00:36:42 <ski> this means that
00:36:54 <ski> MkQueue :: (exists q. q * (a * q -> q) * (q -> Maybe (q * a))) -> Queue a
00:37:23 <ski> but, according to the equivalence between `(exists a. ..a..) -> ...' and `forall a. (..a.. -> ...)', this ought to be the same as
00:37:26 <iqubic> Sure. I'd buy that.
00:37:42 <ski> MkQueue :: forall q. q * (a * q -> q) * (q -> Maybe (q * a)) -> Queue a
00:37:48 <ski> which we now can uncurry as
00:38:01 <ski> MkQueue :: forall q. q -> (a -> q -> q) -> (q -> Maybe (q * a)) -> Queue a
00:38:10 [itchyjunk] is now known as [itchTheIndiffer
00:38:56 <ski> which we now can express in actuall Haskell (using the `ExistentialQuantification' extension (imho a misnomer, something like `ExistentialConstructors' would be a better name. i'd prefer to have `ExistentialQuantification' available for a real `exists' keyword))
00:39:21 <ski> data Queue a = forall q. MkQueue q (a -> q -> q) (q -> Maybe (q,a))
00:39:29 <ski> or, with record syntax, for field names
00:39:49 <ski> data Queue a = forall q. MkQueue {queueState :: q,enqueue :: a -> q -> q,dequeu :: q -> Maybe (q,a)}
00:40:00 <ski> we could alternatively use `GADTs' syntax
00:40:08 <ski> data Queue a
00:40:10 <ski> where
00:40:22 <iqubic> I'm familiar with how `GADTs' work.
00:40:22 <ski> MkQueue :: q -> (a -> q -> q) -> (q -> Maybe (q,a)) -> Queue a
00:41:05 <iqubic> That's a catamorpism for `Queue a'
00:41:11 <ski> (anyway, this ought to explain why the `ExistentialQuantification' syntax uses the `forall' keyword .. the data constructor *is* polymorphic in the existentially quantified type variable (which does not occur in the result type, only possibly in argument types))
00:41:39 <iqubic> I actually think I already knew that.
00:41:57 <ski> now, `Queue a' encapsulates one internal state of a queue, together with methods for manipulating it
00:42:34 <iqubic> That makes sense.
00:42:44 <ski> in practice, you'd then define wrapper methods, which extract the state, and the method implementation in question, apply it to the state (and any extra parameters), and then *rewrap* the new state with the method implementations again, producing a new `Queue a' as result
00:43:19 <ski> and, you'd define a "class constructor", which is just a function that returns a `Queue a'
00:43:24 <iqubic> That's just the smart thing to do.
00:43:26 <ski> emptyQ :: Queue a
00:43:48 <ski> emptyQ = MkQueue [] enqueue dequeue
00:43:50 <ski> where
00:43:54 <ski> enqueue ... = ...
00:43:58 <ski> dequeue ... = ...
00:44:02 JeremyB99 joins (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069)
00:44:24 <ski> so that's your "class"/"class constructor". it specifies the initial state, and provides implementations for the methods
00:44:37 <iqubic> @type uncons
00:44:38 <lambdabot> [a] -> Maybe (a, [a])
00:44:58 <ski> well, the above implementation uses `[a]' for `q' .. this is inefficient, namely to add to one end of a list, and remove from the other
00:45:10 <iqubic> I agree.
00:45:10 × JeremyB99 quits (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069) (Read error: Connection reset by peer)
00:45:19 <iqubic> Using a linked list is slow.
00:45:31 <ski> better is to use `([a],[a])' for the state type `q', basically a queue with state `(front,revBack)' represents the items in the list `front ++ reverse revBack'
00:45:42 <ski> this is the "folklore FP" implementation of queues
00:46:54 <iqubic> I think I actually wrote an implementation of a Queue using that representation for the Queue
00:47:18 <ski> (once in a while, when `revBack' becomes empty, you reverse `front' and move it over to `revBack', setting the new `front' to `[]'. but that `O(n)' cost is only incurred now and them, making the amorticized cost still `O(1)' .. assuming you just keep around the newest version of the queue, not older versions. there are ways to make it efficient, even if you keep around the older ones. see "Purely Functional
00:47:24 <ski> Data Structures" by Chris Okasaki)
00:47:30 johnw joins (~johnw@69.62.242.138)
00:48:06 <ski> anyway, taking a step back to `exists q. q * (a * q -> q) * (q -> Maybe (q * a))', we can use the equivalent with the `nu' form here actually, rewriting as
00:48:22 <ski> exists q. q * (a * q -> q) * (q -> Maybe (q * a))
00:48:34 <ski> = exists q. q * (a -> q -> q) * (q -> Maybe (q * a))
00:48:41 <ski> = exists q. q * (q -> a -> q) * (q -> Maybe (q * a))
00:48:55 <ski> = exists q. q * (q -> (a -> q) * Maybe (q * a))
00:49:08 <ski> = nu q. (a -> q) * Maybe (q * a)
00:49:12 <ski> which now suggests
00:49:48 <ski> data Queue a = MkQueue {enqueue :: a -> Queue a,dequeue :: Maybe (Queue a,a)}
00:49:57 <iqubic> I used my own Queue implementation for Advent of Code one year, before I found that Containers has Data.Seq, which has a much better API and implenentation than what I made myself.
00:49:58 <ski> (taking the greatest fixed point interpretation of this)
00:50:08 <ski> now the instance state is hidden, inside closures
00:50:18 <iqubic> Right.
00:52:00 <ski> there is a similar equivalence between `a -> b' and `exists env. env * (env * a #-> b)', expressing how functions can be represented as a closure, a pair of a "(user) data"/"context"/"environment"/"config" part, and a (low-level) function (think C function pointer, or address of a subroutine in assembler) taking that, and the function argument, as input
00:52:13 <iqubic> Data.Seq is actually a dequeue, as you can add and remove from both ends.
00:52:47 <iqubic> I didn't know about that last equivalence!
00:53:01 <ski> (`#->' there is known as "strict implication", in logic, btw. `a #-> b' is equivalent to `[] (a -> b)', where `[]' is read "necessary", and in this case means that it's not "cotingent", doesn't depend on run-time input, is defined statically at the top-level)
00:53:45 <ski> in C, the `qsort' (suggesting, but not mandating, "quick sort") function, is specified as
00:54:01 <ski> void qsort(void *base,size_t nmemb,size_t size,int (*compar)(const void *,const void *));
00:54:21 <iqubic> Got it. I was thinking you had randomly decided to pull in Linear Types for some reason. Good to know that's not thecate.
00:54:23 <ski> which, if we imagine an extension of C with parametric polymorphism (and parameterized data types), would really be
00:54:29 <iqubic> *the case
00:54:54 <ski> forall<T> void qsort<T>(T *base,size_t nmemb,typesize_t<T> size,int (*compar)(const T *,const T *));
00:55:16 <ski> but better would have been to make the interface pass along a "data pointer", to be passed to the callback, as
00:55:34 <ski> forall<T,U> void qsort<T>(T *base,size_t nmemb,typesize_t<T> size,U *env,int (*compar)(U *,const T *,const T *));
00:55:37 <ski> or just
00:55:59 <ski> void qsort(void *base,size_t nmemb,size_t size,void *env,int (*compar)(void *,const void *,const void *));
00:56:02 <ski> in actual C
00:56:35 <ski> because then the callback would be able to depend on run-time data, without needing to use global state (which is undesirable in the presence of multi-threading, also reentrancy)
00:56:49 <iqubic> That does seem lake a better type signature.
00:57:32 <ski> GTK does callbacks in this style
00:57:40 <ski> and it's basically emulating closures
00:57:44 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:d9f3:ec2f:a760:e0fe)
00:58:28 <ski> if you wanted to store a closure, more long-term, you'd use something like `struct { void *data; void (*foo)(void *data,size_t n,double (*parr)[n]); }' or somesuch
00:58:40 <ski> (or, if you add multiple function pointers in there, you get "OO objects")
00:58:53 <iqubic> I don't know how GTK works, as I've never used it.
00:59:07 nate4 joins (~nate@c-98-45-158-125.hsd1.ca.comcast.net)
00:59:09 <ski> if you check <https://www.glfw.org/docs/latest/group__input.html#ga1caf18159767e761185e49a3be019f8d> (in GLFW), this says
00:59:33 <ski> GLFWkeyfun glfwSetKeyCallback(GLFWwindow *window,GLFWkeyfun callback);
00:59:40 <iqubic> C isn't Object Oriented is it?
00:59:56 <ski> where `GLFWkeyfun' is defined at <https://www.glfw.org/docs/latest/group__input.html#ga5bd751b27b90f865d2ea613533f0453c> as
01:00:12 <ski> typedef void (*GLFWkeyfun)(GLFWwindow *window,int key,int scancode,int action,int mods)
01:00:26 <ski> .. so it looks like these callbacks are missing the "user data" to simulate closures :(
01:00:38 <ski> iqubic : no, but this is one way to simulate OO objects
01:00:54 <ski> (not including implementation inheritance, that requires a bit more stuff)
01:00:57 wroathe joins (~wroathe@207-153-38-140.fttp.usinternet.com)
01:00:57 × wroathe quits (~wroathe@207-153-38-140.fttp.usinternet.com) (Changing host)
01:00:57 wroathe joins (~wroathe@user/wroathe)
01:01:21 <ski> however, checking <https://www.glfw.org/docs/latest/group__window.html#gae77a4add0d2023ca21ff1443ced01653>, we see
01:01:37 <ski> void *glfwGetWindowUserPointer(GLFWwindow *window);
01:01:37 <ski> and
01:02:01 <ski> void glfwSetWindowUserPointer(GLFWwindow *window,void *pointer);
01:02:10 <ski> so there the user data is !
01:02:39 <ski> i suspect they realized the usefulness of this later, and decided to add it like this, rather than change the existing interface for creating a window
01:03:06 <ski> (someone pointed this about GLFW out, the other day, which is why i recalled it now)
01:03:35 <ski> (yea, no linear types, here)
01:04:09 <ski> anyway, i wanted to say one more thing about the queues above
01:04:10 <wroathe> Hey guys, me again... how would I go about determining what in this loop is allocating memory, and how many times it's being constructed? https://gist.github.com/JustinChristensen/2111f13e812112b5ac973e292606d17f#file-fixfile-hs-L65-L84 I'm running a memory benchmark that shows that for a 6.8M file that has ~7M characters a single call to fixFile allocates 4.5GB worth of heap objects and GCs 1079 times.
01:04:12 × nate4 quits (~nate@c-98-45-158-125.hsd1.ca.comcast.net) (Ping timeout: 252 seconds)
01:04:16 <wroathe> I'd like to determine how I could run a more detailed benchmark to show exactly where those allocations are occurring...
01:04:44 JeremyB99 joins (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069)
01:05:31 <wroathe> My two theories are constructing boxed Word8 values, and constructing boxed FixedState values in this loop. My goal is to get this loop to near-native performance where the automaton keeps the state value in a single word of memory
01:05:34 <ski> consider again `exists q. q * (a * q -> q) * (q -> 1 + a * q)' -- but this time, think of it differently. think of the first `q' part not as "current state" but as "another operation", namely one for giving an empty queue. while the other two are still "enqueue" and "dequeue"
01:06:30 <ski> data QueueOps a = forall q. MkQueueOps {empty :: q,enqueue :: a -> q -> q,dequeue :: q -> Maybe (q,a)}
01:07:17 <ski> iqubic : the difference now is that, instead of unwrapping, applying method, then rewrapping state, repeatedly, we now just unwrap/open the container of operations *once* at the start, then pass around "naked queue states" to the operations
01:08:41 <ski> and this makes a real difference, since now you can have "binary operations", like e.g. taking two heaps and merging them together into one. or taking two priority queues and merging them. with the "OO view" of existentials, you have just a single object state, so your "binary method" can't "look inside" both queue inputs, just one. the other might use a different internal state type
01:09:00 <ski> but with this version, the "ADT view" (Abstract Data Type), you *can* have "binary operations"
01:09:06 [_] joins (~itchyjunk@user/itchyjunk/x-7353470)
01:10:32 × JeremyB99 quits (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069) (Read error: Connection reset by peer)
01:11:40 <ski> wroathe : hm, you removed the strict patterns on `state', looks like
01:12:21 <ski> did you try [Leary]'s other suggestion ? (Church encoding)
01:12:22 <wroathe> ski: I did. That didn't help at all, and if it did I couldn't have explained why
01:12:26 × [itchTheIndiffer quits (~itchyjunk@user/itchyjunk/x-7353470) (Ping timeout: 245 seconds)
01:12:39 <wroathe> ski: I'm not going to do a lot of rewriting until I get past the "evidence" phase
01:13:00 <wroathe> Still trying to figure out exactly what gets allocated where. Even ticky-ticky isn't very explanatory
01:13:05 <ski> yea, your're only passing `Start' or `Backslash' as argument in the `state' position, so i wouldn't except being strict in the argument doing much
01:13:05 <iqubic> ski: brb, switching machines
01:13:35 JeremyB99 joins (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069)
01:13:43 × JeremyB99 quits (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069) (Read error: Connection reset by peer)
01:13:48 <wroathe> ski: I was actually just looking at MutVar#. I'm wondering how I can make that enumeration an unlifted type, and then read/write it from a mutable location
01:14:03 iqubic- joins (~avi@2601:602:9502:c70:774c:879b:1855:10ba)
01:14:13 <iqubic-> back
01:14:49 × dcoutts quits (~duncan@cpc69402-oxfd27-2-0-cust903.4-3.cable.virginm.net) (Ping timeout: 276 seconds)
01:15:05 ski 's not quite sure what `fixFile' is supposed to do
01:16:00 <ski> iqubic : i'll wait for you to read the last above, and perhaps comment/ask about it
01:16:02 <wroathe> ski: It's just a simple state machine. I'm iterating through the characters of a file, and I need to keep track of whether I've seen a Backslash or not. If I see a Backslash, and then I find a character that isn't a Backslash, I'm inserting a matching \ before continuing with output
01:16:27 <wroathe> ski: The point of the program is that I've got a TSV that has a bunch of \ in unquoted fields, and this function "fixes" that by properly escaping them
01:16:38 <wroathe> As an exercise I'm trying to see if I can get it to sed-like performance
01:17:03 <ski> oh, i guess you double the backslashes .. unless it was already doubled ?
01:17:05 <wroathe> (If I can't there will be no point in maintaining this in Haskell code when I've got a perfectly good shell script that runs sed just fine)
01:17:09 ski missed the doubling, initially
01:17:13 <wroathe> ski: Correct
01:17:26 × iqubic quits (~avi@2607:fb91:1518:c0e2:d265:9ef3:5320:9df0) (Ping timeout: 245 seconds)
01:17:47 <wroathe> Thanks to earlier suggestions in here and a bit of digging in the Base code I was able to minimize the amount of I/O and maximize the amount of buffering this does
01:18:10 <wroathe> But something within this loop is doing a bunch of allocating throwaway objects, and I'd like to make it stop doing that
01:18:18 <ski> i was wondering how efficient it would be to use a buffer size of `1'
01:18:54 <wroathe> ski: Well that's just intended to be a memory location to hold a single character being examined in the loop. The actual buffering is done on the Handle
01:19:38 <wroathe> If you look at the top I defined this thing I'm calling a "Fat FD" that allows me to create a separate instance of BufferedIO where I set my buffer size to 8M. I learned yesterday that for regular FD GHC hardcodes that to just 8192 bytes!
01:20:09 <ski> mhm
01:20:10 <wroathe> So if I've got an 800M TSV that would end up being like almost 100k write calls
01:20:49 <ski> i see
01:21:07 <wroathe> read/write, actually. On either end.
01:21:39 <wroathe> Pretty happy with how that turned out. It works nicely. Now to make Haskell stop doing Haskell things in the loop itself.
01:21:42 ski would proably look at core of the code, trying to see where it could allocate
01:22:20 <ski> (`-ddump-simpl', or perhaps some other version of it)
01:22:43 <wroathe> Let me see if that makes more sense to me than the stg or cmm did
01:22:47 <wroathe> I haven't tried simpl yet
01:24:41 <wroathe> ski: What does an allocation "look like" in simpl?
01:25:10 <wroathe> For example, I see this: case ghc-prim:GHC.Prim.word8ToWord# ipv3_a3KB of { __DEFAULT -> src<bench/memory/Main.hs:69:47-51> Main.Start; 92## -> src<bench/memory/Main.hs:69:32-40> Main.Backslash })
01:26:13 <ski> that's checking `c == bs'
01:26:53 × smalltalkman quits (uid545680@id-545680.hampstead.irccloud.com) (Quit: Connection closed for inactivity)
01:27:32 <wroathe> Right, but I mean the terms "Main.Backslash" and "Main.Start" there. Do those constitute an allocation?
01:27:33 <ski> `let' would allocate. and lambdas, often, i guess. and i suppose calling data constructors
01:29:08 <ski> hm, i suspect so
01:29:32 <wroathe> My theory right now is that GHC isn't recognizing what this pattern is, and is just allocating a new value of type FixState on every loop iteration
01:29:55 <wroathe> So I think what I need to do here is figure out what the syntax for making it an unlifted type is, and use something like MutVar#
01:30:28 <iqubic-> ski: I assume using this would be better than trying roll my own Queue code: https://hackage.haskell.org/package/containers-0.7/docs/Data-Sequence.html#t:Seq
01:31:56 JeremyB99 joins (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069)
01:32:05 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:d9f3:ec2f:a760:e0fe) (Remote host closed the connection)
01:32:06 × JeremyB99 quits (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069) (Read error: Connection reset by peer)
01:32:21 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:d9f3:ec2f:a760:e0fe)
01:32:21 <iqubic-> It's O(1) for popping from each end and O(1) for pushing to either end
01:33:42 <iqubic-> Oh... except that this doesn't work with infinite Seqs
01:34:19 <iqubic-> (1 :<| undefined) `index` 0 = undefined
01:34:27 × Square quits (~Square@user/square) (Ping timeout: 252 seconds)
01:34:45 <iqubic-> It's strict in the spine of the sequence. But it's still really good for what it does.
01:36:30 <ski> iqubic- : probably, yea
01:36:48 <ski> .. how would you like infinite queues to work ?
01:37:15 <ski> (enqueueing being a black hole, and dequeueing just removing from its infinite end ?)
01:38:12 <ski> wroathe : yea. i suspect that using a Church representation, GHC could perhaps use "join points", which would not require additional allocation
01:38:13 <iqubic-> Yeah... I don't know when I'd need an infinite Sequence.
01:38:29 <ski> (but i haven't tried playing around with that, with `-ddumpl-simpl' or similar)
01:38:49 <ski> iqubic- : no, i mean, not when you need it, but how ought it to work, reasonably
01:39:20 <ski> (iqubic- : i also PMed you a question)
01:39:39 <wroathe> ski: Hmm, Church scares me... (on a number of levels). I'll try both that and this approach. Ultimately I would prefer to use Lifted types for this that GHC magically optimizes to the code I want
01:39:58 <geekosaur> require a Monoid constraint, enqueue eats, dequeue produces mempty 🙂
01:40:31 ski nods to wroathe
01:41:10 × iqubic- quits (~avi@2601:602:9502:c70:774c:879b:1855:10ba) (Remote host closed the connection)
01:41:25 <ski> geekosaur : not necessarily. you could have `listToQueue :: [a] -> Queue a', where if the list is infinite, enqueueing is just a black hole, and dequeueing removes from the infinite list
01:41:33 <geekosaur> the Hawking version requires an Arbitrary constraint so dequeue can produce a randomized value
01:41:45 iqubic joins (~avi@2601:602:9502:c70:774c:879b:1855:10ba)
01:42:57 <ski> hehe :p
01:45:05 <ski> listToQueue revBack = loop [] revBack
01:45:08 <ski> where
01:45:36 <ski> enqueue (loop front revBack) x = loop (x:front) revBack
01:46:22 <ski> dequeue (loop front [ ]) = ...
01:46:49 <ski> dequeue (loop front (x:revBack)) = Just (loop front revBack,x)
01:49:41 <ski> iqubic : anyway, continuations can be useful for efficiency reasons (directly call a callback, instead of making a bundle that'll only be unwrapped by the receiver immediately after the call). can also be useful sometimes for control reasons (early return/exit / short-circuiting), and for more advanced control (e.g. backtracking, ..)
01:50:12 <iqubic> Yeah. That's really cool.
01:51:17 <ski> e.g. you can use this to turn "internal iteration" (like a `mapM' library operation that applies a callback to each element of some collection (perhaps virtual, generated as we go)), into "external iteration" (the caller gets to decide if and when we advance to the next element)
01:51:49 szkl joins (uid110435@id-110435.uxbridge.irccloud.com)
01:52:50 <ski> if a language has composable/delimited/sub- continuation side-effects (or, equivalently, (undelimited) continuation side-effects, and at least one mutable cell (state side-effect)), then, given any implementation of a monad, you can turn that into a side-effect, as if that monad was a built-in side-effect in the language (and with composable continuations, this can be relatively efficient, more than
01:52:56 <ski> interpreting different data constructors all the time in (especially left-nested) `(>>=)'s). e.g. you could introduce parser side-effects that way
01:53:19 <ski> there's two nice papers by Andrzej Filinski about this. the technique (and the papers) is called "monadic reflection"
01:54:34 <iqubic> I'll look into that when I get time. I need to get some dinner now.
01:54:46 JeremyB99 joins (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069)
01:54:48 <ski> if you have `foo :: ... -> Maybe T', you can replace this with `withFoo :: ... -> o -> (T -> o) -> o' (or perhaps, if you had `foo :: ... -> IO (Maybe T)', you'd replace this with `withFoo :: ... -> IO o -> (T -> IO o) -> IO o')
01:55:06 <ski> this is passing two continuations, one for the `Nothing' case, and one for the `Just' case, of the `Maybe'
01:55:16 <iqubic> I am now a more clever and learned lady!
01:55:43 Xyloes joins (~wyx@2400:dd01:103a:1012:5923:33ce:7857:fc04)
01:55:54 <ski> `withFoo' will directly call the appropriate continuation (corresponding to a branch of a `case'), rather than constructing a `Maybe T', only to have the caller take it apart immediately and branch into a `case'
01:56:43 <ski> effectively, `withFoo' will jump to the appropriate branch immediately, without the control flow having to first pass through the "needle's eye" of the `case', requiring allocating a `Maybe' somewhere
01:57:39 <ski> parsing combinator libraries often do something like this, internally
01:58:11 <ski> also the `LogicT' type, for fair backtracking, iirc
01:58:48 <ski> @hackage logict
01:58:48 <lambdabot> https://hackage.haskell.org/package/logict
02:00:18 <ski> newtype LogicT m a = LogicT { unLogicT :: forall r. (a -> m r -> m r) -> m r -> m r } -- yep
02:01:21 <ski> (note `LogicT Identity a' is the Church representation for `[a]')
02:02:11 <ski> oh, i guess, on the topic of `withXXX', i should mention the two encodings of `exists'
02:02:15 <ski> if we want
02:02:42 <ski> foo :: ... -> exists q. (q,(a,q) -> q,q -> Maybe (q,a))
02:02:47 <ski> we can represent this as
02:02:54 <ski> foo :: ... -> Queue a
02:03:15 <ski> defining `Queue a' as we did above, using `ExistentialQuantification' or `GADTs'
02:03:40 <ski> or, we can use the equivalence between `...' and `forall o. (... -> o) -> o', to get from
02:03:44 <ski> foo :: ... -> exists q. (q,(a,q) -> q,q -> Maybe (q,a))
02:03:46 <ski> to
02:04:03 <ski> withFoo :: ... -> forall o. ((exists q. (q,(a,q) -> q,q -> Maybe (q,a))) -> o) -> o
02:04:07 × sawilagar quits (~sawilagar@user/sawilagar) (Ping timeout: 255 seconds)
02:04:26 <ski> which, by `(exists a. ..a..) -> ...' being equivalent to `forall a. (..a.. -> ...)', amounts to
02:04:46 <ski> withFoo :: ... -> forall o. (forall q. (q,(a,q) -> q,q -> Maybe (q,a)) -> o) -> o
02:05:22 <ski> or, uncurrying (and removing the `forall o.', since `... -> forall a. ..a..' is equivalent to `forall a. (... -> ..a..)', and we can elide top-level `forall's)
02:05:54 <ski> withFoo :: ... -> (forall q. q -> (a -> q -> q) -> (q -> Maybe (q,a)) -> o) -> o
02:06:27 <ski> so, this is the "CPS" encoding of existentials, by passing an extra callback, that will be polymorphic in the existentially quantified type variable
02:06:42 <ski> iqubic : have a nice dinner
02:08:49 <iqubic> Thanks for being willing to teach a trans woman like me.
02:11:56 peterbecich joins (~Thunderbi@047-229-123-186.res.spectrum.com)
02:15:01 travgm joins (~travgm@fsf/member/travgm)
02:16:14 × peterbecich quits (~Thunderbi@047-229-123-186.res.spectrum.com) (Ping timeout: 252 seconds)
02:18:46 × emmanuelux quits (~emmanuelu@user/emmanuelux) (Quit: au revoir)
02:29:56 × travgm quits (~travgm@fsf/member/travgm) (Ping timeout: 245 seconds)
02:33:31 <wroathe> ski: So I lost Leary's example, but is the church encoding for FixState in my example basically the same as the "bool" encoding? Is this correct?
02:33:34 <wroathe> type FixState a = a -> a -> a
02:33:36 <wroathe> start :: FixState a; start a _ = a
02:33:39 <wroathe> backslash :: FixState a; backslash _ b = b
02:34:11 <ski> well, more like `type FixState = forall a. a -> a -> a' .. but yes, for `start' and `backslash'
02:34:32 <wroathe> Ah, I was wondering about forall a. there
02:34:46 <wroathe> I still don't get the use of forall beyond making the compiler shut up
02:34:55 × Xyloes quits (~wyx@2400:dd01:103a:1012:5923:33ce:7857:fc04) (Remote host closed the connection)
02:35:08 <wroathe> Is it RankNTypes that enables that for type synonyms?
02:35:14 <ski> `forall' means the corresponding value is polymorphic
02:36:00 <ski> `length :: forall a. ([a] -> Int)' means that, strictly speaking, `length' is not a function, but a "polymorphic value". namely one that, when specialized, yields a function. (a "polymorphic function", for short)
02:36:28 <wroathe> type FixState a = a -> a -> a
02:36:28 <wroathe> start :: FixState a; start a _ = a
02:36:29 <wroathe> backslash :: FixState a; backslash _ b = b
02:36:34 <ski> if you use `forall' around an argument type, then that argument itself (not necessarily the whole function that takes that argument) is polymorphic. this is known as rank-3
02:36:34 <wroathe> Whooops, sorry
02:36:37 <ski> er, rank-2
02:36:52 <wroathe> • Illegal polymorphic type: forall a. a -> a -> a
02:36:52 <wroathe> • In the expansion of type synonym ‘FixState’
02:36:52 <wroathe> In the type signature:
02:36:52 <wroathe> emit :: Handle -> Ptr Word8 -> Word8 -> FixState -> IO FixState
02:37:29 Xyloes joins (~wyx@2400:dd01:103a:1012:5923:33ce:7857:fc04)
02:37:38 <wroathe> I take it that's not very useful with type synonyms then
02:37:41 <ski> *usually*, if you write a type signature with type variables in it, like `zip :: [a] -> [b] -> [(a,b)]', there's "implicit" `forall's *directly* after the `::'
02:38:03 Sciencentistguy9 joins (~sciencent@hacksoc/ordinary-member)
02:38:35 <ski> iow, we really have `zip :: forall a b. [a] -> [b] -> [(a,b)]', but Haskell allows us to be implicit about the `forall's, omit/elide them, so just writing `zip :: [a] -> [b] -> [(a,b)]', and the implementation will (conceptually, at least) insert them back for us
02:38:57 <ski> this is merely a convenience thing. some other languages with polymorphism has no such convenience syntax
02:39:10 <wroathe> So is the above error saying that we basically do need FixState paramterized by a so that I can quantify it in function signatures?
02:39:22 travgm joins (~travgm@2600:100e:a121:d6af:56b:4880:133:700e)
02:40:12 × Sciencentistguy quits (~sciencent@hacksoc/ordinary-member) (Ping timeout: 268 seconds)
02:40:12 Sciencentistguy9 is now known as Sciencentistguy
02:40:40 <ski> in any case, `a -> Bool' is *not* short for `forall a. a -> Bool' (since if it were, then `filter :: (a -> Bool) -> [a] -> [a]', could be said to mean the same as `filter :: (forall a. a -> Bool) -> [a] -> [a]', which it most definitely does *not*) .. it's only at the "top-level" of a type *signature*, right after the `::', where implicit `forall's can be added
02:41:15 <wroathe> Your brain is too big for me :P
02:41:45 <ski> "I take it that's not very useful with type synonyms then" -- with `Rank2Types' or `RankNTypes', they can be
02:42:28 <ski> "So is the above error saying that we basically do need FixState paramterized by a so that I can quantify it in function signatures?" -- no, it's asking you to turn on higher-rank (or at least rank-2)
02:42:32 <ski> since
02:42:36 <ski> emit :: Handle -> Ptr Word8 -> Word8 -> FixState -> IO FixState
02:42:45 <ski> by the type synonym, expands to
02:42:58 <wroathe> I've got RankNTypes enabled
02:42:59 <ski> emit :: Handle -> Ptr Word8 -> Word8 -> (forall a. a -> a -> a) -> IO (forall a. a -> a -> a)
02:43:09 <ski> and that's rank-2, the argument is polymorphic
02:43:22 <ski> the second problem is that you now also have `forall' nested inside of `IO'
02:43:23 <wroathe> It won't let me define type FixState = forall a. a -> a -> a without it
02:43:57 <ski> that requires `ImpredicativeTypes' .. which at least used to only be partially implemented. there was some paper with a new approach to it, but i dunno if that's available in GHC yet
02:44:16 <ski> one way around that is to wrap the `forall' inside a data type
02:44:28 <ski> newtype FixState = FS (forall a. a -> a -> a)
02:44:37 <geekosaur> QuickLook has been in ghc since 9.2
02:44:39 <ski> then `IO FixState' will be fine
02:44:59 <ski> geekosaur : and it works fine, also for `IO (forall a. ..a..)' say ?
02:45:09 ski can't recall the details of the paper
02:45:13 <wroathe> ski: https://gist.github.com/JustinChristensen/2111f13e812112b5ac973e292606d17f#file-church-hs
02:45:17 <geekosaur> I think so, yes
02:45:19 <ski> ok
02:45:23 <geekosaur> I don't do impredicativity much
02:45:28 hgolden_ joins (~hgolden@cpe-172-251-233-141.socal.res.rr.com)
02:45:30 <wroathe> This is obviously wrong, but this I think is what you guys are suggesting I do when you say church encoding
02:45:59 jmdaemon joins (~jmdaemon@user/jmdaemon)
02:46:59 × hgolden quits (~hgolden@2603-8000-9d00-3ed1-dd4f-298a-9c49-a0ed.res6.spectrum.com) (Ping timeout: 268 seconds)
02:50:56 <ski> hm, yea, i think if you were just returning `IO FixState', that could be useful. but now you're also taking a `FixState' as input, which is making this more questionable. passing `start' or `backslash' as input might allocate closures here, unless these get allocated once, outside
02:51:04 × Unicorn_Princess quits (~Unicorn_P@user/Unicorn-Princess/x-3540542) (Remote host closed the connection)
02:51:46 <ski> (and even then, calling `state' with two `do's may allocate those, i guess unless they get translated into join points ?)
02:52:37 <wroathe> So are you saying you're cooling on the idea of the church encoding being a solution for this?
02:52:48 <wroathe> I still haven't gotten this to compmile
02:52:51 <wroathe> compile*
02:55:44 smalltalkman joins (uid545680@id-545680.hampstead.irccloud.com)
02:59:01 wroathe gives up on this idea
03:09:30 × travgm quits (~travgm@2600:100e:a121:d6af:56b:4880:133:700e) (Ping timeout: 268 seconds)
03:34:34 × ddellacosta quits (~ddellacos@ool-44c73d16.dyn.optonline.net) (Ping timeout: 276 seconds)
03:44:21 × FinnElija quits (~finn_elij@user/finn-elija/x-0085643) (Killed (NickServ (Forcing logout FinnElija -> finn_elija)))
03:44:21 finn_elija joins (~finn_elij@user/finn-elija/x-0085643)
03:44:21 finn_elija is now known as FinnElija
03:44:33 codolio joins (~dolio@130.44.134.54)
03:45:19 × dolio quits (~dolio@130.44.134.54) (Ping timeout: 260 seconds)
03:45:27 nate4 joins (~nate@c-98-45-158-125.hsd1.ca.comcast.net)
03:48:59 hapisnake joins (~hapisnake@120.138.12.144)
03:49:31 × td_ quits (~td@83.135.9.0) (Ping timeout: 245 seconds)
03:51:37 td_ joins (~td@i53870905.versanet.de)
03:55:24 dolio joins (~dolio@130.44.134.54)
03:55:34 × codolio quits (~dolio@130.44.134.54) (Ping timeout: 256 seconds)
03:55:59 ddellacosta joins (~ddellacos@ool-44c73d16.dyn.optonline.net)
03:59:59 × szkl quits (uid110435@id-110435.uxbridge.irccloud.com) (Quit: Connection closed for inactivity)
04:01:04 takuan joins (~takuan@178-116-218-225.access.telenet.be)
04:05:29 × hays quits (rootvegeta@fsf/member/hays) (Remote host closed the connection)
04:05:51 × hamess quits (~hamess@user/hamess) (Ping timeout: 260 seconds)
04:10:14 × hapisnake quits (~hapisnake@120.138.12.144) (Ping timeout: 250 seconds)
04:26:02 hays joins (rootvegeta@fsf/member/hays)
04:27:08 × hays quits (rootvegeta@fsf/member/hays) (Client Quit)
04:29:00 hays joins (rootvegeta@fsf/member/hays)
04:41:00 × ddellacosta quits (~ddellacos@ool-44c73d16.dyn.optonline.net) (Quit: WeeChat 4.1.1)
04:47:09 aforemny_ joins (~aforemny@2001:9e8:6cd2:2300:81b8:672c:d485:69b9)
04:47:15 × aforemny quits (~aforemny@i59F516CC.versanet.de) (Ping timeout: 256 seconds)
04:48:41 × nate4 quits (~nate@c-98-45-158-125.hsd1.ca.comcast.net) (Ping timeout: 245 seconds)
05:02:13 peterbecich joins (~Thunderbi@047-229-123-186.res.spectrum.com)
05:12:12 trev joins (~trev@user/trev)
05:16:55 × lg188 quits (~lg188@82.18.98.230) (Quit: Ping timeout (120 seconds))
05:17:16 lg188 joins (~lg188@82.18.98.230)
05:17:35 <glguy> int-e: you get to leverage so laziness for part 2?
05:17:54 <int-e> I didn't
05:19:15 <glguy> oh, maybe just recursively built up a list?
05:20:40 glguy tries to reframe this as a scanr
05:22:18 <probie> I used a boring `foldr` for part 2
05:23:58 <probie> glguy: c3VtICQgZm9sZHIgKFx4IHhzIC0+IDEgKyBzdW0gKHRha2UgKHgtMSkgeHMpOiB4cykgW10gKG1hcCBjb3VudFdpbm5lcnMgZ2FtZXMp is how I did it (base64 "encrypted" to avoid spoilers)
05:38:15 × peterbecich quits (~Thunderbi@047-229-123-186.res.spectrum.com) (Ping timeout: 260 seconds)
05:39:21 × azimut quits (~azimut@gateway/tor-sasl/azimut) (Remote host closed the connection)
05:39:47 azimut joins (~azimut@gateway/tor-sasl/azimut)
05:41:54 <EvanR> I want my client to decode64 when clicking on base64 encoded text
05:46:01 robobub joins (uid248673@id-248673.uxbridge.irccloud.com)
05:49:22 × azimut quits (~azimut@gateway/tor-sasl/azimut) (Remote host closed the connection)
05:49:46 azimut joins (~azimut@gateway/tor-sasl/azimut)
05:56:35 danza joins (~francesco@rm-19-56-167.service.infuturo.it)
05:58:34 × wroathe quits (~wroathe@user/wroathe) (Ping timeout: 255 seconds)
06:10:49 × euleritian quits (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) (Ping timeout: 255 seconds)
06:11:25 euleritian joins (~euleritia@dynamic-002-247-251-082.2.247.pool.telefonica.de)
06:16:20 zetef joins (~quassel@95.77.17.251)
06:22:13 chomwitt joins (~chomwitt@2a02:587:7a09:c300:1ac0:4dff:fedb:a3f1)
06:22:37 hapisnake joins (~hapisnake@103.28.246.140)
06:22:59 × JeremyB99 quits (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069) (Remote host closed the connection)
06:23:52 JeremyB99 joins (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069)
06:33:56 wroathe joins (~wroathe@207-153-38-140.fttp.usinternet.com)
06:33:57 × wroathe quits (~wroathe@207-153-38-140.fttp.usinternet.com) (Changing host)
06:33:57 wroathe joins (~wroathe@user/wroathe)
06:34:43 × hapisnake quits (~hapisnake@103.28.246.140) (Quit: Client closed)
06:45:02 × wroathe quits (~wroathe@user/wroathe) (Ping timeout: 255 seconds)
06:45:44 nate4 joins (~nate@c-98-45-158-125.hsd1.ca.comcast.net)
06:46:21 peterbecich joins (~Thunderbi@047-229-123-186.res.spectrum.com)
06:48:32 rosco joins (~rosco@175.136.158.171)
06:50:13 × nate4 quits (~nate@c-98-45-158-125.hsd1.ca.comcast.net) (Ping timeout: 256 seconds)
06:50:46 × danza quits (~francesco@rm-19-56-167.service.infuturo.it) (Ping timeout: 255 seconds)
06:50:55 × clwif^ quits (~cd@c-98-242-74-66.hsd1.ga.comcast.net) (Remote host closed the connection)
06:55:16 × euleritian quits (~euleritia@dynamic-002-247-251-082.2.247.pool.telefonica.de) (Read error: Connection reset by peer)
06:55:33 euleritian joins (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de)
06:56:41 <EvanR> the more I think about part 2 the less I understand it
06:56:54 <EvanR> luckily I got my stars already
06:59:51 × euleritian quits (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) (Ping timeout: 256 seconds)
07:00:11 euleritian joins (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de)
07:02:01 × zetef quits (~quassel@95.77.17.251) (Ping timeout: 245 seconds)
07:05:59 × peterbecich quits (~Thunderbi@047-229-123-186.res.spectrum.com) (Ping timeout: 260 seconds)
07:08:12 Sgeo_ joins (~Sgeo@user/sgeo)
07:11:35 × Sgeo quits (~Sgeo@user/sgeo) (Ping timeout: 260 seconds)
07:11:36 zetef joins (~quassel@95.77.17.251)
07:16:36 acidjnk joins (~acidjnk@p200300d6e72b9356246dd2d07051f792.dip0.t-ipconnect.de)
07:16:36 × euleritian quits (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) (Read error: Connection reset by peer)
07:16:43 euleritian joins (~euleritia@dynamic-002-247-251-082.2.247.pool.telefonica.de)
07:17:05 × euleritian quits (~euleritia@dynamic-002-247-251-082.2.247.pool.telefonica.de) (Read error: Connection reset by peer)
07:17:21 euleritian joins (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de)
07:25:38 misterfish joins (~misterfis@84-53-85-146.bbserv.nl)
07:30:03 sord937 joins (~sord937@gateway/tor-sasl/sord937)
07:37:38 × sord937 quits (~sord937@gateway/tor-sasl/sord937) (Remote host closed the connection)
07:37:59 sord937 joins (~sord937@gateway/tor-sasl/sord937)
07:48:51 lortabac joins (~lortabac@2a01:e0a:541:b8f0:55ab:e185:7f81:54a4)
07:53:16 × iqubic quits (~avi@2601:602:9502:c70:774c:879b:1855:10ba) (Ping timeout: 245 seconds)
07:54:06 × zetef quits (~quassel@95.77.17.251) (Ping timeout: 245 seconds)
07:55:57 danse-nr3 joins (~danse@na-19-84-78.service.infuturo.it)
07:56:59 × danse-nr3 quits (~danse@na-19-84-78.service.infuturo.it) (Remote host closed the connection)
07:57:21 danse-nr3 joins (~danse@na-19-84-78.service.infuturo.it)
08:01:43 × azimut quits (~azimut@gateway/tor-sasl/azimut) (Ping timeout: 240 seconds)
08:02:46 CiaoSen joins (~Jura@2a05:5800:2d9:1600:ca4b:d6ff:fec1:99da)
08:02:59 × misterfish quits (~misterfis@84-53-85-146.bbserv.nl) (Ping timeout: 264 seconds)
08:04:15 <EvanR> ah ha!
08:04:56 fendor joins (~fendor@2a02:8388:1605:d100:267b:1353:13d7:4f0c)
08:07:06 zetef joins (~quassel@95.77.17.251)
08:12:35 × _d0t quits (~{-d0t-}@user/-d0t-/x-7915216) (Ping timeout: 268 seconds)
08:15:47 _d0t joins (~{-d0t-}@user/-d0t-/x-7915216)
08:21:30 × tzh quits (~tzh@c-71-193-181-0.hsd1.or.comcast.net) (Quit: zzz)
08:24:03 waleee joins (~waleee@h-176-10-144-38.NA.cust.bahnhof.se)
08:24:49 coot joins (~coot@89.69.206.216)
08:28:41 misterfish joins (~misterfis@84-53-85-146.bbserv.nl)
08:37:04 × lg188 quits (~lg188@82.18.98.230) (Quit: Ping timeout (120 seconds))
08:37:27 lg188 joins (~lg188@82.18.98.230)
08:37:38 dcoutts joins (~duncan@cpc69402-oxfd27-2-0-cust903.4-3.cable.virginm.net)
08:37:56 idgaen joins (~idgaen@2a01:e0a:498:fd50:fcc6:bb5d:489a:ce8c)
08:42:08 × FinnElija quits (~finn_elij@user/finn-elija/x-0085643) (Remote host closed the connection)
08:42:40 × dcoutts quits (~duncan@cpc69402-oxfd27-2-0-cust903.4-3.cable.virginm.net) (Ping timeout: 276 seconds)
08:42:48 FinnElija joins (~finn_elij@user/finn-elija/x-0085643)
08:46:58 × coot quits (~coot@89.69.206.216) (Quit: coot)
08:48:16 gmg joins (~user@user/gehmehgeh)
08:50:28 × euleritian quits (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) (Read error: Connection reset by peer)
08:51:30 euleritian joins (~euleritia@dynamic-002-247-251-082.2.247.pool.telefonica.de)
08:56:45 × Sgeo_ quits (~Sgeo@user/sgeo) (Read error: Connection reset by peer)
08:58:55 × TMA quits (tma@twin.jikos.cz) (Ping timeout: 276 seconds)
09:00:04 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
09:03:37 × steew quits (~steew@user/steew) (Ping timeout: 255 seconds)
09:03:45 <danse-nr3> morning. Enjoying reading abuseofnotation.github.io/category-theory-illustrated, although it may look like kindergarden study material to many
09:04:47 × Incredia quits (~Incredia@176.254.244.83) (Ping timeout: 264 seconds)
09:06:40 Square2 joins (~Square4@user/square)
09:08:23 × zetef quits (~quassel@95.77.17.251) (Ping timeout: 264 seconds)
09:14:15 cfricke joins (~cfricke@user/cfricke)
09:17:20 × YoungFrog quits (~youngfrog@2a02:a03f:ca07:f900:3d37:6f51:8df5:683d) (Ping timeout: 268 seconds)
09:19:56 zetef joins (~quassel@95.77.17.251)
09:21:15 × infinity0 quits (~infinity0@pwned.gg) (Remote host closed the connection)
09:23:22 infinity0 joins (~infinity0@pwned.gg)
09:23:43 Incredia joins (~Incredia@176.254.244.83)
09:23:54 × Square2 quits (~Square4@user/square) (Quit: Leaving)
09:24:23 Square2 joins (~Square4@user/square)
09:24:59 pretty_dumm_guy joins (trottel@gateway/vpn/protonvpn/prettydummguy/x-88029655)
09:27:33 × econo_ quits (uid147250@id-147250.tinside.irccloud.com) (Quit: Connection closed for inactivity)
09:29:36 coot joins (~coot@89-69-206-216.dynamic.chello.pl)
09:30:21 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:d9f3:ec2f:a760:e0fe) (Remote host closed the connection)
09:33:46 alp_ joins (~alp@2001:861:e3d6:8f80:59a0:3738:2d56:41bc)
09:34:28 × waleee quits (~waleee@h-176-10-144-38.NA.cust.bahnhof.se) (Ping timeout: 256 seconds)
09:34:47 × shriekingnoise quits (~shrieking@186.137.175.87) (Ping timeout: 264 seconds)
09:51:23 chele joins (~chele@user/chele)
10:01:20 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:d9f3:ec2f:a760:e0fe)
10:02:04 iqubic joins (~avi@2601:602:9502:c70:7ce7:f8c:f1d2:dccf)
10:02:46 __monty__ joins (~toonn@user/toonn)
10:03:41 × zetef quits (~quassel@95.77.17.251) (Ping timeout: 245 seconds)
10:05:12 × danse-nr3 quits (~danse@na-19-84-78.service.infuturo.it) (Remote host closed the connection)
10:09:28 danse-nr3 joins (~danse@na-19-84-78.service.infuturo.it)
10:09:45 kuribas joins (~user@ip-188-118-57-242.reverse.destiny.be)
10:11:04 × tomboy64 quits (~tomboy64@user/tomboy64) (Ping timeout: 276 seconds)
10:14:08 × Lord_of_Life quits (~Lord@user/lord-of-life/x-2819915) (Ping timeout: 256 seconds)
10:14:12 zetef joins (~quassel@95.77.17.251)
10:14:41 Lord_of_Life joins (~Lord@user/lord-of-life/x-2819915)
10:15:01 malte joins (~malte@mal.tc)
10:18:40 guy80 joins (~guy@250.79-105-213.static.virginmediabusiness.co.uk)
10:19:27 guy80 is now known as telem
10:19:42 <telem> hi, im reading about solidity
10:19:51 <telem> it uses top level variables
10:19:56 × misterfish quits (~misterfis@84-53-85-146.bbserv.nl) (Ping timeout: 245 seconds)
10:20:05 <telem> i want to understand how this fits into the haskell story
10:20:19 <danse-nr3> haskell also has top level vals
10:20:27 <telem> but they are immutable
10:20:51 <telem> like, not variable
10:21:05 <telem> we have top level immutable values
10:21:35 <telem> is it something to do with the evaluation order?
10:21:43 <telem> like, in do syntax you can overwrite them
10:21:53 <telem> its something to do with it not being imperative?
10:22:03 <danse-nr3> that is shadowing more than overwriting
10:22:24 <telem> sure, but it would throw a syntax error at top level right?
10:22:31 <telem> about conflicting function definitions...
10:22:40 <telem> or it would just strat trying to pattern match them or something
10:22:43 <telem> ahhh, maybe thats it
10:22:55 <telem> so all the declerations are taken to be simultaniously true
10:23:09 tomboy64 joins (~tomboy64@user/tomboy64)
10:23:09 <telem> that kind of makes sense about the top down imperative evaluation order
10:23:16 <telem> kind of adds a sort of temporality
10:23:23 <telem> temporal scoping*
10:24:12 <telem> i guess thats why you can overwrite a top level value in a restrected scope
10:24:30 <telem> im always amazed how much scoping considerations affect the language
10:24:41 <telem> i think its what makes it so different to imperative languages
10:24:54 <telem> i think i understand how top level variables fit into this now
10:25:09 <telem> so i answerd my own question! but i didnt think i could do that when i asked it!
10:25:12 <telem> derp
10:25:20 <danse-nr3> you are welcome
10:25:30 <telem> yeah, thanks for the input
10:25:37 <telem> i was kind of hoping there could be some interesting offshoot
10:25:59 <telem> but then i just trying to think about carried scopes in imperative program specifications in some DSL
10:26:27 <telem> i think that would make a really cool haskell style language
10:26:54 <telem> i guess kind of making the list of active variables in a do-like block
10:27:02 <telem> making it explicit
10:27:44 <telem> i was doing something like that, where i had programs in datatypes so you could modify them
10:28:25 <telem> but then there was a kind of horrible formalism of how you would have to write the corresponding program in pure haskell so that its implementation would map over nicely to how it would be written in the DSL
10:29:34 <telem> you end up implementing a sort of graph with explicit shape decorations that the program sits ontop of, which essentially mimics how top level functions fit together to form a program graph
10:29:53 <telem> and then get frustrated at the idea of having to somehow compile pure code to it
10:30:25 ridcully_ joins (~ridcully@p57b52ac5.dip0.t-ipconnect.de)
10:30:43 <telem> but then, if you can either do that, or are happy writing it by hand, then in these imperative subsequent code lines, then you can repeatedly modify the program with lenses into it and stuff
10:31:15 <telem> modify_program all_if_statements_are_true
10:32:11 <telem> im not sure if anything would be lost with these semantics
10:32:16 × ridcully quits (~ridcully@p508acfd3.dip0.t-ipconnect.de) (Ping timeout: 255 seconds)
10:32:32 <telem> other than pattern matching using multiple lines of function decleartion
10:33:27 <telem> i think also, re with me cos this is kind of mind-bending. so, something like, to level value declerations *replacing* pattern matching
10:33:46 <telem> like, where do you specify the value name. some languages have it in the type sig
10:33:55 <telem> f :: (x :: String) -> Bool
10:34:07 <telem> while in the imperative style its
10:34:10 <telem> x :: String
10:34:16 <telem> f :: x -> Bool
10:34:24 <telem> or something like that
10:34:48 <telem> obviously that conflicts with polymorphic syntax
10:35:29 <telem> seems to force pattern matching into the type signature, not sure to what effect!
10:36:26 <telem> i guess if the imperative ordering risked shadowing or overwriting the value, then a distinguishing annotation to a required type signature could kind of handle both value overwrites, and pattern matching which does not overwrite, other than matching a seperate case
10:36:58 <telem> and then how you would treat unreachable patterns
10:37:20 <telem> i think we already *have* the imperative ordering for patterns which makes me suspicious!
10:37:31 <telem> i hate it when it makes *too much* sense!
10:37:48 <telem> makes me think im onto something, which makes me afraid!
10:38:17 <telem> so im glad that was useful!?
10:38:40 <telem> and then like, i guess i dont have to wait for a response then... ciao?
10:38:51 × telem quits (~guy@250.79-105-213.static.virginmediabusiness.co.uk) (Quit: Connection closed)
10:40:23 × euleritian quits (~euleritia@dynamic-002-247-251-082.2.247.pool.telefonica.de) (Read error: Connection reset by peer)
10:40:43 euleritian joins (~euleritia@77.22.252.56)
10:46:57 nate4 joins (~nate@c-98-45-158-125.hsd1.ca.comcast.net)
10:48:49 × remedan quits (~remedan@ip-94-112-0-18.bb.vodafone.cz) (Quit: Bye!)
10:52:02 × nate4 quits (~nate@c-98-45-158-125.hsd1.ca.comcast.net) (Ping timeout: 252 seconds)
10:56:43 × mobivme quits (~mobivme@112.201.111.217) (Ping timeout: 256 seconds)
10:59:55 oo_miguel joins (~Thunderbi@78-11-179-96.static.ip.netia.com.pl)
11:00:02 mobivme joins (~mobivme@112.201.111.217)
11:01:07 × danse-nr3 quits (~danse@na-19-84-78.service.infuturo.it) (Ping timeout: 256 seconds)
11:02:17 `2jt joins (~jtomas@90.162.208.36)
11:04:20 remedan joins (~remedan@ip-94-112-0-18.bb.vodafone.cz)
11:06:47 × zetef quits (~quassel@95.77.17.251) (Ping timeout: 256 seconds)
11:16:15 misterfish joins (~misterfis@87.215.131.102)
11:16:22 zetef joins (~quassel@95.77.17.251)
11:27:29 bitmapper joins (uid464869@id-464869.lymington.irccloud.com)
11:30:25 YoungFrog joins (~youngfrog@2a02:a03f:ca07:f900:1f5c:a3c6:297:feeb)
11:34:49 × lortabac quits (~lortabac@2a01:e0a:541:b8f0:55ab:e185:7f81:54a4) (Ping timeout: 255 seconds)
11:35:12 dcoutts joins (~duncan@cpc69402-oxfd27-2-0-cust903.4-3.cable.virginm.net)
11:39:49 × lottaquestions quits (~nick@2607:fa49:503d:b200:791c:1e35:f3fd:c3f3) (Remote host closed the connection)
11:40:15 lottaquestions joins (~nick@2607:fa49:503d:b200:2d55:64ae:c120:e947)
11:45:34 × pretty_dumm_guy quits (trottel@gateway/vpn/protonvpn/prettydummguy/x-88029655) (Quit: WeeChat 3.5)
11:46:27 pretty_dumm_guy joins (trottel@gateway/vpn/protonvpn/prettydummguy/x-88029655)
11:51:14 shriekingnoise joins (~shrieking@186.137.175.87)
11:51:23 danse-nr3 joins (~danse@na-19-84-78.service.infuturo.it)
11:55:53 × danse-nr3 quits (~danse@na-19-84-78.service.infuturo.it) (Read error: Connection reset by peer)
11:56:11 danse-nr3 joins (~danse@151.47.50.89)
11:57:01 × __monty__ quits (~toonn@user/toonn) (Ping timeout: 245 seconds)
11:58:42 __monty__ joins (~toonn@user/toonn)
12:00:04 × JeremyB99 quits (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069) (Read error: Connection reset by peer)
12:03:08 ritog joins (~ritog@45.112.243.193)
12:03:38 JeremyB99 joins (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069)
12:04:00 × JeremyB99 quits (~JeremyB99@2600:1702:21b0:a500:b427:1e7a:fffe:f069) (Read error: Connection reset by peer)
12:05:07 _ht joins (~Thunderbi@28-52-174-82.ftth.glasoperator.nl)
12:05:19 Sciencentistguy7 joins (~sciencent@hacksoc/ordinary-member)
12:06:55 lortabac joins (~lortabac@2a01:e0a:541:b8f0:55ab:e185:7f81:54a4)
12:08:28 × Sciencentistguy quits (~sciencent@hacksoc/ordinary-member) (Ping timeout: 268 seconds)
12:08:28 Sciencentistguy7 is now known as Sciencentistguy
12:10:50 × zetef quits (~quassel@95.77.17.251) (Ping timeout: 260 seconds)
12:11:43 × jjhoo quits (~jahakala@user/jjhoo) (Ping timeout: 255 seconds)
12:14:32 × ritog quits (~ritog@45.112.243.193) (Quit: Leaving)
12:15:52 Tisoxin joins (~Ikosit@user/ikosit)
12:18:41 jjhoo joins (~jahakala@user/jjhoo)
12:20:17 <Tisoxin> Hi! Is there a lens combinator (in the lens package) that allows me to do
12:20:17 <Tisoxin> > [1, 2, 3] & ix 1 `cbr` \x -> Just (x+1)
12:20:17 <Tisoxin> ⇒ Just [1, 3, 3]
12:20:17 <Tisoxin> > [1, 2, 3] & ix 1 `cbr` \x -> Nothing
12:20:17 <Tisoxin> ⇒ Nothing
12:20:18 <Tisoxin> cbr is the lens combinator I'm searching
12:20:18 <lambdabot> error:
12:20:18 <lambdabot> • Variable not in scope:
12:20:19 <lambdabot> cbr :: (m0 -> f0 m0) -> (a1 -> Maybe a1) -> t
12:20:19 <lambdabot> error:
12:20:19 <lambdabot> • Variable not in scope:
12:20:20 <lambdabot> cbr :: (m0 -> f0 m0) -> (p0 -> Maybe a0) -> t
12:21:11 <ncf> id?
12:21:49 <ncf> > [1,2,3] & ix 1 `id` (\x -> Just (x+1))
12:21:51 <lambdabot> Just [1,3,3]
12:21:52 <ncf> > [1,2,3] & ix 1 `id` (\x -> Nothing)
12:21:53 <lambdabot> Nothing
12:22:36 <ncf> or if you want to pretend that lens doesn't use the van laarhoven encoding, (%%~) https://hackage.haskell.org/package/lens-5.2.3/docs/Control-Lens-Lens.html#v:-37--37--126-
12:22:58 <ncf> (i think that's a good idea, actually!)
12:23:23 <Tisoxin> ok thanks, I guess I should really once again take a look at how exactly lenses work
12:23:29 waleee joins (~waleee@h-176-10-144-38.NA.cust.bahnhof.se)
12:23:55 <Tisoxin> I also just now found traverseOf which should do the right thing as well™
12:24:44 <Tisoxin> Thanks ncf!
12:24:56 <ncf> what you're asking for is basically the "universal use case" for traversals; so much so that they're encoded that way: in the lens library, a Traversal s t a b is a polymorphic function (forall f. Applicative f => (a -> f b) -> s -> f t)
12:26:06 <ncf> for an analogy, if you consider that the universal use case for natural numbers is to be able to recurse on them, i.e. given a function and an initial value, apply the function n times to the initial value, then you end up with the "Church encoding" for natural numbers, (forall a. (a -> a) -> a -> a)
12:27:34 <Tisoxin> very interesting, I didn't now that this is how one can construct the church encoding of a type but it's very intuitive
12:29:12 <dminuoso_> Tisoxin: I think what you're really after is just `at`
12:29:34 <dminuoso_> Which captures writing/updating/deleting indexed elements via a lens.
12:31:02 <Tisoxin> I don't think so. `at` only works for Maps and not for lists afaik
12:32:11 × CiaoSen quits (~Jura@2a05:5800:2d9:1600:ca4b:d6ff:fec1:99da) (Ping timeout: 260 seconds)
12:33:56 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
12:34:01 <dminuoso_> Ah. Mmm.
12:34:20 <dminuoso_> Oh, I did read your initial question wrong too, you dont mean to delete with Nothing.
12:36:47 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
12:37:01 × danse-nr3 quits (~danse@151.47.50.89) (Ping timeout: 245 seconds)
12:37:38 <dminuoso_> Tisoxin: To continue on ncf's points, a Lens then is just a (forall f. Functor f => (a -> f b) -> s -> f t) - and the rationale here is that instead of focusing on "multiple" points (where you have to combine the effects via Applicative), it focus only on a single thing.
12:37:49 <dminuoso_> Which is why you only have Functor (since no combination of effects occur)
12:37:51 <dminuoso_> > (1, 2) & _1 `id` (\x -> Just (x + 1))
12:37:52 <lambdabot> Just (2,2)
12:39:06 <Tisoxin> hm, ok; thanks
12:39:27 simendsjo joins (~user@84.209.170.3)
12:41:09 danse-nr3 joins (~danse@151.47.50.89)
12:41:13 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
12:43:24 <dminuoso_> % data Vec3 a b c = Vec3 a b c
12:43:24 <yahb2> <no output>
12:43:36 <dminuoso_> % traverseV3 f = \(Vec3 a b c) -> Vec3 <$> f a <*> f b <*> f c
12:43:37 <yahb2> <no output>
12:43:40 <dminuoso_> % l1 f = \(Vec3 a b c) -> (\x -> Vec3 x b c) <$> f a
12:43:40 <yahb2> <no output>
12:43:44 <dminuoso_> % l1 f = \(Vec3 a b c) -> (\x -> Vec3 x b c) <$> f a
12:43:44 <yahb2> <no output>
12:43:50 <dminuoso_> err that one should have been named l2.
12:44:07 <dminuoso_> Tisoxin: ^- Do you see how Lens is a sort of degenerate traversal that doesnt run over the entire thing?
12:44:51 <dminuoso_> % l1 f = \(Vec3 a b c) -> (\x -> Vec3 x b c) <$> f a
12:44:51 <yahb2> <no output>
12:44:54 <dminuoso_> % l2 f = \(Vec3 a b c) -> (\x -> Vec3 a x c) <$> f b
12:44:55 <yahb2> <no output>
12:51:08 akegalj joins (~akegalj@78-1-167-210.adsl.net.t-com.hr)
12:51:17 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
12:51:50 <Tisoxin> > Tisoxin: ^- Do you see how Lens is a sort of degenerate traversal that doesnt run over the entire thing?
12:51:50 <Tisoxin> yes
12:51:51 <lambdabot> <hint>:1:10: error: parse error on input ‘^-’
12:55:29 × jespada quits (~jespada@cpc121308-nmal25-2-0-cust15.19-2.cable.virginm.net) (Read error: Connection reset by peer)
12:55:32 jespada_ joins (~jespada@cpc121308-nmal25-2-0-cust15.19-2.cable.virginm.net)
12:55:41 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: Textual IRC Client: www.textualapp.com)
12:56:46 azimut joins (~azimut@gateway/tor-sasl/azimut)
12:57:13 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
12:58:04 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
12:59:26 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
13:03:18 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
13:09:40 [itchyjunk] joins (~itchyjunk@user/itchyjunk/x-7353470)
13:11:46 zetef joins (~quassel@95.77.17.251)
13:13:03 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
13:13:31 × [_] quits (~itchyjunk@user/itchyjunk/x-7353470) (Ping timeout: 268 seconds)
13:16:15 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
13:16:29 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
13:17:03 sawilagar joins (~sawilagar@user/sawilagar)
13:17:27 × sawilagar quits (~sawilagar@user/sawilagar) (Remote host closed the connection)
13:17:50 sawilagar joins (~sawilagar@user/sawilagar)
13:18:05 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
13:22:57 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
13:23:16 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
13:23:34 rgh joins (~ritog@45.112.243.193)
13:25:59 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
13:26:43 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
13:29:43 pastly joins (~pastly@gateway/tor-sasl/pastly)
13:35:44 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
13:36:26 rgh is now known as ritog
13:36:33 ritog is now known as rito
13:37:49 CiaoSen joins (~Jura@2a05:5800:2d9:1600:ca4b:d6ff:fec1:99da)
13:38:55 × iqubic quits (~avi@2601:602:9502:c70:7ce7:f8c:f1d2:dccf) (Ping timeout: 260 seconds)
13:40:46 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
13:40:59 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
13:43:09 <haskellbridge> 12<B​enno Fünfstück> @djinn (a -> b) -> [a] -> [b]
13:44:29 <ncf> can't djinn from the bridge
13:44:38 × gabiruh quits (~gabiruh@vps19177.publiccloud.com.br) (Ping timeout: 260 seconds)
13:46:37 × danse-nr3 quits (~danse@151.47.50.89) (Read error: Connection reset by peer)
13:47:26 × misterfish quits (~misterfis@87.215.131.102) (Ping timeout: 260 seconds)
13:50:18 <haskellbridge> 12<B​enno Fünfstück> sad :( is there an online versoin of djinn somewhere
13:51:49 <xerox> on irc
13:52:06 gabiruh joins (~gabiruh@vps19177.publiccloud.com.br)
13:53:43 × phma quits (phma@2001:5b0:210d:4b88:db07:55ae:ef67:3fd5) (Read error: Connection reset by peer)
13:54:05 bennofs joins (~bennofs@141.76.100.206)
13:54:06 × ft quits (~ft@p508dbe71.dip0.t-ipconnect.de) (Ping timeout: 245 seconds)
13:54:31 phma joins (~phma@host-67-44-208-166.hnremote.net)
13:54:58 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
13:55:32 <probie> @djinn (a -> b) -> [a] -> [b]
13:55:33 <lambdabot> Error: Undefined type []
13:55:53 ft joins (~ft@p4fc2a395.dip0.t-ipconnect.de)
13:58:57 danse-nr3 joins (~danse@151.47.50.89)
13:59:31 <ncf> https://www.hedonisticlearning.com/djinn/ ?
14:01:48 <danse-nr3> interesting, looks like an alternative to hoogle
14:02:34 <danse-nr3> oh, no, > Generate Haskell code from a type
14:03:14 × Xyloes quits (~wyx@2400:dd01:103a:1012:5923:33ce:7857:fc04) (Quit: Konversation terminated!)
14:04:37 <akegalj> I ran into augustss implementation of BASIC http://augustss.blogspot.com/search/label/BASIC but I can't figure out why line "10 GOSUB 1000" works? How can this be valid? Source is here https://hackage.haskell.org/package/BASIC-0.1.5.0/docs/src/Language-BASIC-Parser.html#getBASIC and its pretty short. How can number 10 come before GOSUB. What magic is this?
14:06:00 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
14:06:29 <exarkun> akegalj: What would you say type of the numeric literal `10` is?
14:08:50 <akegalj> exarkun: I can't even guess. I would guess it is Num a
14:09:10 <exarkun> akegalj: What if, instead of `10`, that line had `f`? As in, `f GOSUB 1000`?
14:09:13 <exarkun> What's the type of f?
14:09:23 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
14:10:11 <akegalj> exarkun: f would be some function in this case as its bound to some type variable. But its not literal
14:10:47 <exarkun> "f would be some function" -> indeed. I'm not sure what you mean by "its bound to some type variable".
14:11:14 × danse-nr3 quits (~danse@151.47.50.89) (Ping timeout: 260 seconds)
14:11:43 <exarkun> How do you figure f would be a function just by looking at that expression?
14:11:55 <akegalj> exarkun: ignore type variable part
14:12:42 <akegalj> exarkun: its function becouse it takes two arguments, right ?
14:12:56 <exarkun> Yea
14:13:01 <akegalj> its applied to them by type aplication " "
14:13:08 <exarkun> yep
14:13:58 <akegalj> that doesn't make me less confused :D
14:14:20 <akegalj> is 10 a function ?
14:14:42 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
14:16:32 <exarkun> If `f x y` is function application to two arguments and the type checker accepts `10 x y` then ...?
14:17:06 <akegalj> exarkun: which type checker? Haskells ?
14:17:53 × bennofs quits (~bennofs@141.76.100.206) (Quit: Connection closed)
14:18:24 <exarkun> akegalj: yea
14:18:31 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
14:19:11 danse-nr3 joins (~danse@151.47.50.89)
14:19:23 <exarkun> akegalj: We can narrow down the type a bit. It's not just a function, but a function of two arguments, and those arguments have particular types.
14:20:19 <exarkun> Like, GOSUB is a constructor for GOTO
14:21:23 × dcoutts quits (~duncan@cpc69402-oxfd27-2-0-cust903.4-3.cable.virginm.net) (Ping timeout: 260 seconds)
14:21:25 dcoutts_ joins (~duncan@cpc69402-oxfd27-2-0-cust903.4-3.cable.virginm.net)
14:21:47 <exarkun> And we probably know something about its return type because the way you use this thing is with `runBASIC`' which accepts a value of `BASIC` (an alias for `Expr ()`)
14:22:10 <exarkun> So given that, what's a narrower type for `f` in `f GOSUB 1000`?
14:22:12 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
14:22:25 <akegalj> exarkun: Its Expr ()
14:22:44 thegeekinside joins (~thegeekin@189.141.65.247)
14:22:59 <exarkun> `f GOSUB 1000` is, yea. How about `f` by itself?
14:24:21 Unicorn_Princess joins (~Unicorn_P@user/Unicorn-Princess/x-3540542)
14:24:22 <akegalj> exarkun: I can't tell . Its f :: a -> b -> Expr ()
14:24:35 <akegalj> exarkun: where is this Expr defined?
14:24:59 <exarkun> Expr is in Types.hs
14:25:26 <probie> https://hackage.haskell.org/package/BASIC-0.1.5.0/docs/src/Language-BASIC-Types.html
14:25:38 <exarkun> `f :: a -> b -> Expr ()` is right but we can narrow it further. We saw GOSUB as a value for the first parameter, so we know `a` must be the type of GOSUB.
14:26:38 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
14:27:14 <probie> exarkun: I think you mean of type `GOTO`. `data GOTO = GOTO | GOSUB deriving (Eq)`
14:27:53 <akegalj> exarkun: yes, then is `f :: GOTO -> b -> Expr ()`
14:28:15 <exarkun> sorry yea. I mean whatever type `GOSUB` is must be the same as `a`. so, indeed, GOTO.
14:28:25 <akegalj> I guess this fits into `Cmd Integer Command [Expr a]` of the Expr type
14:30:10 × 040AADFUL quits (~nand@haasn.dev) (Killed (NickServ (GHOST command used by haasn!sid579015@id-579015.hampstead.irccloud.com)))
14:30:28 <exarkun> akegalj: Yea, getting close
14:30:30 haasn` joins (~nand@haasn.dev)
14:30:49 × idgaen quits (~idgaen@2a01:e0a:498:fd50:fcc6:bb5d:489a:ce8c) (Quit: WeeChat 4.1.1)
14:30:50 × zetef quits (~quassel@95.77.17.251) (Ping timeout: 256 seconds)
14:31:03 × haasn` quits (~nand@haasn.dev) (Remote host closed the connection)
14:32:29 <byorgey> akegalj: In Haskell, what type is 10?
14:32:42 <exarkun> So in, eg, the Func.hs example, we've got this do block full of similar things. Since these things return `Expr ()` and we use them in a `do` block, do we know something else about `Expr`?
14:33:31 <danse-nr3> % :t 10 -- this byorgey?
14:33:31 <yahb2> 10 -- this byorgey? :: Num a => a
14:34:26 <cheater> if i have two types, Foo and Bar that take the same kind of parameters (say 5 int parameters), can i somehow make the constructor a variable when creating the value with the constructor? something like x 1 2 3 4 5
14:35:06 <danse-nr3> yeah but maybe wrap the types in a product first
14:35:14 <akegalj> exarkun: sorry, where is Func.hs?
14:35:18 <exarkun> akegalj: https://hackage.haskell.org/package/BASIC-0.1.5.0/src/examples/Func.hs
14:35:32 <exarkun> just an arbitrary but specific example of using the library
14:36:03 <cheater> duh, put the constructor in a variable
14:36:04 <exarkun> although it doesn't use GOSUB so maybe not the bet choice
14:36:05 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
14:36:14 billchenchina joins (~billchenc@2a0d:2580:ff0c:1:e3c9:c52b:a429:5bfe)
14:36:17 × billchenchina quits (~billchenc@2a0d:2580:ff0c:1:e3c9:c52b:a429:5bfe) (Remote host closed the connection)
14:36:36 <akegalj> exarkun: ... sec ... to check that
14:36:58 <exarkun> Maybe https://hackage.haskell.org/package/BASIC-0.1.5.0/src/examples/HiLo.hs is closer to what you were looking at originally?
14:37:17 <exarkun> oh yea, I think that's the same example as from the blog post
14:37:22 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
14:37:57 machinedgod joins (~machinedg@modemcable243.147-130-66.mc.videotron.ca)
14:38:11 <akegalj> exarkun: yes, that's the same example
14:40:09 <akegalj> exarkun: I think I am confused with "parsing" part from Language.BASIC.Parser . I ll try to play around and see if I can figure this out. Fortunately example is quite short but I guess my mind can't bend over this one
14:40:25 <exarkun> akegalj: I think there's basically one more leap to make
14:40:55 <exarkun> I haven't hinted at it much yet because I want to let you figure out the surprise :)
14:41:02 <cheater> hm no that didn't work
14:41:10 <cheater> the two constructors are from different types
14:41:50 <exarkun> akegalj: You're on the right track thinking about `Cmd`. Keep thinking about that `f :: GOTO -> b -> Expr ()` type also.
14:42:06 <exarkun> And pay attention to the instances that Parser.hs defines
14:42:44 <akegalj> exarkun: thanks for hand holding, will play in repl to figure it out
14:43:36 <exarkun> np, have fun
14:46:09 × seeg123456 quits (~seeg12345@64.176.64.83) (Quit: Gateway shutdown)
14:46:45 <danse-nr3> maybe now we have more bandwidth cheater ... i was thinking that maybe i was wrong pointing to a product, could be a case for composition
14:47:11 <cheater> think about it this way
14:47:12 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
14:48:06 <cheater> data Foo = Foo Int deriving Show; data Bar = Bar Int deriving Show; if bool then show (Foo 2) else show (Bar 2)
14:48:27 nate4 joins (~nate@c-98-45-158-125.hsd1.ca.comcast.net)
14:48:41 <cheater> i want this to be something like: let x = if bool then Foo else Bar; show (x 2)
14:49:03 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
14:49:14 <danse-nr3> show $ if ?
14:49:42 <danse-nr3> hum maybe that does not type check actually
14:51:32 <danse-nr3> no it does not
14:52:11 <cheater> yeah
14:52:29 <danse-nr3> but `show` takes a constraint, i guess we should make an example with something else, as you probably do not want to use a class
14:53:44 × nate4 quits (~nate@c-98-45-158-125.hsd1.ca.comcast.net) (Ping timeout: 268 seconds)
14:55:53 seeg123456 joins (~seeg12345@64.176.64.83)
14:56:54 × simendsjo quits (~user@84.209.170.3) (Ping timeout: 252 seconds)
14:57:52 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
14:58:46 <akegalj> exarkun: byorgey: aha, the whole trickery is to implement instances of functions over Num typeclasses . When I reread I saw byorgey simple question "what type is 10" :D
15:00:58 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
15:01:06 <akegalj> do people tend to write DSLs using these tricks or is this not so common ?
15:01:13 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
15:02:44 <exarkun> I think this style is a fun joke that would practically never be used for serious code
15:04:17 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
15:05:09 × euleritian quits (~euleritia@77.22.252.56) (Ping timeout: 252 seconds)
15:05:34 euleritian joins (~euleritia@dynamic-002-247-248-235.2.247.pool.telefonica.de)
15:05:43 <kuribas> The problem with overly polymorphic code is that it can often compile, but into something different than intended.
15:06:07 <kuribas> Also function monad or Num instance is pretty hard to read.
15:06:57 <danse-nr3> i find function applicative legit at least. Num instance... a bit more edgy
15:07:40 <kuribas> Meh, 99% of obfuscated code examples are using the function applicative/monad.
15:08:08 <kuribas> If you really want this, insert a Reader newtype to make it explicit.
15:08:26 <exarkun> Also the Num instance in BASIC is trivially unlawful. It only provides fromInteger. And I'm not sure why the empty Eq and Show instances are there, but they have no implementation at all.
15:08:51 <probie> exarkun: Once upon a time, Haskell required both `Eq` and `Show` for `Num`
15:08:55 <exarkun> Could you implement the rest of them? I'm not sure. Probably not in a very meaningful or coherent way.
15:09:01 <exarkun> probie: Ah
15:09:54 <exarkun> akegalj: More concretely, the types say you can do `negate $ 10 GOTO 20` it will just crash at runtime if you try. Also, what could it even mean?
15:10:15 <exarkun> I mean .. maybe `negate $ 10 GOTO 20` should be the same as `20 COMEFROM 10`? :) But in general it's nonsense.
15:10:16 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
15:10:40 <exarkun> (actually 20 COMEFROM 10 probably equals 10 GOTO 20, maybe I meant 10 COMEFROM 20)
15:10:43 zetef joins (~quassel@95.77.17.251)
15:13:08 <kuribas> exarkun: intercal?
15:14:39 <exarkun> as legit a choice as BASIC!
15:15:11 <exarkun> (well maybe not)
15:15:14 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
15:15:19 <akegalj> exarkun: yes, I saw they are not lawful. Fun example no matter what
15:15:25 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
15:20:43 wib_jonas joins (~wib_jonas@business-37-191-60-209.business.broadband.hu)
15:22:54 misterfish joins (~misterfis@84-53-85-146.bbserv.nl)
15:25:27 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
15:25:56 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
15:35:17 × alp_ quits (~alp@2001:861:e3d6:8f80:59a0:3738:2d56:41bc) (Ping timeout: 252 seconds)
15:37:26 alp_ joins (~alp@2001:861:e3d6:8f80:c0c9:d001:c090:e9f8)
15:43:58 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
15:44:40 × bitdex quits (~bitdex@gateway/tor-sasl/bitdex) (Quit: = "")
15:45:05 iqubic joins (~avi@2601:602:9502:c70:3f43:b574:9cc8:e2f)
15:48:16 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
15:50:34 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
15:51:10 × chomwitt quits (~chomwitt@2a02:587:7a09:c300:1ac0:4dff:fedb:a3f1) (Ping timeout: 246 seconds)
15:53:16 × CiaoSen quits (~Jura@2a05:5800:2d9:1600:ca4b:d6ff:fec1:99da) (Ping timeout: 245 seconds)
15:57:26 × zetef quits (~quassel@95.77.17.251) (Ping timeout: 245 seconds)
15:58:41 × danse-nr3 quits (~danse@151.47.50.89) (Ping timeout: 245 seconds)
15:58:52 danse-nr3 joins (~danse@rm-19-41-115.service.infuturo.it)
16:02:20 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
16:06:25 × machinedgod quits (~machinedg@modemcable243.147-130-66.mc.videotron.ca) (Remote host closed the connection)
16:06:31 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
16:06:48 notzmv joins (~zmv@user/notzmv)
16:08:11 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
16:08:35 zetef joins (~quassel@95.77.17.251)
16:10:07 <iqubic> ski: I think you can use forall for existential qualification and fake heterogeneous lists.
16:11:33 <iqubic> data Showable = forall s. Show s => S s
16:12:04 <iqubic> And then you can have [Showable].
16:12:34 × euleritian quits (~euleritia@dynamic-002-247-248-235.2.247.pool.telefonica.de) (Read error: Connection reset by peer)
16:12:39 <iqubic> But the only thing you can do with the elements of that list is call the Show methods on them.
16:12:51 euleritian joins (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de)
16:13:08 × euleritian quits (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) (Read error: Connection reset by peer)
16:13:56 euleritian joins (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de)
16:16:49 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
16:17:01 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
16:19:31 × akegalj quits (~akegalj@78-1-167-210.adsl.net.t-com.hr) (Ping timeout: 245 seconds)
16:20:37 <byorgey> glguy: I did part 2 with a lazy recursively defined list, kind of ad-hoc though. I didn't figure out a way to formulate it as a scanr or anything. https://github.com/byorgey/AoC/blob/master/2023/04/04.hs#L49
16:21:17 <glguy> byorgey: I think the benefit of scanr would have been lost by having to post-process the result with map (take 1)
16:21:59 <byorgey> maybe so
16:22:07 <xerox> nice sprinkling of >>>
16:22:49 <byorgey> I always sprinkle >>> when solving programming challenges, but never use it in real projects =)
16:22:55 × lortabac quits (~lortabac@2a01:e0a:541:b8f0:55ab:e185:7f81:54a4) (Quit: WeeChat 4.1.1)
16:23:50 <danse-nr3> >>> considered harmful?
16:23:53 szkl joins (uid110435@id-110435.uxbridge.irccloud.com)
16:24:11 <byorgey> not at all, just a style thing
16:24:44 <xerox> my heat of the moment one was like this https://github.com/mrtnpaolo/advent-of-code-2023/blob/5e8feb7/execs/Day04.hs#L37-L42
16:25:47 <byorgey> ah, nice
16:26:43 × qqq quits (~qqq@92.43.167.61) (Quit: leaving)
16:26:49 <xerox> wished there was an insertwith that also returns the possibly different eventually inserted value
16:28:16 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
16:28:40 <byorgey> I feel like there must be a way to do that in one line with lens combinators.
16:29:44 <ski> iqubic : yes, `[Showable]' encodes `[exists s. Show s *> s]'
16:29:54 <ncf> i used löb https://github.com/ncfavier/aoc/blob/main/src/2023/Day04.hs
16:29:58 <ski> "ut the only thing you can do with the elements of that list is call the Show methods on them." -- yes
16:30:28 <xerox> löve that
16:31:21 <byorgey> ncf: fantastic
16:32:22 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
16:33:26 <ski> ncf : each one depends on the following `n' ?
16:33:41 <ncf> yes
16:33:58 <ski> sounds like a course-of-values recursion could also be used there, then
16:35:09 <ncf> yes that's what glguy did
16:35:15 <glguy> https://github.com/glguy/advent/blob/main/solutions/src/2023/04.hs#L57-L60
16:35:23 <ski> mhm
16:36:16 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
16:36:28 dhil joins (~dhil@2001:8e0:2014:3100:5872:f936:bc7a:ceb8)
16:36:50 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
16:36:59 <ncf> re lens, probably something with (<%~)
16:37:51 × misterfish quits (~misterfis@84-53-85-146.bbserv.nl) (Ping timeout: 256 seconds)
16:38:01 × danse-nr3 quits (~danse@rm-19-41-115.service.infuturo.it) (Ping timeout: 255 seconds)
16:39:00 <cheater> what are those directories called ~/.ghcup/hls/1.2.3.4 ? i mean i know they're related to the hls, but how do i get rid of them? i have two, one's called 2.4.0.0 and the other called 1.9.0.0. i guess i don't need both, so how do i get rid of one? they're 2 gigs a pop
16:39:47 <glguy> cheater: if you use "ghcup tui", you can uninstall things with the u key
16:40:30 <ncf> insertWith' f k v = at k <%~ \x -> f v <$> x <|> Just v
16:40:34 <glguy> While you're there you can uninstall both and upgrade to 2.5.0.0 if you want
16:40:35 <cheater> is there any reason at all to have two different versions of hls?
16:40:58 <haskellbridge> 14<m​aerwald> Yes
16:41:18 <haskellbridge> 14<m​aerwald> Hls 2.5.0.0 doesn't support GHC 9.4.7 anymore
16:41:45 <haskellbridge> 14<m​aerwald> If you use vscode, it can downgrade automatically if your project GHC is e.g. 9.4.7
16:42:17 <cheater> https://i.imgur.com/S2VPCmH.png
16:42:19 <glguy> are a lot of projects that use 9.4.7 not compatible with 9.4.8?
16:42:28 <cheater> i honestly don't even use hls at all right now
16:42:41 <cheater> i might look into setting it up with vim
16:43:13 <glguy> I use it both with vim and vscode - it's pretty useful
16:43:31 × juri_ quits (~juri@faikvm.com) (Ping timeout: 255 seconds)
16:43:42 <ncf> insertWith'' f k v = alterF (\x -> let x' = maybe (f v) v x in (x, Just x)) k
16:44:29 <ncf> er
16:44:37 <ncf> insertWith'' f k v = alterF (\x -> let x' = maybe v (f v) x in (x', Just x')) k
16:44:48 <iqubic> I haven't updated to 9.6.2 because jle's advent-of-code-api fails to work with newer versions of transformers. I think it's something to do with liftIO not being re-exported.
16:45:08 <iqubic> jle`: you might want to fix this.
16:45:43 Guest87 joins (~Guest87@2409:11:1420:a600:fc27:c511:dd24:c407)
16:46:23 × Guest87 quits (~Guest87@2409:11:1420:a600:fc27:c511:dd24:c407) (Client Quit)
16:46:32 <cheater> what is the haskellbridge bridging towards
16:46:59 <yushyin> matrix
16:47:57 <yushyin> the room name is haskell-irc, iirc
16:48:38 <cheater> OK
16:49:14 chomwitt joins (~chomwitt@2a02:587:7a09:c300:1ac0:4dff:fedb:a3f1)
16:49:19 × YoungFrog quits (~youngfrog@2a02:a03f:ca07:f900:1f5c:a3c6:297:feeb) (Ping timeout: 260 seconds)
16:49:58 <geekosaur> yes
16:50:25 juri_ joins (~juri@faikvm.com)
16:50:57 <geekosaur> if you /whois haskellbridge it'll give you some more information
16:51:21 <yushyin> nice
16:51:24 <geekosaur> although there isn't enough room to list all the bridged channels and where they go
16:53:23 <geekosaur> hm, didn't include matrix in that, should fix that
16:53:59 × zetef quits (~quassel@95.77.17.251) (Ping timeout: 264 seconds)
16:54:03 <cheater> geekosaur: the /whois doesn't tell me anything
16:56:23 <ski> -!- ircname : Haskell matterbridge operated by geekosaur
16:56:54 <geekosaur> it tells you the important part which is who to contact for more information
16:56:57 <cheater> yeah i saw that
16:57:03 <cheater> but i already knew that part
16:57:07 <geekosaur> as I said, there isn;'t enough room (IRC limits) to really say more
16:57:08 <cheater> since you're the one who told me about it
16:57:10 <cheater> lol
16:57:32 <cheater> try setting your ircname to "Haskell chat bridge https://tiny.co/blah"
16:57:54 YoungFrog joins (~youngfrog@2a02:a03f:ca07:f900:1f5c:a3c6:297:feeb)
17:00:53 TMA joins (tma@twin.jikos.cz)
17:01:11 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
17:01:23 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
17:02:31 <trev> glguy: can you explain to me (a dummy) how your part 2 works? even printing out the accumulator each fold, i still can't grasp it :|
17:02:31 × wib_jonas quits (~wib_jonas@business-37-191-60-209.business.broadband.hu) (Quit: Client closed)
17:03:23 <glguy> trev: it's building up a list of how many total cards you get by playing one of each card in the list
17:04:24 <glguy> so you start with: wins_on_card_1 : wins_on_card_2 : ... : []
17:04:49 <glguy> the output in each position is how many cards one of that card turns into
17:05:06 idgaen joins (~idgaen@2a01:e0a:498:fd50:fcc6:bb5d:489a:ce8c)
17:05:15 euandreh joins (~Thunderbi@189.6.18.26)
17:05:17 <glguy> foldr replaces all of those : constructors in the input with a function
17:05:43 <glguy> The function takes two things: the number of wins on the current card and the output list for all cards following it
17:06:03 <glguy> It extends that output list by one element, that element is the number of cards this card will turn into
17:06:07 × iqubic quits (~avi@2601:602:9502:c70:3f43:b574:9cc8:e2f) (Ping timeout: 260 seconds)
17:07:00 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
17:07:53 <glguy> f wins_1 (f wins_2 (f wins_3 [])) ==> f wins_1 (f wins_2 [output_3]) ==> f wins_1 [output_2, output_3] ==> [output_1, output_2, output_3]
17:08:02 <trev> i guess i don't even understand the first iteration of the fold - the accumulator is [] and then you prepend `1 + sum (take wins xs)` but that should just be 1
17:08:04 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
17:08:16 × `2jt quits (~jtomas@90.162.208.36) (Ping timeout: 255 seconds)
17:08:27 <glguy> The very last card in the list will necessarily have 0 wins on it
17:08:46 <glguy> so you'll have: f 0 [] ==> 1 + sum (take 0 []) : [] ==> [1,]
17:08:51 <glguy> s/,//
17:09:19 <trev> ah so it's going backwards
17:09:21 <glguy> so that last card doesn't turn into any more cards, when you play it you only play 1 card
17:09:37 × coot quits (~coot@89-69-206-216.dynamic.chello.pl) (Quit: coot)
17:10:04 × AlexZenon quits (~alzenon@5.139.232.120) (Ping timeout: 256 seconds)
17:10:21 coot joins (~coot@89-69-206-216.dynamic.chello.pl)
17:10:41 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:d9f3:ec2f:a760:e0fe) (Remote host closed the connection)
17:10:57 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:d9f3:ec2f:a760:e0fe)
17:11:24 <trev> thanks. genius solution
17:12:46 × phma quits (~phma@host-67-44-208-166.hnremote.net) (Read error: Connection reset by peer)
17:12:49 × fendor quits (~fendor@2a02:8388:1605:d100:267b:1353:13d7:4f0c) (Remote host closed the connection)
17:13:34 phma joins (~phma@2001:5b0:2143:bdc8:5f21:c979:aa9:dd43)
17:13:57 <trev> i confused myself since i'm doing it in OCaml which doesn't have tail recursion on foldr so i was using foldl and reversing the input -_-
17:14:02 × YoungFrog quits (~youngfrog@2a02:a03f:ca07:f900:1f5c:a3c6:297:feeb) (Ping timeout: 256 seconds)
17:14:17 <glguy> Oh, you could reverse and foldl like this just fine
17:14:39 <trev> yeah, it works that way. i forgot about the rev and couldn't conceptualize it in my mind
17:14:47 <glguy> ah, I see
17:15:47 YoungFrog joins (~youngfrog@2a02:a03f:ca07:f900:1f5c:a3c6:297:feeb)
17:16:58 <ski> trev : "OCaml which doesn't have tail recursion on foldr" -- Haskell doesn't, either
17:17:06 AlexZenon joins (~alzenon@5.139.232.120)
17:19:05 iqubic joins (~avi@2601:602:9502:c70:dd03:78c7:a43f:a269)
17:19:11 <trev> ski, oh then i have no idea why it wasn't working with foldr
17:19:32 <ski> ?
17:19:37 × coot quits (~coot@89-69-206-216.dynamic.chello.pl) (Quit: coot)
17:20:52 <trev> ski: it just doesn't work correctly with fold_right in OCaml. No idea why right now
17:21:29 <ski> you mean you don't get the right result ?
17:21:53 <trev> yep
17:22:52 × Square2 quits (~Square4@user/square) (Ping timeout: 246 seconds)
17:23:00 <ski> hm, i don't see why it shouldn't
17:23:11 <ski> val fold_right : ('a -> 'b -> 'b) -> 'a list -> 'b -> 'b
17:23:45 <ski> argument ordering is slightly different, but shouldn't be a problem. it's also not incremental, but that shouldn't be needed here, afaiui
17:25:15 <trev> i'll put the two side by side in a paste
17:26:05 <trev> https://paste.tomsmeding.com/rqjAOycf
17:26:36 <trev> perhaps i've been staring at it too long
17:26:46 × kuribas quits (~user@ip-188-118-57-242.reverse.destiny.be) (Remote host closed the connection)
17:27:06 <idgaen> in ocaml foldr can product stack overflow enough easily. But in haskell there is not this issue (there is no stack, for saying it merely).
17:27:28 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
17:27:42 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
17:28:26 <trev> i don't get a stack overflow, just the wrong answer
17:28:46 <idgaen> weird
17:28:57 albet70 joins (~xxx@2400:8902::f03c:92ff:fe60:98d8)
17:29:26 <idgaen> possibly an arithmetic overflow then
17:29:46 <trev> that is possible cause the output is a huge negative number
17:30:47 <glguy> trev: aren't the arguments to fold_right in the wrong order in your paste?
17:31:44 <trev> glguy: left and right have swapped args in ocaml
17:32:16 <glguy> well your code doesn't match what ski pasted
17:32:31 <glguy> if the type signature ski pasted is correct, then your code has the arguments in the wrong order
17:32:48 <trev> oh wow you're right
17:32:53 <idgaen> I'd rather like the haskell arguments order for fold… each time I tried to play with ocaml I was confused
17:33:15 <trev> that is super annoying!
17:33:28 <trev> now my |> won't work
17:33:46 <glguy> good, because that direction of composition is always so awkward
17:33:48 <glguy> :-p
17:33:53 <ncf> how does it typecheck if the arguments are swapped?
17:34:03 <trev> acc and [] are the same type
17:34:10 <trev> int list
17:34:13 <ski> idgaen : there is a stack, just not in quite the ordinary sense. also GHC will extend the stack on overflow, now, rather than crashing
17:34:22 × loonycyborg quits (loonycybor@wesnoth/developer/loonycyborg) (Remote host closed the connection)
17:34:42 <glguy> There goes the illusion of types helping with program correctness :-S
17:34:43 <idgaen> ski: ok, thanks you for this information.
17:34:48 <ncf> oh right, you're building a list
17:35:02 <ski> trev : no, `fold_left' is the same as in Haskell
17:35:08 <ski> val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
17:35:31 <ski> (and yea, i just copied these from `ocaml')
17:35:52 <trev> ski i meant in ocaml's fold_left and fold_right swap the two last args
17:36:04 <trev> and also the args of the accumulator :\
17:36:07 <ski> idgaen : part of the point of the OCaml ordering, is to be able to say `fold_right o fold_right' or `fold_left o fold_left'
17:36:50 <ski> .. and SML has yet another ordering
17:36:56 <trev> what does the `o` mean ski?
17:37:12 <ski> function composition
17:37:26 <idgaen> ski: oh! It is for composition of function. I have never noticed
17:37:29 <ski> val foldr : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
17:37:32 <ski> val foldl : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
17:37:47 <ski> in SML, they preferred to keep the signatures of both exactly the same
17:37:55 <ski> (and uncurried the callback)
17:39:27 <ski> @type let foldl :: (s -> a -> s) -> s -> [a] -> s; foldl = Prelude.foldl in foldl . foldl
17:39:28 <lambdabot> (s -> a -> s) -> s -> [[a]] -> s
17:39:30 <ski> vs.
17:39:32 <ski> @type let foldr :: (a -> s -> s) -> s -> [a] -> s; foldr = Prelude.foldr in foldr . flip . foldr
17:39:33 <lambdabot> (a -> s -> s) -> s -> [[a]] -> s
17:39:42 <ski> that `flip' isn't needed in the OCaml version
17:39:56 <EvanR> last night I finally realized this "foldr" solution, and it's very fast and sensible. But now I'm wondering if foldl' would be even faster xD
17:40:34 <EvanR> also discussing the detailed solution the day of?
17:41:11 <ski> @type map . map
17:41:16 <lambdabot> (a -> b) -> [[a]] -> [[b]]
17:41:18 <ski> @type zipWith . zipWith
17:41:19 <idgaen> I used to use foldl' unless if lazyness or I build a list. In these last case foldr is better, I feel.
17:41:19 <lambdabot> (a -> b -> c) -> [[a]] -> [[b]] -> [[c]]
17:41:38 <EvanR> you can build a list backwards with foldl' very fast xD
17:42:00 <EvanR> i.e. what is required here
17:42:31 <idgaen> depends I you want keep the original order.
17:42:34 <ski> > foldl' (flip (:)) [] [0 ..] -- very fast infinite list building
17:42:40 <lambdabot> mueval-core: Time limit exceeded
17:43:00 <EvanR> laziness doesn't help with memory usage in this one
17:44:17 <EvanR> if you build list L backwards, it is in the right order still
17:44:21 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
17:44:31 <EvanR> i.e. start with the last element and prepend second to last element, etc
17:44:53 econo_ joins (uid147250@id-147250.tinside.irccloud.com)
17:47:48 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
17:48:17 tzh joins (~tzh@c-71-193-181-0.hsd1.or.comcast.net)
17:49:11 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
17:52:34 × CrunchyFlakes quits (~CrunchyFl@ip92348280.dynamic.kabel-deutschland.de) (Ping timeout: 276 seconds)
17:52:42 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
17:53:42 CrunchyFlakes joins (~CrunchyFl@ip92348280.dynamic.kabel-deutschland.de)
17:53:44 <EvanR> I just tried and it has no effect on runtime, maybe because everything else in the program is much slower, maybe because optimizer thinks they are equivalent
17:53:53 <EvanR> or both
17:54:35 Square joins (~Square@user/square)
17:54:37 <EvanR> but the foldl' version has simpler code, and I'd like to ask for input on beautifying my foldr code, but only if the spoiler period is over
17:54:48 × pavonia quits (~user@user/siracusa) (Quit: Bye!)
17:55:25 <EvanR> or by the time I get back from the DMV I'll have figured it out xD
17:56:08 <trev> my bad for bringing up the solution so early. it was eating at me
17:57:27 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
18:00:01 <idgaen> trev: I'm happy, I joined too lately for looking at your solution ;)
18:02:07 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
18:02:08 × euleritian quits (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) (Read error: Connection reset by peer)
18:02:08 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
18:02:56 × adium quits (adium@user/adium) (Excess Flood)
18:03:01 euleritian joins (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de)
18:04:59 adium joins (adium@user/adium)
18:09:32 akegalj joins (~akegalj@141-136-219-144.dsl.iskon.hr)
18:10:42 AlexNoo_ joins (~AlexNoo@5.139.232.120)
18:12:26 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
18:13:14 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
18:13:58 × AlexNoo quits (~AlexNoo@5.139.232.120) (Ping timeout: 255 seconds)
18:22:22 × euleritian quits (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) (Read error: Connection reset by peer)
18:22:31 euleritian joins (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de)
18:23:10 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
18:23:25 edr joins (~edr@user/edr)
18:27:39 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
18:28:44 peterbecich joins (~Thunderbi@047-229-123-186.res.spectrum.com)
18:36:14 × bwe quits (~bwe@2a01:4f8:1c1c:4878::2) (Quit: Lost terminal)
18:42:26 × euleritian quits (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) (Ping timeout: 245 seconds)
18:43:05 euleritian joins (~euleritia@dynamic-002-247-248-235.2.247.pool.telefonica.de)
18:43:34 × peterbecich quits (~Thunderbi@047-229-123-186.res.spectrum.com) (Ping timeout: 256 seconds)
18:50:10 nate4 joins (~nate@c-98-45-158-125.hsd1.ca.comcast.net)
18:50:19 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
18:51:22 × gentauro quits (~gentauro@user/gentauro) (Read error: Connection reset by peer)
18:52:58 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
18:54:55 × nate4 quits (~nate@c-98-45-158-125.hsd1.ca.comcast.net) (Ping timeout: 255 seconds)
18:56:40 gentauro joins (~gentauro@user/gentauro)
18:56:42 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
18:57:41 × akegalj quits (~akegalj@141-136-219-144.dsl.iskon.hr) (Ping timeout: 252 seconds)
18:59:14 AlexNoo_ is now known as AlexNoo
19:00:40 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
19:01:06 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
19:02:11 <EvanR> also if you're ok with foldr it seems this becomes one of the situations you can count on one hand where foldl not-prime would at least not be wrong
19:07:49 × rosco quits (~rosco@175.136.158.171) (Quit: Lost terminal)
19:11:04 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
19:11:06 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
19:14:45 × chele quits (~chele@user/chele) (Remote host closed the connection)
19:16:15 <monochrom> Usually, if you use foldl to build a list and then reverse it, you can use foldr to build a diff list instead.
19:16:52 <EvanR> no need to reverse in this case
19:17:33 × euandreh quits (~Thunderbi@189.6.18.26) (Remote host closed the connection)
19:17:37 <glguy> EvanR: if you're worried about spoilers just put the code in a pastebin instead of directly into channel
19:17:45 <EvanR> oh
19:18:12 <EvanR> also I tried a 3rd way and the runtime is still not affected
19:18:16 <monochrom> Yeah if you say "this paste contains spoilers" then people can choose to not click.
19:19:17 euandreh joins (~Thunderbi@189.6.18.26)
19:19:44 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:d9f3:ec2f:a760:e0fe) (Remote host closed the connection)
19:20:45 AlexNoo_ joins (~AlexNoo@5.139.232.120)
19:20:59 acidjnk_new joins (~acidjnk@p200300d6e72b930718d4047c6b088385.dip0.t-ipconnect.de)
19:21:17 Incredia_ joins (~Incredia@176.254.244.83)
19:21:41 × alp_ quits (~alp@2001:861:e3d6:8f80:c0c9:d001:c090:e9f8) (Ping timeout: 240 seconds)
19:22:11 drewjose6 joins (~drewjose@129.154.40.88)
19:22:33 g__ joins (g@libera/staff/glguy)
19:22:34 WzC joins (~Frank@77-162-168-71.fixed.kpn.net)
19:22:52 mniip_ joins (mniip@libera/staff/mniip)
19:22:56 × g quits (g@libera/staff/glguy) (Killed (cadmium.libera.chat (Nickname regained by services)))
19:22:56 g__ is now known as g
19:22:57 caasih_ joins (sid13241@id-13241.ilkley.irccloud.com)
19:22:57 yandere_ joins (sid467876@id-467876.ilkley.irccloud.com)
19:22:57 lally_ joins (sid388228@id-388228.uxbridge.irccloud.com)
19:22:58 totbwf_ joins (sid402332@id-402332.uxbridge.irccloud.com)
19:23:00 _0xa_ joins (~user@2001:19f0:5001:2ba8:5400:1ff:feda:88fc)
19:23:01 meooow_ joins (~meooow@2400:6180:100:d0::ad9:e001)
19:23:02 dsal_ joins (sid13060@id-13060.lymington.irccloud.com)
19:23:04 Taneb0 joins (~Taneb@runciman.hacksoc.org)
19:23:04 jackdk_ joins (sid373013@cssa/jackdk)
19:23:05 hovsater_ joins (sid499516@id-499516.lymington.irccloud.com)
19:23:07 smalltalkman_ joins (uid545680@id-545680.hampstead.irccloud.com)
19:23:08 Fangs_ joins (sid141280@id-141280.hampstead.irccloud.com)
19:23:10 nurupo_ joins (~nurupo.ga@user/nurupo)
19:23:13 delyan__ joins (sid523379@id-523379.hampstead.irccloud.com)
19:23:14 dysfigured joins (~dfg@dfg.rocks)
19:23:14 kaskal- joins (~kaskal@2001:4bb8:2d2:5771:29a:c01c:fefc:78b5)
19:23:19 sa_ joins (sid1055@id-1055.tinside.irccloud.com)
19:23:20 jmtd joins (jon@dow.land)
19:23:23 bw____ joins (sid2730@id-2730.ilkley.irccloud.com)
19:23:24 urdh_ joins (~urdh@user/urdh)
19:23:38 innegatives_ joins (sid621315@id-621315.tinside.irccloud.com)
19:24:57 np joins (~nerdypepp@user/nerdypepper)
19:25:26 abrar_ joins (~abrar@pool-108-52-90-30.phlapa.fios.verizon.net)
19:25:33 farn_ joins (~farn@2a03:4000:7:3cd:d4ab:85ff:feeb:f505)
19:25:33 aosync_ joins (~alews@141.94.77.100)
19:25:36 ezzieygu1wuf joins (~Unknown@user/ezzieyguywuf)
19:25:37 shane_ joins (~shane@ana.rch.ist)
19:25:40 × Taneb quits (~Taneb@runciman.hacksoc.org) (Ping timeout: 252 seconds)
19:25:41 × yandere quits (sid467876@id-467876.ilkley.irccloud.com) (Ping timeout: 252 seconds)
19:25:41 × Jon quits (jon@dow.land) (Ping timeout: 252 seconds)
19:25:41 × smalltalkman quits (uid545680@id-545680.hampstead.irccloud.com) (Ping timeout: 252 seconds)
19:25:41 × jackdk quits (sid373013@cssa/jackdk) (Ping timeout: 252 seconds)
19:25:41 × totbwf quits (sid402332@id-402332.uxbridge.irccloud.com) (Ping timeout: 252 seconds)
19:25:41 × hovsater quits (sid499516@id-499516.lymington.irccloud.com) (Ping timeout: 252 seconds)
19:25:41 × bw___ quits (sid2730@id-2730.ilkley.irccloud.com) (Ping timeout: 252 seconds)
19:25:41 × meooow quits (~meooow@2400:6180:100:d0::ad9:e001) (Ping timeout: 252 seconds)
19:25:41 × lally quits (sid388228@id-388228.uxbridge.irccloud.com) (Ping timeout: 252 seconds)
19:25:41 × Incredia quits (~Incredia@176.254.244.83) (Ping timeout: 252 seconds)
19:25:41 × abrar quits (~abrar@pool-108-52-90-30.phlapa.fios.verizon.net) (Ping timeout: 252 seconds)
19:25:41 × nerdypepper quits (~nerdypepp@user/nerdypepper) (Ping timeout: 252 seconds)
19:25:41 × farn quits (~farn@2a03:4000:7:3cd:d4ab:85ff:feeb:f505) (Ping timeout: 252 seconds)
19:25:41 × _0xa quits (~user@user/0xa/x-3134607) (Ping timeout: 252 seconds)
19:25:41 × delyan_ quits (sid523379@id-523379.hampstead.irccloud.com) (Ping timeout: 252 seconds)
19:25:42 × krj quits (~krjst@2604:a880:800:c1::16b:8001) (Ping timeout: 252 seconds)
19:25:42 × aosync quits (~alews@user/aws) (Ping timeout: 252 seconds)
19:25:42 × kaskal quits (~kaskal@89.144.222.250) (Ping timeout: 252 seconds)
19:25:42 × caasih quits (sid13241@id-13241.ilkley.irccloud.com) (Ping timeout: 252 seconds)
19:25:42 × hughjfchen quits (~hughjfche@vmi556545.contaboserver.net) (Ping timeout: 252 seconds)
19:25:42 × edr quits (~edr@user/edr) (Ping timeout: 252 seconds)
19:25:42 × AlexNoo quits (~AlexNoo@5.139.232.120) (Ping timeout: 252 seconds)
19:25:42 × infinity0 quits (~infinity0@pwned.gg) (Ping timeout: 252 seconds)
19:25:42 × acidjnk quits (~acidjnk@p200300d6e72b9356246dd2d07051f792.dip0.t-ipconnect.de) (Ping timeout: 252 seconds)
19:25:42 × Lycurgus quits (~georg@user/Lycurgus) (Ping timeout: 252 seconds)
19:25:42 × urdh quits (~urdh@user/urdh) (Ping timeout: 252 seconds)
19:25:42 × cln_ quits (cln@wtf.cx) (Ping timeout: 252 seconds)
19:25:43 × Fangs quits (sid141280@id-141280.hampstead.irccloud.com) (Ping timeout: 252 seconds)
19:25:43 × dsal quits (sid13060@id-13060.lymington.irccloud.com) (Ping timeout: 252 seconds)
19:25:43 × ezzieyguywuf quits (~Unknown@user/ezzieyguywuf) (Ping timeout: 252 seconds)
19:25:43 × titibandit quits (~titibandi@user/titibandit) (Ping timeout: 252 seconds)
19:25:43 × nurupo quits (~nurupo.ga@user/nurupo) (Ping timeout: 252 seconds)
19:25:43 × ski quits (~ski@remote11.chalmers.se) (Ping timeout: 252 seconds)
19:25:43 × shane quits (~shane@ana.rch.ist) (Ping timeout: 252 seconds)
19:25:43 × yushyin quits (XznNkBgf65@karif.server-speed.net) (Ping timeout: 252 seconds)
19:25:43 × haveo quits (~weechat@pacamara.iuwt.fr) (Ping timeout: 252 seconds)
19:25:43 × innegatives quits (sid621315@id-621315.tinside.irccloud.com) (Ping timeout: 252 seconds)
19:25:44 × drewjose quits (~drewjose@129.154.40.88) (Ping timeout: 252 seconds)
19:25:44 × sa quits (sid1055@id-1055.tinside.irccloud.com) (Ping timeout: 252 seconds)
19:25:44 × Noinia quits (~Frank@77-162-168-71.fixed.kpn.net) (Ping timeout: 252 seconds)
19:25:44 × dfg quits (~dfg@user/dfg) (Ping timeout: 252 seconds)
19:25:44 × dhil quits (~dhil@2001:8e0:2014:3100:5872:f936:bc7a:ceb8) (Ping timeout: 252 seconds)
19:25:44 lally_ is now known as lally
19:25:44 jackdk_ is now known as jackdk
19:25:45 smalltalkman_ is now known as smalltalkman
19:25:45 caasih_ is now known as caasih
19:25:45 hovsater_ is now known as hovsater
19:25:45 Fangs_ is now known as Fangs
19:25:45 totbwf_ is now known as totbwf
19:25:45 yandere_ is now known as yandere
19:25:45 delyan__ is now known as delyan_
19:25:45 urdh_ is now known as urdh
19:25:45 drewjose6 is now known as drewjose
19:25:45 dsal_ is now known as dsal
19:25:46 hughjfch1 joins (~hughjfche@vmi556545.contaboserver.net)
19:25:49 sa_ is now known as sa
19:25:50 ski joins (~ski@remote11.chalmers.se)
19:25:58 Lycurgus joins (~georg@li1192-118.members.linode.com)
19:25:58 × Lycurgus quits (~georg@li1192-118.members.linode.com) (Changing host)
19:25:58 Lycurgus joins (~georg@user/Lycurgus)
19:25:59 haveo joins (~weechat@pacamara.iuwt.fr)
19:26:01 cln_ joins (cln@wtf.cx)
19:26:10 titibandit joins (~titibandi@user/titibandit)
19:26:18 krasjet joins (~krjst@2604:a880:800:c1::16b:8001)
19:26:32 × mniip quits (mniip@libera/staff/mniip) (Read error: Connection reset by peer)
19:27:00 dhil joins (~dhil@2001:8e0:2014:3100:5872:f936:bc7a:ceb8)
19:27:16 nurupo_ is now known as nurupo
19:27:32 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
19:28:32 infinity0 joins (~infinity0@pwned.gg)
19:29:11 mc47 joins (~mc47@xmonad/TheMC47)
19:30:41 × cfricke quits (~cfricke@user/cfricke) (Quit: WeeChat 4.0.5)
19:31:20 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
19:32:09 coot joins (~coot@89-69-206-216.dynamic.chello.pl)
19:32:34 × rito quits (~ritog@45.112.243.193) (Quit: Leaving)
19:32:52 ritog joins (~ritog@45.112.243.193)
19:34:43 rito joins (~ritog@45.112.243.193)
19:35:15 JeremyB99 joins (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c)
19:35:34 × ritog quits (~ritog@45.112.243.193) (Client Quit)
19:35:34 × rito quits (~ritog@45.112.243.193) (Remote host closed the connection)
19:35:36 × JeremyB99 quits (~JeremyB99@2607:fb90:8de2:efba:5583:eaba:6418:d88c) (Read error: Connection reset by peer)
19:37:13 × coot quits (~coot@89-69-206-216.dynamic.chello.pl) (Quit: coot)
19:37:27 coot joins (~coot@89-69-206-216.dynamic.chello.pl)
19:37:33 yushyin joins (sJ30bcriGA@mail.karif.server-speed.net)
19:39:46 misterfish joins (~misterfis@84-53-85-146.bbserv.nl)
19:40:28 × oo_miguel quits (~Thunderbi@78-11-179-96.static.ip.netia.com.pl) (Ping timeout: 276 seconds)
19:41:03 bwe joins (~bwe@2a01:4f8:1c1c:4878::2)
19:42:12 bwe_ joins (~bwe@2a01:4f8:1c1c:4878::2)
19:42:59 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
19:45:30 JeremyB99 joins (~JeremyB99@208.64.173.6)
19:47:01 × bwe_ quits (~bwe@2a01:4f8:1c1c:4878::2) (Client Quit)
19:47:06 alp_ joins (~alp@2001:861:e3d6:8f80:9ca3:38ae:c1a8:63c1)
19:47:15 × bwe quits (~bwe@2a01:4f8:1c1c:4878::2) (Remote host closed the connection)
19:47:32 bwe joins (~bwe@2a01:4f8:1c1c:4878::2)
19:47:59 × bwe quits (~bwe@2a01:4f8:1c1c:4878::2) (Client Quit)
19:49:06 bwe joins (~bwe@2a01:4f8:1c1c:4878::2)
19:49:31 × bwe quits (~bwe@2a01:4f8:1c1c:4878::2) (Client Quit)
19:50:40 bwe joins (~bwe@2a01:4f8:1c1c:4878::2)
19:52:26 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
19:53:37 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:97d:c646:7189:b78d)
19:56:05 × dcoutts_ quits (~duncan@cpc69402-oxfd27-2-0-cust903.4-3.cable.virginm.net) (Ping timeout: 252 seconds)
19:56:46 Feuermagier_ joins (~Feuermagi@user/feuermagier)
19:56:47 Feuermagier is now known as Guest6842
19:56:47 × Guest6842 quits (~Feuermagi@user/feuermagier) (Killed (tungsten.libera.chat (Nickname regained by services)))
19:56:47 Feuermagier_ is now known as Feuermagier
19:57:42 alexherbo2 joins (~alexherbo@2a02-8440-3341-75a8-58d4-3b45-b569-2dca.rev.sfr.net)
20:01:16 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:97d:c646:7189:b78d) (Remote host closed the connection)
20:01:29 × bwe quits (~bwe@2a01:4f8:1c1c:4878::2) (Quit: Lost terminal)
20:01:43 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:97d:c646:7189:b78d)
20:02:04 bwe joins (~bwe@2a01:4f8:1c1c:4878::2)
20:03:51 wroathe joins (~wroathe@207-153-38-140.fttp.usinternet.com)
20:03:51 × wroathe quits (~wroathe@207-153-38-140.fttp.usinternet.com) (Changing host)
20:03:51 wroathe joins (~wroathe@user/wroathe)
20:07:54 AlexNoo_ is now known as AlexNoo
20:11:51 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:97d:c646:7189:b78d) (Remote host closed the connection)
20:12:32 × coot quits (~coot@89-69-206-216.dynamic.chello.pl) (Quit: coot)
20:12:46 coot joins (~coot@89-69-206-216.dynamic.chello.pl)
20:16:14 × bwe quits (~bwe@2a01:4f8:1c1c:4878::2) (Quit: Lost terminal)
20:17:54 bwe joins (~bwe@2a01:4f8:1c1c:4878::2)
20:18:29 × bwe quits (~bwe@2a01:4f8:1c1c:4878::2) (Remote host closed the connection)
20:18:48 bwe joins (~bwe@2a01:4f8:1c1c:4878::2)
20:19:36 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:97d:c646:7189:b78d)
20:21:59 Taneb0 is now known as Taneb
20:25:52 kassouni joins (~textual@2601:646:401:6c30:5dd8:64ca:fd4d:e39b)
20:26:00 × trev quits (~trev@user/trev) (Quit: trev)
20:27:40 × wroathe quits (~wroathe@user/wroathe) (Ping timeout: 246 seconds)
20:29:48 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:97d:c646:7189:b78d) (Remote host closed the connection)
20:32:52 × coot quits (~coot@89-69-206-216.dynamic.chello.pl) (Quit: coot)
20:33:07 coot joins (~coot@89-69-206-216.dynamic.chello.pl)
20:37:29 × opus quits (~nil@user/opus) (Quit: bye)
20:37:29 × pedant quits (~who@user/pedant) (Quit: bye)
20:37:30 × anderson quits (~anderson@user/anderson) (Quit: bye)
20:41:16 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:97d:c646:7189:b78d)
20:45:23 <zero> there has to be a more elegant way of writing `req_msg <$> (decodeStrict =<< req)`
20:45:55 <Rembane> zero: req_msg . decodeStrict =<< req -- IIRC
20:46:14 <dminuoso_> That doesnt look right.
20:46:17 <shapr> @pl req_msg <$> (decodeStrict =<< req)
20:46:17 <lambdabot> req_msg <$> (decodeStrict =<< req)
20:46:22 <shapr> oh well, worth trying
20:46:26 <dminuoso_> zero: You can drop the parenthesis.
20:46:33 <Rembane> dminuoso_: I had to write it to realize it. :/
20:46:45 <dminuoso_> zero: Even ignoring precedence! No matter how you associate that <$>, it will be the same.
20:46:52 <dminuoso_> By law.
20:46:56 <Rembane> zero: Just out of curiousity, what's the type of decodeStrict?
20:47:30 cimento joins (CO2@gateway/vpn/protonvpn/cimento)
20:47:31 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:97d:c646:7189:b78d) (Remote host closed the connection)
20:47:40 <zero> i thought so too. but i get an error
20:47:47 <Rembane> What's the error?
20:47:57 <zero> decodeStrict :: forall a. FromJSON a => ByteString -> Maybe a
20:48:39 <zero> Couldn't match type ‘Text’ with ‘Maybe Text’Expected: ByteString -> Maybe Text Actual: ByteString -> Text
20:48:45 <zero> without the parenthesis
20:50:02 <zero> Couldn't match type ‘Maybe a0’ with ‘Req’Expected: ByteString -> Req Actual: ByteString -> Maybe a0In the second argument of ‘(.)’, namely ‘decodeStrict’In the first argument of ‘(=<<)’, namely ‘req_msg . decodeStrict’
20:50:06 <zero> with the .
20:50:42 <Rembane> I was super wrong about the dot, I'm sorry.
20:50:54 <zero> Rembane: i did the same mistake
20:51:22 zetef joins (~quassel@95.77.17.251)
20:51:23 <Rembane> zero: It looks nice, but doesn't work. :)
20:51:52 <zero> my brain tells me to write it another way
20:54:11 <Rembane> zero: You could use do-notation if that makes your brain happier.
20:54:50 <dminuoso_> zero: Depending on surrounding code, <&> could help
20:54:53 × alp_ quits (~alp@2001:861:e3d6:8f80:9ca3:38ae:c1a8:63c1) (Remote host closed the connection)
20:55:10 alp_ joins (~alp@2001:861:e3d6:8f80:fcbc:9c69:6404:51f0)
20:55:59 <dminuoso_> zero: Or making a decodeReq :: (Req -> a) -> Inp -> Decode a type of function
20:56:05 <dminuoso_> Such that you can write `decodeReq req_msg =<< req`
20:58:09 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
20:59:06 dcoutts_ joins (~duncan@cpc69402-oxfd27-2-0-cust903.4-3.cable.virginm.net)
21:02:11 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
21:02:30 <Hecate> win la
21:02:32 <Hecate> (woops)
21:02:37 × zetef quits (~quassel@95.77.17.251) (Ping timeout: 255 seconds)
21:03:02 zetef joins (~quassel@5.2.182.98)
21:03:08 not_reserved joins (~not_reser@185.195.59.27)
21:04:14 × dhil quits (~dhil@2001:8e0:2014:3100:5872:f936:bc7a:ceb8) (Ping timeout: 260 seconds)
21:11:16 × _ht quits (~Thunderbi@28-52-174-82.ftth.glasoperator.nl) (Remote host closed the connection)
21:17:24 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
21:17:46 × sord937 quits (~sord937@gateway/tor-sasl/sord937) (Quit: sord937)
21:21:13 × alp_ quits (~alp@2001:861:e3d6:8f80:fcbc:9c69:6404:51f0) (Ping timeout: 246 seconds)
21:21:23 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:97d:c646:7189:b78d)
21:23:20 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
21:24:50 akegalj joins (~akegalj@141-136-219-144.dsl.iskon.hr)
21:25:38 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:97d:c646:7189:b78d) (Ping timeout: 252 seconds)
21:26:12 × kassouni quits (~textual@2601:646:401:6c30:5dd8:64ca:fd4d:e39b) (Ping timeout: 256 seconds)
21:27:46 × akegalj quits (~akegalj@141-136-219-144.dsl.iskon.hr) (Client Quit)
21:28:01 × coot quits (~coot@89-69-206-216.dynamic.chello.pl) (Quit: coot)
21:30:32 × takuan quits (~takuan@178-116-218-225.access.telenet.be) (Remote host closed the connection)
21:38:07 × mobivme quits (~mobivme@112.201.111.217) (Excess Flood)
21:40:33 mobivme joins (~mobivme@112.201.111.217)
21:45:16 zzz joins (~z@user/zero)
21:48:41 × zero quits (~z@user/zero) (Ping timeout: 245 seconds)
21:48:41 zzz is now known as zero
21:51:04 alp_ joins (~alp@2001:861:e3d6:8f80:2823:fd6b:81cc:5297)
21:51:28 Square2 joins (~Square4@user/square)
21:53:20 <darkling> ROFL @ Venn diagrams.
21:53:30 <darkling> Err. -ECHANNEL.
21:54:21 × Square quits (~Square@user/square) (Ping timeout: 252 seconds)
21:55:27 × misterfish quits (~misterfis@84-53-85-146.bbserv.nl) (Ping timeout: 260 seconds)
22:00:57 fendor joins (~fendor@2a02:8388:1605:d100:267b:1353:13d7:4f0c)
22:09:26 × dcoutts_ quits (~duncan@cpc69402-oxfd27-2-0-cust903.4-3.cable.virginm.net) (Remote host closed the connection)
22:09:39 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:97d:c646:7189:b78d)
22:09:44 dcoutts_ joins (~duncan@cpc69402-oxfd27-2-0-cust903.4-3.cable.virginm.net)
22:11:49 × mc47 quits (~mc47@xmonad/TheMC47) (Remote host closed the connection)
22:11:57 <monochrom> I love Venn diagrams!
22:14:02 × robobub quits (uid248673@id-248673.uxbridge.irccloud.com) (Quit: Connection closed for inactivity)
22:14:47 <glguy> If I do part 2 as a list of partial sums I get: asPart2' = head . foldr (\wins xs -> 1 + (2 * head xs - xs !! wins) : xs) [0]
22:18:25 × chomwitt quits (~chomwitt@2a02:587:7a09:c300:1ac0:4dff:fedb:a3f1) (Ping timeout: 256 seconds)
22:19:33 × euandreh quits (~Thunderbi@189.6.18.26) (Ping timeout: 256 seconds)
22:26:10 euandreh joins (~Thunderbi@189.6.18.26)
22:27:52 <glguy> I should put that in my c++ solution where the indexing can be efficient
22:28:08 <monochrom> :)
22:29:15 <int-e> Hmm... 1 + (head xs - xs !! wins) + head xs ...okay, yeah, that looks correct :P
22:30:39 × euandreh quits (~Thunderbi@189.6.18.26) (Ping timeout: 252 seconds)
22:32:24 × fendor quits (~fendor@2a02:8388:1605:d100:267b:1353:13d7:4f0c) (Remote host closed the connection)
22:32:28 ski Euler's some diagrams
22:33:42 euandreh joins (~Thunderbi@189.6.18.26)
22:41:05 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
22:43:14 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
22:44:31 <iqubic> I love Euler Diagrams.
22:51:42 nate4 joins (~nate@c-98-45-158-125.hsd1.ca.comcast.net)
22:55:25 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
22:56:46 × nate4 quits (~nate@c-98-45-158-125.hsd1.ca.comcast.net) (Ping timeout: 276 seconds)
22:59:58 × szkl quits (uid110435@id-110435.uxbridge.irccloud.com) (Quit: Connection closed for inactivity)
23:00:51 × euandreh quits (~Thunderbi@189.6.18.26) (Remote host closed the connection)
23:01:13 × mobivme quits (~mobivme@112.201.111.217) (Quit: ZNC 1.8.2+deb2build5 - https://znc.in)
23:02:04 mobivme joins (~mobivme@112.201.111.217)
23:02:08 × gmg quits (~user@user/gehmehgeh) (Quit: Leaving)
23:04:26 × euleritian quits (~euleritia@dynamic-002-247-248-235.2.247.pool.telefonica.de) (Read error: Connection reset by peer)
23:04:45 euleritian joins (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de)
23:06:45 × notzmv quits (~zmv@user/notzmv) (Ping timeout: 268 seconds)
23:07:04 × mobivme quits (~mobivme@112.201.111.217) (Quit: ZNC 1.8.2+deb2build5 - https://znc.in)
23:09:57 mobivme joins (~mobivme@112.201.111.217)
23:10:10 × zetef quits (~quassel@5.2.182.98) (Remote host closed the connection)
23:11:47 × Square2 quits (~Square4@user/square) (Ping timeout: 252 seconds)
23:20:22 notzmv joins (~zmv@user/notzmv)
23:25:19 × __monty__ quits (~toonn@user/toonn) (Quit: leaving)
23:28:47 pavonia joins (~user@user/siracusa)
23:30:01 Sgeo joins (~Sgeo@user/sgeo)
23:33:22 × euleritian quits (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) (Read error: Connection reset by peer)
23:33:39 × acidjnk_new quits (~acidjnk@p200300d6e72b930718d4047c6b088385.dip0.t-ipconnect.de) (Ping timeout: 256 seconds)
23:33:56 euleritian joins (~euleritia@77.22.252.56)
23:38:05 × waleee quits (~waleee@h-176-10-144-38.NA.cust.bahnhof.se) (Ping timeout: 240 seconds)
23:52:47 × tomboy64 quits (~tomboy64@user/tomboy64) (Ping timeout: 264 seconds)

All times are in UTC on 2023-12-04.