2026/05/20

Newest at the top

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
2026-05-20 11:33:24 +0000 <ski> btw, polymorphic recursion is when a polymorphic operation is recursive, and at least some recursive invokation does *not* use the same unknown type variables as the current call
2026-05-20 11:32:42 +0000weary-traveler(~user@user/user363627) (Remote host closed the connection)
2026-05-20 11:32:04 +0000myxos(~myxos@67-1-178-42.tcso.qwest.net) myxokephale
2026-05-20 11:31:52 +0000fgarcia(~lei@user/fgarcia) fgarcia
2026-05-20 11:31:48 +0000weary-traveler(~user@user/user363627) user363627
2026-05-20 11:31:47 +0000synchromesh(~john@2406:5a00:247e:1500:cb6:d4f7:ed0e:5cdb) synchromesh
2026-05-20 11:31:38 +0000merijn(~merijn@77.242.116.146) merijn
2026-05-20 11:31:23 +0000Moyst(~moyst@user/moyst) (*.net *.split)
2026-05-20 11:31:23 +0000confusedalex(~confuseda@user/confusedalex) (*.net *.split)
2026-05-20 11:31:23 +0000myxos(~myxos@67-1-178-42.tcso.qwest.net) (*.net *.split)
2026-05-20 11:31:23 +0000synchromesh(~john@2406:5a00:247e:1500:cb6:d4f7:ed0e:5cdb) (*.net *.split)
2026-05-20 11:31:23 +0000dolio(~dolio@130.44.140.168) (*.net *.split)
2026-05-20 11:31:23 +0000chele(~chele@user/chele) (*.net *.split)
2026-05-20 11:31:23 +0000merijn(~merijn@77.242.116.146) (*.net *.split)
2026-05-20 11:31:23 +0000weary-traveler(~user@user/user363627) (*.net *.split)
2026-05-20 11:31:22 +0000fgarcia(~lei@user/fgarcia) (*.net *.split)
2026-05-20 11:31:22 +0000vanishingideal(~vanishing@user/vanishingideal) (*.net *.split)
2026-05-20 11:31:22 +0000nhar(~noah@76.33.110.8) (*.net *.split)
2026-05-20 11:31:21 +0000 <ski> e.g. the logic/functional programming language Mercury *does* pass around type infos, at run-time, to polymorphic operations, in this fashion
2026-05-20 11:31:12 +0000 <mesaoptimizer> I see