Newest at the top
2025-09-16 05:19:43 +0200 | merijn | (~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn |
2025-09-16 05:16:56 +0200 | <StatisticalIndep> | In any case, (mmapWithFilePtr "mm" ReadWrite Nothing $ \ (p, _) -> sequence_ $ zipWith (\ c i -> poke (plusPtr p i) c) "ME GO TOO FAR!" [0..]) works nicely enough. ;) (Yes, I know this will break with multi-byte chars.) |
2025-09-16 05:13:13 +0200 | <hololeap> | made me remember this: https://www.channable.com/tech/lessons-in-managing-haskell-memory |
2025-09-16 05:11:14 +0200 | aforemny_ | (~aforemny@i59F4C711.versanet.de) (Ping timeout: 256 seconds) |
2025-09-16 05:10:38 +0200 | aforemny | (~aforemny@2001:9e8:6cce:4800:55ab:c43e:17dc:ff6c) aforemny |
2025-09-16 05:08:40 +0200 | merijn | (~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 245 seconds) |
2025-09-16 05:08:33 +0200 | <geekosaur> | GC assumes pinned memory is an exception, not the rule |
2025-09-16 05:07:21 +0200 | <geekosaur> | we do actually have such a thing as pinned memory, but it's only applicable to ByteArray# and it's handled via an exception list (and I seem to recall hearing of programs that heavily use ByteStrings getting slow because the exception list isn't very efficient?) |
2025-09-16 05:05:50 +0200 | <StatisticalIndep> | geekosaur: Oh, I forgot about GC. Okay, that seals the deal. All those features are more valuable than having that bit of non-marshalled mapping elegance. |
2025-09-16 05:04:31 +0200 | <StatisticalIndep> | hololeap: It also makes sense from a standpoint of variables being constants in Haskell, and there hence being no such thing as an “insertion”. (The tree has to be reconstructed from the zipper instead.) |
2025-09-16 05:04:28 +0200 | <geekosaur> | and probably make it a lot more expensive, if it has to check if every pointer actually lives in the heap or not |
2025-09-16 05:04:25 +0200 | arandombit | (~arandombi@user/arandombit) arandombit |
2025-09-16 05:04:25 +0200 | arandombit | (~arandombi@2603:7000:4600:ffbe:21ee:ceac:8353:7a15) (Changing host) |
2025-09-16 05:04:25 +0200 | arandombit | (~arandombi@2603:7000:4600:ffbe:21ee:ceac:8353:7a15) |
2025-09-16 05:04:08 +0200 | <geekosaur> | hypothetically could be done. would really complicate GC, though |
2025-09-16 05:03:56 +0200 | merijn | (~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn |
2025-09-16 05:03:14 +0200 | <StatisticalIndep> | I just wish I could tell Haskell: to point every pointer to an Int, in e.g. a fixey list of Ints, to a pointer location in a block of mmapped data that contains unboxed ints in exactly the same format as GHC expects them. |
2025-09-16 05:01:51 +0200 | <hololeap> | makes sense that Map is a binary tree, given the (Ord k) constraint on most operations |
2025-09-16 05:01:15 +0200 | <StatisticalIndep> | Yep. |
2025-09-16 05:00:55 +0200 | <geekosaur> | which is another reason you must marshal/unmarshal, because it's asking far too much for other languages to have to figure out how Map is a size-balanced binary tree or Seq is a fingertree, etc. |
2025-09-16 04:59:48 +0200 | <StatisticalIndep> | Ah, yes, i remembered something like that! |
2025-09-16 04:59:35 +0200 | <geekosaur> | Maps are actually more complex than that: "The implementation of Map is based on size balanced binary trees (or trees of bounded balance)" (from the documentation) |
2025-09-16 04:58:50 +0200 | StatisticalIndep | (~Statistic@2a02:3035:666:b7d5:4e00:1517:7b0c:d0aa) |
2025-09-16 04:58:38 +0200 | StatisticalIndep | (~Statistic@2a02:3035:666:b7d5:4e00:1517:7b0c:d0aa) (Quit: Client closed) |
2025-09-16 04:58:26 +0200 | <StatisticalIndep> | I probably expect a Map to internally be stored as an array of pointers, with pointers to keys and to values being interleaved? Or something a bit smarter with fewer pointers. ;) |
2025-09-16 04:56:28 +0200 | <geekosaur> | (if you don't have optimization enabled, even the strict values have them, but optimization unboxes whenever possible) |
2025-09-16 04:55:56 +0200 | <geekosaur> | right, and all those pointers introduce places where a value could be computed lazily |
2025-09-16 04:55:22 +0200 | arandombit | (~arandombi@user/arandombit) (Ping timeout: 256 seconds) |
2025-09-16 04:54:59 +0200 | <geekosaur> | *Data.Map.Map |
2025-09-16 04:54:58 +0200 | <StatisticalIndep> | I guess my mindset came from having seen diagrams of how GHC stores data in memory. Like how lists are linked lists of boxed values. Lots more pointers than one would think. |
2025-09-16 04:54:39 +0200 | <geekosaur> | they are… until ADTs get involved. (what representation do you expect a Data.Map to have?) |
2025-09-16 04:53:58 +0200 | <StatisticalIndep> | OK, true. |
2025-09-16 04:53:42 +0200 | <geekosaur> | actually I don't see how "doesn't have type information" is related. it's not like C values do |
2025-09-16 04:53:31 +0200 | <StatisticalIndep> | Internally though, the fully evaluated values are of course just normal pointers and words and such, right? Just boxed in boxed boxes that are boxed more than the boss on boxyourboss.com was. ;) |
2025-09-16 04:52:47 +0200 | merijn | (~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 265 seconds) |
2025-09-16 04:52:09 +0200 | <StatisticalIndep> | And after all, those are all things I came to Haskell for, because I liked them. So now I have to live with it.:D |
2025-09-16 04:52:01 +0200 | <geekosaur> | which also requires that everything live in Haskell's heap and non-Haskell code not have access to that heap |
2025-09-16 04:51:43 +0200 | <StatisticalIndep> | Yup. |
2025-09-16 04:51:38 +0200 | <StatisticalIndep> | geekosaur: That was what I needed to hear btw: Marshalling is needed in _any_ case. Because the values don’t have type info attached to them and it’s not that simple anyway within Haskell. :) |
2025-09-16 04:51:37 +0200 | <geekosaur> | not only that, but Haskell's implementation of types allows for laziness in the form of thunks, which wouldn't be meaningful to non-Haskell code (a "value" can be a Haskell function that computes the value when demanded) |
2025-09-16 04:50:15 +0200 | <StatisticalIndep> | impossible.) |
2025-09-16 04:50:15 +0200 | <StatisticalIndep> | geekosaur: Yes, that’s probably my core pet peeve with how Haskell in implemented. It makes interoperation hard. But I get why it was chosen. The whole point was that all types should be checked at compile time, not at runtime. (Hence also things like dynamic libraries and variants with types that aren’t know at compile time yet, being hard or |
2025-09-16 04:48:24 +0200 | <StatisticalIndep> | Interesting: The Storable instances for basic types seem to be implemented inside GHC, and the libraries just use stuff like (writeWordOffAddr# = writeWordOffAddr#). So there is probably no actual marshalling work, and it’s fast and 1:1. |
2025-09-16 04:47:21 +0200 | <geekosaur> | re marshaling: requiring STorable doesn't seem like much of an issue, and you would need it anyway because Haskell values aren't designed to be meaningful outside of Haskell's heap |
2025-09-16 04:46:53 +0200 | merijn | (~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn |
2025-09-16 04:46:31 +0200 | <StatisticalIndep> | jackdk: Thanks a lot! |
2025-09-16 04:45:18 +0200 | <StatisticalIndep> | Ah, yes, StateVar was a pretty nice experience, when I used SDL. Comes really close to it, indeed. |
2025-09-16 04:45:10 +0200 | arandombit | (~arandombi@user/arandombit) arandombit |
2025-09-16 04:45:10 +0200 | arandombit | (~arandombi@2603:7000:4600:ffbe:21ee:ceac:8353:7a15) (Changing host) |
2025-09-16 04:45:10 +0200 | arandombit | (~arandombi@2603:7000:4600:ffbe:21ee:ceac:8353:7a15) |