I think I see: you are making the claim that dynamically allocating such references is not useful?
I think I see: you are making the claim that dynamically allocating such references is not useful?
Slightly stronger, I don’t see how you can implement that without breaking some fundamental part of the language (I think referential transparency, but I don’t have the background to concisely describe it).
BurningWitness:
I don’t see how you can implement that without breaking some fundamental part of the language
Well, I explained how I can get my API from yours.
And another potential implementation is explained here: A reference implementation of IOScopedRef
tomjaguarpaw:
Well, I explained how I can get my API from yours.
Yes, and I explained that I have no idea what “reading from the vault” would look like. I’m essentially getting
contextual vault :: Contextual Vault
foo :: IO ()
foo = do
a <- _ vault
print a
---
main =
withScopedIORef vault 5 $ \x ->
overriding x (+2) $
foo
with…
tomjaguarpaw:
It can grow dynamically.
Yes, but that would require a completely different implementation. No matter how you slice it these references will have to live in CPU cache, and a static table is the most compact solution to that.
Much like with [RFC] Mutable records as a GHC extension, I view a simple solution that fits the existing model as infinitely more preferable to both the…
tomjaguarpaw:
which allows references to be allocated dynamically
And that’s a feature you’ll have to argue for.
Per my earlier example the piece of code we’re looking to allow for is
main = overriding x (+2) foo
such that overriding x modifies the behavior of foo without passing x to foo.
Your implementation uses ReaderT Vault, which, as others have pointed out, is…
Following up from yesterday’s post:
Haskell's missing mutable reference type Links
Whilst looking at the Scoped thread-locals GHC proposal I realised that Haskell is missing a mutable reference type that some other languges have (and people have tried to encode in Haskell), so I wrote it up: haskells-missing-mutable-ref
Today I show a reference implementation for IOScopedRef:
I’m not sure exactly what implementation you’re thinking of, but a table which grows dynamically is essential to implement withIOScopedRef, which allows references to be allocated dynamically. However, that variable-size table can be implemented as a Vault inside a fixed-size table: A reference implementation of IOScopedRef
I’m still not quite sure what you mean. Yes, withIOScopedRef in particular, and IOScopedRef in general, is a feature I am arguing for! Part of its essential behaviour is to allow references to be allocated dynamically, just like an essential feature of IORef is that they can be allocated dynamically.
But suppose I had your contextual. I could define
contextual vault :: Contextual…
If the value is dynamically allocated, then how do you use it inside a function without passing it? And if you’re passing a value, why not determine the wanted behavior based on passed value instead? The following is obviously not valid Haskell:
module Foo (foo) where
withIOScopedRef 5 $ \x ->
let foo = _ x
The point here is that x is not a value , it’s a place. foo…
BurningWitness:
It’s mutating if you look at the flow imperatively, but that would be an implementation detail.
That’s a fine point of view. I don’t have a strong view on what “mutable” should mean, but I think it’s interesting to know that the fact that IORef is implemented by actually mutating the value stored in a piece of memory is also an implementation detail. According to The Key…
Thanks for the feedback!
BurningWitness:
Okay, I had to spend 40 minutes figuring out what this is, and I’m still not sure.
Maybe the reference implementation in the next article (linked at the top of the current one) will help?
BurningWitness:
Am I correct to understand that the problem you’re looking to solve is that of a user-definable implicit global context, which can be adjusted…
tomjaguarpaw:
Why is it not “mutable from the user perspective”? The value of
x“mutates” here, doesn’t it?
It’s mutating if you look at the flow imperatively, but that would be an implementation detail. I instead think of x as a stack of changes over the initial value; no matter what I do, upon reaching the end of an overriding function x will be exactly the same as it was…
A Stackage intro/status report by Jens Petersen.
Stackage
### Stackage talk at Haskell Ecosystem Workshop 2026
Stackage talk given at the HF Haskell Ecosystem Workshop 2026 (Zurihac)
Two new i386 specific bugs were found on GHC this week:
GitLab
when building ghc for i386, either in an i386 debian container or targetting i386 on x86_64 host, if the ghc tree is configured with --intree-gmp, the external...
GitLab
Okay, I had to spend 40 minutes figuring out what this is, and I’m still not sure.
Am I correct to understand that the problem you’re looking to solve is that of a user-definable implicit global context, which can be adjusted locally, e.g.
overriding :: Contextual a -> (a -> a) -> (forall b. IO b -> IO b) -- deeply magical
contextual x :: Contextual Int -- still magical
contextual…
Oops, i did misread the example slightly sorry ^^ You’re using the IOScopedRef to implement modifySeverity not to modify the Logger value directly.
My point still stands though. Everything that (indirectly) uses this IOScopedRef needs to go through the logger variable anyway so you might as well use it to carry the state in a lexically scoped way.
OK, then tell me how I could obtain…
OK, I think I probably understand what you mean. You mean that if you’re passing the logger around everywhere you may as well replace all instances of
modifySeverity logger f $ do
...
with
logger <- modifySeverity logger f
...
and so you’re asking for an example where you _can’t_ do that transformation. Sure. First, notice that you can only do that transformation if you…
Hello Community!
At ZuriHac I was encouraged to reach out more about what is going with GHC Releases.
So this is a short and somewhat informal update about the status of various releases.
Currently we have five active branches which are far too many for the number of maintainers available. These branches are: master, 10.0, 9.14, 9.12, 9.10
For this reason the…
So, I’m guessing the use case here is that you have a computation that already somehow captures the IOScopedRef, as in
do
ref <- newIOScopedRef 0
let printCurrent = do
current <- readIOScopedRef ref
print current
modifyScopedIORef ref (+1) do
...
printCurrent -- implicitly uses the captured…
Unless I’m totally misreading something, the logging example _doesn’t_ capture the logger. Everything that accesses it also takes it as a parameter. So it’s really equivalent to
loggerExample :: IO ()
loggerExample = do
let logger = newLogger 0
logMsg logger 1 "Getting user"
user <- getUser
logMsg logger 1 ("Is VIP: " <> show (isVip user))
let modification…
prophet:
I’m guessing the use case here is that you have a computation that already somehow captures the
IOScopedRef
Right.
prophet:
Do you have an example where this is useful to have?
“A logging library” from the article is supposed to provide such an example. Is there something I could do to make that clearer? (Also feel free to skip forward two articles in the series to…
prophet:
the logging example doesn’t capture the logger
Well, the definition of Logger does not use IOScopedRef directly. Logger could be defined in a module that doesn’t even know IOScopedRef exists. The IOScopedRef is captured in the closures that are stored in the Logger value, isn’t it? If not, what do you mean by “capture”?
prophet:
So it’s really equivalent to
Sure,…
I’d stick with isExtensionOf here. OsChar isn’t really a Unicode character anyway—it’s closer to a unit of the underlying OS string encoding. For filepath extensions, working at the OsString/filepath level is usually cleaner and avoids encoding-related surprises.
Whilst looking at the Scoped thread-locals GHC proposal I realised that Haskell is missing a mutable reference type that some other languges have (and people have tried to encode in Haskell), so I wrote it up:
From how I read Jello_Raptor comments on Announcing Mutation Testing in Haskell the library just surfaces these untested situations for you, it’s up to you to deal with them. The immediate goal here is to improve the test suite, which presumably will eventually improve the quality of the code[0]. I’ve done lots of minor “manual mutation testing” to ensure a new test covers a bugfix, so I do see…
Keep in mind that OsChar is actually more or less a byte in an encoded byte sequence. You could argue it should have been named OsWord to avoid confusion.
There are cases where extracting an OsChar and pattern matching on it makes sense, e.g. notably with the filepath separator /, because it is encoding agnostic. But in other cases you may get nonsensical results if you expect…
andremarianiello:
The question is: does this mutation cause a change in behavior that is caught by a test?
Why should I care?
The basic assumption seems to be that a test suite must fail if the code is altered semantically.
Suppose there are two data types, A and B and a function f :: A -> B that is to be tested. Suppose both A and B are finite with n and m total elements,…
A test suite for test suites, is it?
How can I tell that a mutation is
Especially with AI-generated code, I venture that mutation might actually have a chance of improving the code. Isn’t that what genetic algorithms were about?
The question isn’t whether a mutation is good or bad. The question is: does this mutation cause a change in behavior that is caught by a test?