2026/05/20

Newest at the top

2026-05-20 13:09:29 +0000nhar(~noah@76.33.110.8) (Ping timeout: 245 seconds)
2026-05-20 13:05:06 +0000nhar(~noah@76.33.110.8)
2026-05-20 13:00:46 +0000vanishingideal(~vanishing@user/vanishingideal) vanishingideal
2026-05-20 12:55:50 +0000merijn(~merijn@77.242.116.146) (Ping timeout: 255 seconds)
2026-05-20 12:53:09 +0000comerijn(~merijn@77.242.116.146) merijn
2026-05-20 12:51:38 +0000Deltaspace(~Deltaspac@178.252.83.109)
2026-05-20 12:51:16 +0000Deltaspace(~Deltaspac@178.252.83.109) (Read error: Connection reset by peer)
2026-05-20 12:51:11 +0000Deltaspace(~Deltaspac@178.252.83.109)
2026-05-20 12:50:49 +0000Deltaspace(~Deltaspac@178.252.83.109) (Read error: Connection reset by peer)
2026-05-20 12:42:49 +0000vanishingideal(~vanishing@user/vanishingideal) (Ping timeout: 272 seconds)
2026-05-20 12:37:00 +0000nhar(~noah@76.33.110.8) (Ping timeout: 268 seconds)
2026-05-20 12:36:25 +0000bitdex(~bitdex@gateway/tor-sasl/bitdex) (Client Quit)
2026-05-20 12:36:19 +0000bitdex(~bitdex@gateway/tor-sasl/bitdex) bitdex
2026-05-20 12:35:34 +0000Deltaspace(~Deltaspac@178.252.83.109)
2026-05-20 12:35:12 +0000Deltaspace(~Deltaspac@user/Deltaspace) (Remote host closed the connection)
2026-05-20 12:32:03 +0000nhar(~noah@76.33.110.8)
2026-05-20 12:00:02 +0000nhar(~noah@76.33.110.8) (Ping timeout: 255 seconds)
2026-05-20 11:59:51 +0000Pozyomka(~pyon@user/pyon) pyon
2026-05-20 11:59:32 +0000Pozyomka_(~pyon@user/pyon) (Quit: WeeChat 4.9.0)
2026-05-20 11:55:28 +0000nhar(~noah@76.33.110.8)
2026-05-20 11:51:47 +0000aka_dude(~aka_dude@192.71.166.120)
2026-05-20 11:49:02 +0000weary-traveler(~user@user/user363627) user363627
2026-05-20 11:49:00 +0000 <ski> (btw, it *is* also possible, in some ways, to learn more about the type, namely when using GADTs. doing a `case'-`of' analysis may then, in each appropriate branch, provide more information (at compilte-time) about abstract type parameters like `a' and `b')
2026-05-20 11:46:41 +0000 <ski> to pass around the (unchanging) type parameters `a' and `b' (so `loop' is monomorphic .. i also factored out the unchanging `f' while i was at it), while for the `nestedShows' you'd have something like `nestedShows @a @{show_a} (x:xs) = show @a @{show_a} : nestedShows @[a] @{mkShowList show_a} (...)')
2026-05-20 11:46:35 +0000 <ski> (in System F, when invoking a polymorphic operation, you are explicitly applying it to the types to use in place of the type parameters, in Haskell (with extensions) you can write this as e.g. `map @Int @Bool (> 4) [2,3,5,7]'. for monomorphic recursion, you can imagine `map' being defined as `map @a @b f = loop where loop :: [a] -> [b]; loop [ ] = []; loop (x:xs) = f x : loop xs', where you do *not* need
2026-05-20 11:43:17 +0000fgarcia(~lei@user/fgarcia) (Ping timeout: 272 seconds)
2026-05-20 11:42:52 +0000puke(~puke@user/puke) puke
2026-05-20 11:42:51 +0000 <mauke> you can tell map uses monomorphic recursion because it can be implemented in C++ templates :-)
2026-05-20 11:42:27 +0000puke(~puke@user/puke) (Read error: error:0A000139:SSL routines::record layer failure)
2026-05-20 11:40:54 +0000 <ski> otoh, `map' from above is *monomorphic* recursive (even though it's a polymorphic function), because, *within* the body of `map', we can think of it as being monomorphic, in the unknown types `a' and `b', recursive call calling on those *same* unknown types
2026-05-20 11:40:49 +0000confusedalex(~confuseda@user/confusedalex) confusedalex
2026-05-20 11:39:54 +0000 <ski> most interesting functions (iow recursive) on these, will need to be polymorphic recursive
2026-05-20 11:39:26 +0000 <ski> data PerfectlyBalancedBinaryTree a = Leaves a | Double (PerfectlyBalancedBinaryTree (a,a)) -- here we pass `(a,a)' in place of `a'
2026-05-20 11:38:47 +0000 <ski> data SwapList a b = Nil | Cons a (SwapList b a) -- `a' and `b' are swapped around, so it's not the same parameter pattern
2026-05-20 11:38:23 +0000 <lambdabot> "(((9,9),(9,9)),((9,9),(9,9)))"
2026-05-20 11:38:22 +0000 <mauke> > let { foo :: Show a => Int -> a -> String; foo n x | n > 0 = foo (n - 1) (x, x) | otherwise = show x } in foo 3 9
2026-05-20 11:38:19 +0000dolio(~dolio@130.44.140.168) dolio
2026-05-20 11:38:04 +0000 <lambdabot> "((9,9),(9,9))"
2026-05-20 11:38:03 +0000 <mauke> > let { foo :: Show a => Int -> a -> String; foo n x | n > 0 = foo (n - 1) (x, x) | otherwise = show x } in foo 2 9
2026-05-20 11:37:54 +0000 <ski> most more reasonable examples of polymorphic recursion involve "non-regular (recursive) data types", being data types whose recursion does not pass the same type parameters, e.g.
2026-05-20 11:36:57 +0000 <ski> iow, it must create a new dictionary, at run-time
2026-05-20 11:36:44 +0000 <ski> and, in this case, because we have a type class constraint, that means that when this is at run-time given an instance method dictionary for `Show Integer', it will then hand off (provide) a dictionary for `Show [Integer]' to the recursive call
2026-05-20 11:36:39 +0000vanishingideal(~vanishing@user/vanishingideal) vanishingideal
2026-05-20 11:36:37 +0000Moyst(~moyst@user/moyst) Moyst
2026-05-20 11:35:54 +0000 <ski> so, if in the top call, `a' will be `Integer', then in the recursive call, `a' will next be `[Integer]', then `[[Integer]]', and so on
2026-05-20 11:35:22 +0000 <ski> note that `xs' has type `[a]', but in the recursive call, `map (: []) xs)' has type `[[a]]'
2026-05-20 11:34:56 +0000 <ski> nestedShows (x:xs) = show x : nestedShows (map (: []) xs)
2026-05-20 11:34:37 +0000 <ski> nestedShows [ ] = []
2026-05-20 11:34:28 +0000 <ski> nestedShows :: Show a => [a] -> [String]
2026-05-20 11:33:56 +0000 <ski> here's a simple (and a bit silly) example of a polymorhic recursive function