kadoban's blog

By kadoban, history, 7 years ago, In English

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.

  • Vote: I like it
  • +46
  • Vote: I do not like it

| Write comment?
»
7 years ago, # |
  Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by kadoban (previous revision, new revision, compare).

»
7 years ago, # |
  Vote: I like it +18 Vote: I do not like it

Modules in vector package are still are unavailable, but the modules

  • Control.Monad.ST
  • Data.Array.ST
  • Data.Array.MArray
  • Data.Array.IO

can be replaced with

  • Control.Monad.ST.Safe
  • Data.Array.ST.Safe
  • Data.Array.MArray.Safe
  • Data.Array.IO.Safe

Which are available in Codeforces's current Haskell environment.

  • »
    »
    7 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    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).

»
7 years ago, # |
  Vote: I like it +4 Vote: I do not like it

This still hasn't been fixed. Some problems are quasi-unsolvable without Data.Vector. Of course, MArrays 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.

  • »
    »
    7 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Bump. It is still impossible to use Data.Vector. Why is -XSafe needed?

»
4 years ago, # |
Rev. 4   Vote: I like it +70 Vote: I do not like it

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 of vector 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 with Safe option and the modules from vector package is declared Unsafe.

The effect of the GHC Safe option is comparable to prohibiting in Rust the source code from having a single unsafe block. However library-introduced unsafe code is allowed as long as it is declared TrustWorthy (it is like safe function having unsafe block in its implementation, although we can only declare the whole module TrustWorthy), 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.

  • »
    »
    4 years ago, # ^ |
      Vote: I like it +21 Vote: I do not like it

    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 using Data.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.

    • »
      »
      »
      4 years ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      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 boxed Ints in an IntMap Int (by the way why haven't I written it with unboxed Array?). My AtCoder submissions are completely polluted with UNPACKs, STs, IOs, and even unsafeWrites everywhere Stream Fusions are not applicable...