Newest at the top
| 2026-04-09 11:51:22 +0000 | <tomsmeding> | Milan_Vanca: precisely that code, without any type annotations? |
| 2026-04-09 11:51:10 +0000 | <Milan_Vanca> | https://paste.tomsmeding.com/resvyMiU |
| 2026-04-09 11:51:08 +0000 | <Milan_Vanca> | what about this? |
| 2026-04-09 11:51:00 +0000 | <tomsmeding> | (that's like 4 abstraction levels down suddenly from what we were talking about_) |
| 2026-04-09 11:50:39 +0000 | <tomsmeding> | if you want to know whether a memory read will occur, well, good luck reading the assembly, no guarantees |
| 2026-04-09 11:50:38 +0000 | <Freakie> | i guess memoization invalidates what I just said yeah |
| 2026-04-09 11:50:18 +0000 | <tomsmeding> | Freakie: we're talking about the semantic level here, where reading the value from memory doesn't count as recomputation |
| 2026-04-09 11:50:06 +0000 | <Milan_Vanca> | ? |
| 2026-04-09 11:49:59 +0000 | <mauke> | Freakie: ??? |
| 2026-04-09 11:49:55 +0000 | <Freakie> | (I think) |
| 2026-04-09 11:49:53 +0000 | <Freakie> | if it can't fit in the registers it will have to be recomputed |
| 2026-04-09 11:49:44 +0000 | <tomsmeding> | if x :: Num a => a, or Show a => [a], or something like that, then it will (likely!) be recomputed |
| 2026-04-09 11:49:43 +0000 | <Freakie> | it's also tricky because if you assume *any* number of instructions you can't say anything register allocation |
| 2026-04-09 11:49:33 +0000 | Enrico63 | (~Enrico63@host-212-171-80-94.pool212171.interbusiness.it) Enrico63 |
| 2026-04-09 11:49:24 +0000 | <tomsmeding> | if x :: Int, then x will be computed only once |
| 2026-04-09 11:49:11 +0000 | <tomsmeding> | Milan_Vanca: no, you cannot say anything about your example unless you know what the type of x is |
| 2026-04-09 11:49:03 +0000 | <mauke> | what |
| 2026-04-09 11:48:51 +0000 | <Milan_Vanca> | tomsmeding showed that x will be computed only once.. so first 2 will be reused then forgoten then recomputed? |
| 2026-04-09 11:48:29 +0000 | <Freakie> | tomsmeding we're not strictly talking purity here though |
| 2026-04-09 11:48:12 +0000 | <mauke> | first what? |
| 2026-04-09 11:48:04 +0000 | <Milan_Vanca> | the same as first one |
| 2026-04-09 11:48:03 +0000 | <tomsmeding> | if x has a monomorphic type, reused; if x has a polymorphic type with type class constraints, recomputed (likely) |
| 2026-04-09 11:47:40 +0000 | <mauke> | Milan_Vanca: depends on the type of x |
| 2026-04-09 11:47:37 +0000 | <tomsmeding> | Freakie: yes, because without IO, everything is pure and hence deterministic |
| 2026-04-09 11:47:29 +0000 | <Milan_Vanca> | what about main = do print x; print x; ... lot of other code; print x will last x be kept or recomputed? |
| 2026-04-09 11:47:24 +0000 | <tomsmeding> | in which case, well, you're using unsafePerformIO, you better know what you're doing |
| 2026-04-09 11:47:23 +0000 | <Freakie> | would it have to use unsafePerformIO? |
| 2026-04-09 11:47:10 +0000 | <tomsmeding> | Freakie: the only way I can make sense of that is `unsafePerformIO (uniform <$> newStdGen)` or whatever the precise API is of System.Random |
| 2026-04-09 11:46:21 +0000 | <tomsmeding> | at which point, `x' :: Int` and is a normal variable, so that `print x' >> print x'` will definitely compute x only once |
| 2026-04-09 11:46:00 +0000 | <tomsmeding> | then GHC can decide to do common subexpression elimination, and rewrite that to `main = let x' = x dNumInt in print x' >> print x'`, but GHC may or may not decide to do this |
| 2026-04-09 11:45:59 +0000 | haritz | (~hrtz@user/haritz) haritz |
| 2026-04-09 11:45:59 +0000 | haritz | (~hrtz@2a01:4b00:bc2e:7000:d5af:a266:ca31:5ef8) (Changing host) |
| 2026-04-09 11:45:59 +0000 | haritz | (~hrtz@2a01:4b00:bc2e:7000:d5af:a266:ca31:5ef8) |
| 2026-04-09 11:45:26 +0000 | <mauke> | Freakie: ? |
| 2026-04-09 11:45:25 +0000 | <tomsmeding> | assuming you mean `print (x :: Int)`, that compiles to something like `main = print (x dNumInt) >> print (x dNumInt)`, where dNumInt is the "Num Int" type class dictionary (evidence) |
| 2026-04-09 11:45:14 +0000 | <Freakie> | if x is a value from a non-deterministic monad it should be recomputed |
| 2026-04-09 11:44:50 +0000 | <mauke> | but it sounds like you're talking about the result of a function |
| 2026-04-09 11:44:35 +0000 | <mauke> | functions are also reused |
| 2026-04-09 11:44:31 +0000 | <Milan_Vanca> | yeah but in example of main = do print x; print x it is always same right? should not be reevaluated? |
| 2026-04-09 11:44:30 +0000 | <Freakie> | I mean if called with the same type argument it should reuse the expression? |
| 2026-04-09 11:44:22 +0000 | <tomsmeding> | what GHC _could_ do is reuse x when used twice at the same type; whether that actually happens depends on what GHC's optimiser decides to do, no guarantees |
| 2026-04-09 11:44:20 +0000 | <mauke> | well... |
| 2026-04-09 11:43:53 +0000 | <tomsmeding> | Milan_Vanca: indeed, because it _cannot_ be reused: its value is different at different types 'a'! |
| 2026-04-09 11:43:42 +0000 | <tomsmeding> | thus it's really a function: from the "Num a" evidence to the resulting value; the `=>` arrow should be read as a function arrow here |
| 2026-04-09 11:43:26 +0000 | <Milan_Vanca> | so x in your example is function and wont be reused? |
| 2026-04-09 11:43:18 +0000 | <tomsmeding> | there we have `x :: Num a => a`, and x's value is different for each type you can fill in for `a` |
| 2026-04-09 11:42:56 +0000 | <tomsmeding> | variables can be secretly functions if they are actually polymorphic with a typeclass argument, such as `x = 4` |
| 2026-04-09 11:42:48 +0000 | <mauke> | (where "secretly a function" is that class constraints thing I was talking about) |
| 2026-04-09 11:42:02 +0000 | <tomsmeding> | Milan_Vanca: using a variable name multiple times does not result in its definition being computed multiple times, except when that variable is secretly a function |
| 2026-04-09 11:41:30 +0000 | <mauke> | you never "need" do notation |