Newest at the top
| 2026-01-18 00:36:01 +0100 | <EvanR> | :thonk: |
| 2026-01-18 00:35:47 +0100 | <haskellbridge> | <Man of Letters (Mikolaj)> anyway, sadly, while "let" can cache values, it can't cache the determination which dictionary to look up into and how to combine whatever has been obtained from the dictionary --- only the GHC magic can do that |
| 2026-01-18 00:35:44 +0100 | <EvanR> | for any of the types that have this api |
| 2026-01-18 00:35:43 +0100 | merijn | (~merijn@host-cl.cgnat-g.v4.dfn.nl) (Ping timeout: 240 seconds) |
| 2026-01-18 00:35:20 +0100 | <EvanR> | I was thinking that, for a given properly constructed implementation, you only do look ups into any implementation once per call to the API |
| 2026-01-18 00:34:55 +0100 | ethantwardy | (~user@user/ethantwardy) ethantwardy |
| 2026-01-18 00:34:33 +0100 | Inline | (~User@2001-4dd6-dd24-0-d5a6-802e-e6e6-ce59.ipv6dyn.netcologne.de) (Ping timeout: 256 seconds) |
| 2026-01-18 00:34:21 +0100 | <haskellbridge> | <Man of Letters (Mikolaj)> oh, yes, right |
| 2026-01-18 00:34:08 +0100 | <EvanR> | that was monochroms version |
| 2026-01-18 00:33:51 +0100 | <haskellbridge> | <Man of Letters (Mikolaj)> in my case, by specializing/monomorphising, I get rid of more than one dictionary lookup/passing |
| 2026-01-18 00:33:13 +0100 | <haskellbridge> | <Man of Letters (Mikolaj)> in your example, by the well placed "let", you avoid one of the two applications of subtraction |
| 2026-01-18 00:32:18 +0100 | <haskellbridge> | <Man of Letters (Mikolaj)> EvanR: right, so that's precisely the purpose of my crude hack with duplicating functions (or function calls) and so helping GHC specialize each call at a concrete known type; let me explain: |
| 2026-01-18 00:31:55 +0100 | ethantwardy | (~user@user/ethantwardy) (Quit: WeeChat 4.4.2) |
| 2026-01-18 00:30:32 +0100 | <haskellbridge> | <Man of Letters (Mikolaj)> ok, thank you, I will think about this |
| 2026-01-18 00:30:03 +0100 | <haskellbridge> | ... long message truncated: https://kf8nh.com/_heisenbridge/media/kf8nh.com/QetWxmpnbhshlldjxsPntKNj/OFJ7l1DSftE (5 lines) |
| 2026-01-18 00:30:03 +0100 | <haskellbridge> | <Man of Letters (Mikolaj)> e.g., I can't think how to get rid of the existentially bound types in the node |
| 2026-01-18 00:30:01 +0100 | <Leary> | The classic example is `data HList f xs where { Nil :: HList f '[]; Cons :: f x -> HList f xs -> HList f (x:xs) }`, but you can do similarly for arbitrary ASTs by duplicating some of their structure on the type level in the same way. |
| 2026-01-18 00:29:01 +0100 | merijn | (~merijn@host-cl.cgnat-g.v4.dfn.nl) merijn |
| 2026-01-18 00:28:07 +0100 | <haskellbridge> | <Man of Letters (Mikolaj)> some of the existential types arise naturally from AST GADTs (I have multiple interpreters of deeply embedded DLS in the implementation) |
| 2026-01-18 00:27:55 +0100 | troydm | (~troydm@user/troydm) troydm |
| 2026-01-18 00:25:34 +0100 | <haskellbridge> | <Man of Letters (Mikolaj)> Leary: where can I see an example of something like that? |
| 2026-01-18 00:24:53 +0100 | ethantwardy | (~user@user/ethantwardy) ethantwardy |
| 2026-01-18 00:24:38 +0100 | <Leary> | Man of Letters (Mikolaj): Re monomorphising, I see, that's a bit unfortunate. You can perhaps get rid of those existentials by using suitable heterogeneous types instead. |
| 2026-01-18 00:24:38 +0100 | <EvanR> | this might not apply exactly, I'm not sure I totally understand the situation |
| 2026-01-18 00:24:20 +0100 | <EvanR> | let f = makeF (+) |
| 2026-01-18 00:24:10 +0100 | <EvanR> | makeF add x = add (x - 1) (x + 1) |
| 2026-01-18 00:22:58 +0100 | <EvanR> | tying |
| 2026-01-18 00:22:54 +0100 | <EvanR> | as far as knot typing I don't know about this |
| 2026-01-18 00:22:50 +0100 | <monochrom> | Oh, like "f x = f (x - 1) + f (x - 1)" vs "f x = let y = f (x - 1) in y + y"? |
| 2026-01-18 00:22:27 +0100 | <EvanR> | dependency isn't dynamically changing* |
| 2026-01-18 00:21:38 +0100 | <EvanR> | this assumes the dependent implementation isn't dynamically changing for the same data structure |
| 2026-01-18 00:21:14 +0100 | <EvanR> | instead of every time it's accessed |
| 2026-01-18 00:21:01 +0100 | <EvanR> | if you're combining implementations in a way to implement another implementation, you do want to use prudent "let" bindings to make sure you only access the dependent implementation once |
| 2026-01-18 00:18:34 +0100 | <EvanR> | holy moly |
| 2026-01-18 00:18:24 +0100 | merijn | (~merijn@host-cl.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds) |
| 2026-01-18 00:18:13 +0100 | <haskellbridge> | <Man of Letters (Mikolaj)> but the nested array indexing code implements what should be in that dictionary --- I'd need a way to somehow boostrap this, recurse across a dictionary |
| 2026-01-18 00:17:26 +0100 | <haskellbridge> | <Man of Letters (Mikolaj)> if I understand your idea correctly, the nested array indexing code should instead take a dictionary that directly works on nested arrays, not vectors |
| 2026-01-18 00:16:51 +0100 | <haskellbridge> | <Man of Letters (Mikolaj)> so, the only argument against I can find is circularity: say, I'm implementing indexing in fancy nested arrays (which is called 12! times in the benchmark I'm working on), the code for the indexing takes a dictionary for storable vectors (the arrays are represented as tuples of such vectors) and it's terribly slow when it has to access the dictionary each time it's called |
| 2026-01-18 00:15:01 +0100 | ethantwardy | (~user@user/ethantwardy) (Client Quit) |
| 2026-01-18 00:14:14 +0100 | ethantwardy | (~user@user/ethantwardy) ethantwardy |
| 2026-01-18 00:13:13 +0100 | merijn | (~merijn@host-cl.cgnat-g.v4.dfn.nl) merijn |
| 2026-01-18 00:11:40 +0100 | target_i | (~target_i@user/target-i/x-6023099) (Quit: leaving) |
| 2026-01-18 00:09:58 +0100 | ethantwardy | (~user@user/ethantwardy) (Client Quit) |
| 2026-01-18 00:07:35 +0100 | ethantwardy | (~user@user/ethantwardy) ethantwardy |
| 2026-01-18 00:06:38 +0100 | <haskellbridge> | <Man of Letters (Mikolaj)> that makes sense; let me think why not |
| 2026-01-18 00:05:34 +0100 | <EvanR> | any time you pass around explicit dictionaries, can't it also be passing (perhaps hidden inside a data type) a record of things doing the implementation |
| 2026-01-18 00:05:18 +0100 | <haskellbridge> | <Man of Letters (Mikolaj)> because what I'm currently doing is seriously embarrassing |
| 2026-01-18 00:02:52 +0100 | <haskellbridge> | <Man of Letters (Mikolaj)> but if anybody has any other ideas how to avoid passing around explicit dictionaries but maintain the very abstract API, I'm all ears |
| 2026-01-18 00:02:38 +0100 | merijn | (~merijn@host-cl.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds) |
| 2026-01-18 00:02:06 +0100 | humasect | (~humasect@dyn-192-249-132-90.nexicom.net) (Quit: Leaving...) |