Home liberachat/#haskell: Logs Calendar

Logs: liberachat/#haskell

←Prev  Next→ 1,804,222 events total
2025-08-28 09:20:40 × arandombit quits (~arandombi@2603:7000:4600:ffbe:2ca2:a28f:2f37:22f6) (Changing host)
2025-08-28 09:20:40 arandombit joins (~arandombi@user/arandombit)
2025-08-28 09:21:28 × ljdarj quits (~Thunderbi@user/ljdarj) (Ping timeout: 248 seconds)
2025-08-28 09:21:36 merijn joins (~merijn@host-vr.cgnat-g.v4.dfn.nl)
2025-08-28 09:25:29 × arandombit quits (~arandombi@user/arandombit) (Ping timeout: 260 seconds)
2025-08-28 09:28:23 × merijn quits (~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-08-28 09:35:22 fp joins (~Thunderbi@wireless-86-50-141-108.open.aalto.fi)
2025-08-28 09:37:20 × lol_ quits (~lol@2603:3016:1e01:b960:14c0:7a30:3283:d6ed) (Ping timeout: 256 seconds)
2025-08-28 09:38:30 jcarpenter2 joins (~lol@96.78.87.197)
2025-08-28 09:39:39 merijn joins (~merijn@host-vr.cgnat-g.v4.dfn.nl)
2025-08-28 09:44:44 × merijn quits (~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-08-28 09:51:01 merijn joins (~merijn@host-vr.cgnat-g.v4.dfn.nl)
2025-08-28 09:55:35 arandombit joins (~arandombi@2603:7000:4600:ffbe:2ca2:a28f:2f37:22f6)
2025-08-28 09:55:35 × arandombit quits (~arandombi@2603:7000:4600:ffbe:2ca2:a28f:2f37:22f6) (Changing host)
2025-08-28 09:55:35 arandombit joins (~arandombi@user/arandombit)
2025-08-28 09:56:01 × merijn quits (~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 248 seconds)
2025-08-28 09:59:37 confusedalex joins (~alex@user/confusedalex)
2025-08-28 09:59:45 × arandombit quits (~arandombi@user/arandombit) (Ping timeout: 248 seconds)
2025-08-28 10:00:31 × humasect quits (~humasect@dyn-192-249-132-90.nexicom.net) (Remote host closed the connection)
2025-08-28 10:02:04 merijn joins (~merijn@host-vr.cgnat-g.v4.dfn.nl)
2025-08-28 10:02:06 <kuribas> I find OOP is just a more restricted version of using HOFs.
2025-08-28 10:02:48 <kuribas> I can make a superclass, and call virtual functions inside a method, but it's just the same as having a HOF function taking helper functions.
2025-08-28 10:06:17 <ski> a large part of it is programming with product types, with message-dispatching (as dual to sum types, with pattern-matching)
2025-08-28 10:06:26 Lycurgus joins (~juan@user/Lycurgus)
2025-08-28 10:06:54 × merijn quits (~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-08-28 10:07:51 <ski> (also the product types would typically be non-strict, leading to a closure-type implementation strategy (passing instance state / environment, to operations in vtable))
2025-08-28 10:10:00 <kuribas> The instance being the product type?
2025-08-28 10:10:30 × gmg quits (~user@user/gehmehgeh) (Quit: Leaving)
2025-08-28 10:11:39 <kuribas> It's true, I don't often see sum types in OOP, usualy they are implicit Unions.
2025-08-28 10:11:52 <kuribas> Using isinstance checks to distinguish between them.
2025-08-28 10:12:11 <kuribas> In Python I often use "Class1 | Class2" instead of a sum type.
2025-08-28 10:12:24 × h2t quits (~h2t@user/h2t) (Server closed connection)
2025-08-28 10:12:25 <kuribas> But for parsing it's sometimes useful to have discriminated unios.
2025-08-28 10:12:36 <kuribas> Then you get into the mess that is "pydantic".
2025-08-28 10:12:39 h2t joins (~h2t@user/h2t)
2025-08-28 10:13:42 <probie> Java these days has pattern matching and you can pretend you have sum types via sealed interfaces, if you want that :p
2025-08-28 10:14:10 <kuribas> like scala?
2025-08-28 10:14:23 <ski> consider `data Queue a = forall q. MkQ {stateQ :: q,enQ :: a -> q -> q,deQ :: q -> Maybe (q,a)}'
2025-08-28 10:14:41 <ski> you can then define wrappers, for invoking the methods
2025-08-28 10:15:37 × davean quits (~davean@davean.sciesnet.net) (Server closed connection)
2025-08-28 10:15:55 davean joins (~davean@davean.sciesnet.net)
2025-08-28 10:16:56 <ski> enqueue :: a -> Queue a -> Queue a
2025-08-28 10:17:03 <ski> enqueue x (MkQ q enQ deQ) = MkQ (enQ x q) enQ deQ
2025-08-28 10:17:05 <ski> and
2025-08-28 10:17:12 <ski> dequeue :: Queue a -> Maybe (Queue a,a)
2025-08-28 10:17:16 <ski> dequeue (MkQ q enQ deQ) = fmap (\(q,x) -> (MkQ q enQ deQ)) (deQ q)
2025-08-28 10:17:24 merijn joins (~merijn@host-vr.cgnat-g.v4.dfn.nl)
2025-08-28 10:17:33 <ski> and then you can define a class, like
2025-08-28 10:18:28 <kuribas> I have sort of the opposite problem, I am writing python, but I don't see a good reason to use a class (other than being more "pythonic"). It just seems less flexible.
2025-08-28 10:18:51 <ski> newListQueue :: Queue a
2025-08-28 10:19:04 <ski> newListQueue = MkQ [] enQ deQ
2025-08-28 10:19:08 <ski> where
2025-08-28 10:19:18 <ski> enQ x xs = xs ++ [x]
2025-08-28 10:19:28 <ski> deQ [ ] = Nothing
2025-08-28 10:19:41 <ski> deQ (x:xs) = Just (xs,x)
2025-08-28 10:19:58 <ski> and you can imagine more efficient implementations
2025-08-28 10:21:39 <ski> but also note that another way to define this type `Queue a' (where the above type is basically `exists q. (q,a -> q -> q,q -> Maybe (q,a))'), recursively, as `data Queue a = MkQ {enQ :: a -> Queue a,deQ :: Maybe (Queue a,a)}'
2025-08-28 10:22:25 <ski> (and then you're redefine the wrappers `enqueue' and `dequeue', for this representation)
2025-08-28 10:22:39 × merijn quits (~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-08-28 10:23:20 × xff0x quits (~xff0x@fsb6a9491c.tkyc517.ap.nuro.jp) (Ping timeout: 248 seconds)
2025-08-28 10:23:39 <ski> "Using isinstance checks to distinguish between them." -- which is kinda a kludge. using VisitorPattern (which is basically CPS, Church representation) is in some sense more principled
2025-08-28 10:24:37 <Franciman> what does principled mean?
2025-08-28 10:24:48 <probie> less ad-hoc
2025-08-28 10:25:59 <ski> if you don't have sealed, or something similar, there's no guarantee there won't be alternatives which are not covered
2025-08-28 10:28:43 <ski> btw, if you imagine `codata Queue a where Enqueue :: a -> Queue a -> Queue a; Dequeue :: Queue a', then one could define `newListQueue' as
2025-08-28 10:28:55 <ski> newListQueue :: Queue a
2025-08-28 10:29:03 <jreicher> The correspondence (if any) between OO and FP is further confused by the OO concept of a class conflating type and implementation.
2025-08-28 10:29:14 <ski> newListQueue = listQueue []
2025-08-28 10:29:21 <ski> where
2025-08-28 10:29:21 <jreicher> IMO you really gotta be careful with that in OO
2025-08-28 10:29:48 <ski> Enqueue x (listQueue xs) = listQueue (xs ++ [x])
2025-08-28 10:29:59 <ski> Dequeue (listQueue [ ]) = Nothing
2025-08-28 10:30:12 <ski> Dequeue (listQueue (x:xs)) = Just (listQueue xs,x)
2025-08-28 10:30:19 <ski> yes, jreicher
2025-08-28 10:31:33 <ski> (`Enqueue' and `Dequeue' here are methods, and `listQueue' is basically the class / class constructor. `listQueue xs' is being defined, in terms of how it responds to "messages", being the methods)
2025-08-28 10:31:58 <Franciman> i see OO as more of a ontological programme
2025-08-28 10:32:25 <Franciman> than an actual way of implementing stuff. So while i agree that all OO languages bottle the implementation side
2025-08-28 10:32:31 <Franciman> i wouldn't say FP is opposed to OO
2025-08-28 10:32:45 × takuan quits (~takuan@d8D86B9E9.access.telenet.be) (Remote host closed the connection)
2025-08-28 10:32:54 <ski> "OO" can mean many different things (as can "FP")
2025-08-28 10:33:08 merijn joins (~merijn@host-vr.cgnat-g.v4.dfn.nl)
2025-08-28 10:33:15 <Franciman> the issue with OO is probably how they put mutable state inside things
2025-08-28 10:33:19 <Franciman> in a non-controlled wy
2025-08-28 10:33:27 <ski> one useful way to contrast and compare, is to focus on the product vs. sum type distinction
2025-08-28 10:33:31 × lortabac quits (~lortabac@2a01:e0a:541:b8f0:55ab:e185:7f81:54a4) (Ping timeout: 248 seconds)
2025-08-28 10:33:31 <jreicher> My take is that FP is a high-level OO. It creates an manages the objects for you.
2025-08-28 10:33:45 <ski> you can do immutable OO
2025-08-28 10:33:57 <ski> (O'Haskell, later Timber, did this)
2025-08-28 10:34:10 <ski> oh, and OCaml supports it, as well
2025-08-28 10:34:16 <jreicher> I believe it's fairly well accepted that a closure is a prototypical immutable object, and a thunk is a prototypical mutable one.
2025-08-28 10:34:49 × jreicher quits (~user@user/jreicher) (Quit: In transit)
2025-08-28 10:35:18 <Lycurgus> my take is the model of computation, math in the case of FP, a variety of things for OOP, i once said pure phenomenollogy
2025-08-28 10:35:26 <ski> to me, "closure" is a particular implementation technique, used for delayed computation values (like first-class function values, "objects", continuations, promises, ..)
2025-08-28 10:35:53 <Lycurgus> communicating objects is downtown OOP
2025-08-28 10:35:56 <ski> "thunk" doesn't particularly convey any connotation of mutation, to me
2025-08-28 10:36:00 segfaultfizzbuzz joins (~segfaultf@23-93-74-222.fiber.dynamic.sonic.net)
2025-08-28 10:36:22 <ski> (it might imply mutation. but might also not imply it. depending on the particular case)
2025-08-28 10:36:37 __monty__ joins (~toonn@user/toonn)
2025-08-28 10:36:44 <Lycurgus> there's a legalistic 3 or 4 part qualifying list, encapsulation, inheritance, etc
2025-08-28 10:36:47 <ski> in Scheme, "thunk" often refers to any procedure taking no parameters

All times are in UTC.