The way codeforces is using GHC's "Safe Haskell" extension is disabling the use of very common and useful modules and extensions, for no benefit that I can figure out.
Importing any of these:
- Control.Monad.ST
- Data.Array.ST
- Data.Array.MArray
- Data.Array.IO
- Data.Vector
- Data.Vector.Unboxed
(and probably more, but these are the ones I tried) gives an error of the form:
Control.Monad.ST: Can't be safely imported!
The module itself isn't safe.
Additionally, the GeneralizedNewtypeDeriving
(GND) and TemplateHaskell
(TH) language extensions are disabled. (compiling with them turned on doesn't error, but they're ignored, so if you try to use them you then get errors).
All of these disabled things are very useful. As-is the Haskell setup on codeforces has no performant mutable arrays available at all, which it's hard to overstate how wacky that is in competitive programming.
The GND extension is quite useful as well since it avoids having to tediously reimplement typeclasses when you wrap a type.
TH is Haskell's metaprogramming facility, like templates in C++ or macros in C. It doesn't get used as much as those features do in their respective languages, but it's still handy now and then.
I'm not really sure why all of this is disabled or exactly what switches are being used to GHC, though it's obviously related to Safe Haskell.
To make it clear, the sense in which "Safe Haskell" is safe is not useful for codeforces. In the programs we write, we're allowed to do unrestricted IO (at the language level at least, I assume there's a VM wrapper or restrictions on I/O at the OS level) in the standard main
entry point to haskell programs. And since we're not writing a library, this is just an executable and used for nothing else, it doesn't make sense to judge the safety of the API we're exporting. There is no safety, you're running the IO action that we specify anyway and that's the only interface.
I would be interested what the motivation is for turning on safe haskell, especially in this way that disallows the use of very common modules and data structures. Even if safe haskell is somehow required (maybe TH would be a risk at compile time the way CF is set up?), there are still ways to whitelist certain modules/packages so we could use them, and this would have no risk that I can imagine.
While I'm at it, the version of GHC allowed is getting pretty old too. Something in the 8.x family, or even 7.10.x would be nice; there have been a couple of nice language changes since 7.8.3. Also 7.8.3 is kind of a uniquely annoying version because one of the common ways to get GHC is via the 'stack' tool, which doesn't support that version. The oldest it knows about is GHC 7.8.4. This makes it a bit uncertain trying to develop and test code locally for CF use.
Auto comment: topic has been updated by kadoban (previous revision, new revision, compare).
Modules in
vector
package are still are unavailable, but the modulescan be replaced with
Which are available in Codeforces's current Haskell environment.
Thanks, that's a nice tip. Thankfully I don't really use 'vector' anyway, so for me that'll fix essentially all of my problem (though it'd still be nice to get this issue fixed for real).
This still hasn't been fixed. Some problems are quasi-unsolvable without
Data.Vector
. Of course,MArray
s could be used instead, but that defeats the whole point of using Haskell, i.e. the speed-verbosity trade-off.MikeMirzayanov, please add
Data.Vector
.Bump. It is still impossible to use
Data.Vector
. Why is-XSafe
needed?We need, seriously, to remove
Safe
option from the Haskell configuration. I achieved my yellow in AtCoder with Haskell, and it was only possible with the help ofvector
library. Imagine, what if vector in Rust (update: originally "C++" here. In C++ iterator is a generalized pointer, but I need to emphasize transformability here) had no iterator and no user code had the chance of implementing it? That's the disaster we have here with Haskell now.Don't misunderstand: we have
vector
installed in the current configuration; however no single module from that package is invokable, since CodeForces GHC is currently configured withSafe
option and the modules fromvector
package is declared Unsafe.The effect of the GHC
Safe
option is comparable to prohibiting in Rust the source code from having a singleunsafe
block. However library-introduced unsafe code is allowed as long as it is declaredTrustWorthy
(it is like safe function having unsafe block in its implementation, although we can only declare the whole moduleTrustWorthy
), and the usual TrustWorthy Haskell library allow us to do any I/O. That is,Safe
does not add anything to the CodeForces security.MikeMirzayanov, sorry to mention you while you've got lots of work to do. However removing
Safe
option from the current Haskell configuration will make Haskell a performant language. I hope you consider the removal. Thanks.It's a little silly, as there isn't much reason to disable anything but
TemplateHaskell
in a competitive programming environment, but it isn't really that bad.vector
is nice, but be honest: It's not why you're coding in Haskell, and the (available on CodeForces) alternatives usingData.Array.MArray.Safe
, although certainly cumbersome, rarely need to be heavily used to solve a competitive programming problem.This should be fixed, but don't mistake it for an excuse. A lot is possible with Haskell, even on CodeForces. I am what holds me back, and I think the same goes for you.
Um... correct. I've gotta admit I might've been blind because I'm a golfer who's addicted to reduce execution time and allocated bytes and to see my Haskell code ranking among C++ and Rust codes in execution time order. My on-hand Union-Find library only has the variant written with
Data.Vector.Unboxed.Mutable
, since I hate the boxedInt
s in anIntMap Int
(by the way why haven't I written it with unboxedArray
?). My AtCoder submissions are completely polluted withUNPACK
s,ST
s,IO
s, and evenunsafeWrite
s everywhere Stream Fusions are not applicable...