From mark.lentczner at gmail.com Mon Jun 1 04:06:19 2015 From: mark.lentczner at gmail.com (Mark Lentczner) Date: Sun, 31 May 2015 21:06:19 -0700 Subject: Time files... and here's another alpha HP for 7.10 Message-ID: So - I hear from a bird that 7.10.2 might be just around the corner. I'm getting ahead of the curve! I just did a fully hermetic and clean build of head of GHC 7.10 branch (what should become 7.10.2), and then brought HP up-to-date: - bootstrapped with 7.10.1 (so hptool needed fixes to build with that) - uses latest shake - built on a clean Debian Wheezy (7) install, (hence uses glibc 2.13 and should also run on Ubuntu 12.04 and later) The package versions are updated as follows: Cabal 1.22.2.0 --> 1.22.3.0 cabal-install 1.22.2.0 --> 1.22.4.0 attoparsec 0.12.1.4 --> 0.13.0.0 syb 0.4.4 --> 0.5.1 text 1.2.0.4 --> 1.2.1.1 cgi 3001.2.2.1 --> 3001.2.2.2 network 2.6.0.2 --> 2.6.2.0 network-uri 2.6.0.1 --> 2.6.0.3 QuickCheck 2.8 --> 2.8.1 hscolour 1.22 --> 1.23 GLUT 2.7.0.0 --> 2.7.0.1 GLURaw 1.5.0.0 --> 1.5.0.1 OpenGL 2.12.0.0 --> 2.12.0.1 OpenGLRaw 2.4.1.0 --> 2.5.0.0 Only package issue was: zlib 0.5.4.2 -- held back because cabal-install needs < 0.6 All the same caveats and notes from Alpha 2 still apply. All these changes are in the pre-release-2 branch on github -- I'll merge it all together later this week. There is a hp-bindist-tarball on my server: haskell-platform-7.10.1.20150528-x86_64-unknown-linux-deb7.tar.gz SHA-256: b503c9e2c34c0865b5fee39444027667bb39b786fa7664029287e3bbf33379da I'll build and put up OS X version in a day or two. One last thing... I'm proposing that we name this release: Haskell Platform 7.10.2 ! - Mark -------------- next part -------------- An HTML attachment was scrubbed... URL: From g9ks157k at acme.softbase.org Mon Jun 1 15:58:50 2015 From: g9ks157k at acme.softbase.org (Wolfgang Jeltsch) Date: Mon, 01 Jun 2015 18:58:50 +0300 Subject: cabal-install: bug and quest for a workaround Message-ID: <1433174330.17993.38.camel@idefix> Hi, I have just installed GHC 7.10.1 and cabal-install 1.22.4.0. The problem is that cabal-install often hangs when trying to download a package. With --verbose=3, I see that it gets a ?301 Moved Permanently? from the server, tries to redirect, shows ?Recovering connection to hackage.haskell.org?, and then hangs. Is there anything I can do to work around this issue? At the moment, I cannot work with my new GHC installation, since it is virtually impossible to install packages with cabal-install. All the best, Wolfgang From rf at rufflewind.com Mon Jun 1 22:02:07 2015 From: rf at rufflewind.com (Phil Ruffwind) Date: Mon, 1 Jun 2015 18:02:07 -0400 Subject: [directory] status of HsDirectory.h Message-ID: I noticed that there aren't many things left in the HsDirectory.h: - macros from autoconf - __hscore_long_path_size - __hscore_S_IRUSR/IWUSR/IXUSR/IFDIR Most of these could be done easily using hsc so I was tempted to remove them. Not to mention, the implementation of __hscore_long_path_size is rather dangerous on systems where PATH_MAX is not defined.[1] However, I wonder if the __hscore prefix has any significance. Are these functions by any chance used in GHC internals or some other libraries? For now I intend to leave them as is. But if no-one else uses them, then I think the header should be deprecated and made private in the future. [1]: http://pubs.opengroup.org/onlinepubs/9699919799 -- Phil From mark.lentczner at gmail.com Tue Jun 2 07:03:24 2015 From: mark.lentczner at gmail.com (Mark Lentczner) Date: Tue, 2 Jun 2015 00:03:24 -0700 Subject: Time files... and here's another alpha HP for 7.10 In-Reply-To: References: Message-ID: There is now an OS X installer of this* "pre 7.10.2 - we'll just call it alpha 3" *Platform, again, built with head of GHC 7.10 branch this morning: Haskell Platform 7.10.1.20150601 alpha 3 64bit.pkg SHA-256: 65adae24b0a75e23c77632e7375198b4f3158e49984e3a1afec452d7ae5832ce Watch out... it weighs 230MiB! -------------- next part -------------- An HTML attachment was scrubbed... URL: From mark.lentczner at gmail.com Tue Jun 2 13:22:04 2015 From: mark.lentczner at gmail.com (Mark Lentczner) Date: Tue, 2 Jun 2015 06:22:04 -0700 Subject: Time files... and here's another alpha HP for 7.10 In-Reply-To: References: Message-ID: On Tue, Jun 2, 2015 at 4:40 AM, George Colpitts wrote: > I guess I should file a haddock bug as I got the same error installing > threadscope Does ghc --print-libdir display the correct path? (That is, with the full version number.) - Mark -------------- next part -------------- An HTML attachment was scrubbed... URL: From wren at community.haskell.org Sun Jun 7 00:49:35 2015 From: wren at community.haskell.org (wren romano) Date: Sat, 6 Jun 2015 20:49:35 -0400 Subject: ANN: bytestring-lexing 0.5.0 Message-ID: -------------------------------------------- -- bytestring-lexing 0.5.0 -------------------------------------------- The bytestring-lexing package offers extremely efficient bytestring parsers for some common lexemes: namely integral and fractional numbers. In addition, it provides efficient serializers for (some of) the formats it parses. As of version 0.3.0, bytestring-lexing offers the best-in-show parsers for integral values. (According to the Warp web server's benchmark of parsing the Content-Length field of HTTP headers.) And as of this version (0.5.0) it offers (to my knowledge) the best-in-show parser for fractional/floating numbers. -------------------------------------------- -- Changes since 0.4.3 (2013-03-21) -------------------------------------------- I've completely overhauled the parsers for fractional numbers. The old Data.ByteString.Lex.Double and Data.ByteString.Lex.Lazy.Double modules have been removed, as has their reliance on Alex as a build tool. I know some users were reluctant to use bytestring-lexing because of that dependency, and forked their own version of bytestring-lexing-0.3.0's integral parsers. This is no longer an issue, and those users are requested to switch over to using bytestring-lexing. The old modules are replaced by the new Data.ByteString.Lex.Fractional module. This module provides two variants of the primary parsers. The readDecimal and readExponential functions are very simple and should suffice for most users' needs. The readDecimalLimited and readExponentialLimited are variants which take an argument specifying the desired precision limit (in decimal digits). With care, the limited-precision parsers can perform far more efficiently than the unlimited-precision parsers. Performance aside, they can also be used to intentionally restrict the precision of your program's inputs. -------------------------------------------- -- Benchmarks -------------------------------------------- For the Criterion output of the benchmark discussed below, see . The main competitors we compare against are the previous version of bytestring-lexing (which already surpassed text and attoparsec/scientific) and bytestring-read which was the previous best-in-show. The unlimited-precision parsers provide 3.3x to 3.9x speedup over the readDouble function from bytestring-lexing-0.4.3.3, as well as being polymorphic over all Fractional values. For Float/Double: these functions have essentially the same performance as bytestring-read on reasonable inputs (1.07x to 0.89x), but for inputs which have far more precision than Float/Double can handle these functions are much slower than bytestring-read (0.30x 'speedup'). However, for Rational: these functions provide 1.26x to 1.96x speedup compared to bytestring-read. The limited-precision parsers do even better, but require some care to use properly. For types with infinite precision (e.g., Rational) we can pass in an 'infinite' limit by passing the length of the input string plus one. For Rational: doing so provides 1.5x speedup over the unlimited-precision parsers (and 1.9x to 3x speedup over bytestring-read), because we can avoid intermediate renormalizations. Whether other unlimited precision types would see the same benefit remains an open question. For types with inherently limited precision (e.g., Float/Double), we could either pass in an 'infinite' limit or we could pass in the actual inherent limit. For types with inherently limited precision, passing in an 'infinite' limit degrades performance compared to the unlimited-precision parsers (0.51x to 0.8x 'speedup'). Whereas, passing in the actual inherent limit gives 1.3x to 4.5x speedup over the unlimited-precision parsers. They also provide 1.2x to 1.4x speedup over bytestring-read; for a total of 5.1x to 14.4x speedup over bytestring-lexing-0.4.3.3! -------------------------------------------- -- Links -------------------------------------------- Homepage: http://code.haskell.org/~wren/ Hackage: http://hackage.haskell.org/package/bytestring-lexing Darcs: http://community.haskell.org/~wren/bytestring-lexing Haddock (Darcs version): http://community.haskell.org/~wren/bytestring-lexing/dist/doc/html/bytestring-lexing -- Live well, ~wren From lemming at henning-thielemann.de Mon Jun 8 18:18:28 2015 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Mon, 8 Jun 2015 20:18:28 +0200 (CEST) Subject: deepseq:NFData1 class Message-ID: I have the type data NonEmpty f a = NonEmpty a (f a) and want to declare an NFData instance in Haskell 98. With the existing NFData class this is not possible because it requires a (NFData (f a)) constraint which needs FlexibleContexts. A solution would be an NFData1 class analogously to the classes in transformers:Data.Functor.Classes: class NFData1 f where rnf1 :: NFData a => f a -> () instance NFData1 [] where rnf1 = rnf instance (NFData1 f) => NFData1 (NonEmpty f) where rnf1 (NonEmpty x xs) = rnf (x, rnf1 xs) instance (NFData1 f, NFData a) => NFData (NonEmpty f a) where rnf = rnf1 From mark.lentczner at gmail.com Tue Jun 9 14:02:24 2015 From: mark.lentczner at gmail.com (Mark Lentczner) Date: Tue, 9 Jun 2015 07:02:24 -0700 Subject: Time files... and here's another alpha HP for 7.10 In-Reply-To: References: Message-ID: When you did the cabal install of haddock, which haddock did you get? Isn't 2.16.0 the latest? And that should be what is in the Platform. I guess I should check that the haddock in GHC is actually 2.16.0! ? -------------- next part -------------- An HTML attachment was scrubbed... URL: From dluposchainsky at googlemail.com Tue Jun 9 20:43:30 2015 From: dluposchainsky at googlemail.com (David Luposchainsky) Date: Tue, 09 Jun 2015 22:43:30 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad Message-ID: <55774FF2.8020505@gmail.com> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hello *, the subject says it all. After we successfully put `=>` into Monad, it is time to remove something in return: `fail`. Like with the AMP, I wrote up the proposal in Markdown format on Github, which you can find below as a URL, and in verbatim copy at the end of this email. It provides an overview over the intended outcome, which design decisions we had to take, and how our initial plan for the transition looks like. There are also some issues left open to discussion. https://github.com/quchen/articles/blob/master/monad_fail.md Here's a short abstract: - - Move `fail` from `Monad` into a new class `MonadFail`. - - Code using failable patterns will receive a more restrictive `MonadFail` constraint. Code without this constraint will be safe to use for all Monads. - - Transition will take at least two GHC releases. GHC 7.12 will include the new class, and generate warnings asking users to make their failable patterns compliant. - - Stackage showed an upper bound of less than 500 breaking code fragments when compiled with the new desugaring. For more details, refer to the link or the paste at the end. Let's get going! David aka quchen =============================================================== =============================================================== =============================================================== `MonadFail` proposal (MFP) ========================== A couple of years ago, we proposed to make `Applicative` a superclass of `Monad`, which successfully killed the single most ugly thing in Haskell as of GHC 7.10. Now, it's time to tackle the other major issue with `Monad`: `fail` being a part of it. You can contact me as usual via IRC/Freenode as *quchen*, or by email to *dluposchainsky at the email service of Google*. This file will also be posted on the ghc-devs@ and libraries@ mailing lists, as well as on Reddit. Overview - -------- - - **The problem** - reason for the proposal - - **MonadFail class** - the solution - - **Discussion** - explaining our design choices - - **Adapting old code** - how to prepare current code to transition smoothly - - **Esimating the breakage** - how much stuff we will break (spoiler: not much) - - **Transitional strategy** - how to break as little as possible while transitioning - - **Current status** The problem - ----------- Currently, the `<-` symbol is unconditionally desugared as follows: ```haskell do pat <- computation >>> let f pat = more more >>> f _ = fail "..." >>> in computation >>= f ``` The problem with this is that `fail` cannot (!) be sensibly implemented for many monads, for example `State`, `IO`, `Reader`. In those cases it defaults to `error`. As a consequence, in current Haskell, you can not use `Monad`-polymorphic code safely, because although it claims to work for all `Monad`s, it might just crash on you. This kind of implicit non-totality baked into the class is *terrible*. The goal of this proposal is adding the `fail` only when necessary and reflecting that in the type signature of the `do` block, so that it can be used safely, and more importantly, is guaranteed not to be used if the type signature does not say so. `MonadFail` class - ----------------- To fix this, introduce a new typeclass: ```haskell class Monad m => MonadFail m where fail :: String -> m a ``` Desugaring can now be changed to produce this constraint when necessary. For this, we have to decide when a pattern match can not fail; if this is the case, we can omit inserting the `fail` call. The most trivial examples of unfailable patterns are of course those that match anywhere unconditionally, ```haskell do x <- action >>> let f x = more more >>> in action >>= f ``` In particular, the programmer can assert any pattern be unfailable by making it irrefutable using a prefix tilde: ```haskell do ~pat <- action >>> let f ~pat = more more >>> in action >>= f ``` A class of patterns that are conditionally failable are `newtype`s, and single constructor `data` types, which are unfailable by themselves, but may fail if matching on their fields is done with failable paterns. ```haskell data Newtype a = Newtype a - -- "x" cannot fail do Newtype x <- action >>> let f (Newtype x) = more more >>> in action >>= f - -- "Just x" can fail do Newtype (Just x) <- action >>> let f (Newtype (Just x)) = more more >>> f _ = fail "..." >>> in action >>= f ``` `ViewPatterns` are as failable as the pattern the view is matched against. Patterns like `(Just -> Just x)` should generate a `MonadFail` constraint even when it's "obvious" from the view's implementation that the pattern will always match. From an implementor's perspective, this means that only types (and their constructors) have to be looked at, not arbitrary values (like functions), which is impossible to do statically in general. ```haskell do (view -> pat) <- action >>> let f (view -> pat) = more more >>> f _ = fail "..." >>> in action >>= f do (view -> ~pat) <- action >>> let f (view -> ~pat) = more more >>> in action >>= f ``` A similar issue arises for `PatternSynonyms`, which we cannot inspect during compilation sufficiently. A pattern synonym will therefore always be considered failable. ```haskell do PatternSynonym x <- action >>> let f PatternSynonym x = more more >>> in f _ = fail "..." >>> in action >>= f ``` Discussion - ---------- - - Although for many `MonadPlus` `fail _ = mzero`, a separate `MonadFail` class should be created instead of just using that. - A parser might fail with an error message involving positional information. Some libraries, like `Binary`, provide `fail` as their only interface to fail a decoding step. - Although `STM` is `MonadPlus`, it uses the default `fail = error`. It will therefore not get a `MonadFail` instance. - - What laws should `fail` follow? **Left zero**, ```haskell ? s f. fail s >>= f ? fail s ``` A call to `fail` should abort the computation. In this sense, `fail` would become a close relative of `mzero`. It would work well with the common definition `fail _ = mzero`, and give a simple guideline to the intended usage and effect of the `MonadFail` class. - - Rename `fail`? **No.** Old code might use `fail` explicitly and we might avoid breaking it, the Report talks about `fail`, and we have a solid migration strategy that does not require a renaming. - - Remove the `String` argument? **No.** The `String` might help error reporting and debugging. `String` may be ugly, but it's the de facto standard for simple text in GHC. No high performance string operations are to be expected with `fail`, so this breaking change would in no way be justified. Also note that explicit `fail` calls would break if we removed the argument. - - How sensitive would existing code be to subtle changes in the strictness behaviour of `do` notation pattern matching? **It doesn't.** The implementation does not affect strictness at all, only the desugaring step. Care must be taken when fixing warnings by making patterns irrefutable using `~`, as that *does* affect strictness. (Cf. difference between lazy/strict State) - - The `Monad` constraint for `MonadFail` seems unnecessary. Should we drop or relax it? What other things should be considered? - Applicative `do` notation is coming sooner or later, `fail` might be useful in this more general scenario. Due to the AMP, it is trivial to change the `MonadFail` superclass to `Applicative` later. (The name will be a bit misleading, but it's a very small price to pay.) - The class might be misused for a strange pointed type if left without any constraint. This is not the intended use at all. I think we should keep the `Monad` superclass for three main reasons: - We don't want to see `(Monad m, MonadFail m) =>` all over the place. - The primary intended use of `fail` is for desugaring do-notation anyway. - Retroactively removing superclasses is easy, but adding them is hard (see AMP). Adapting old code - ----------------- - - Help! My code is broken because of a missing `MonadFail` instance! *Here are your options:* 1. Write a `MonadFail` instance (and bring it into scope) ```haskell #if !MIN_VERSION_base(4,11,0) -- Control.Monad.Fail import will become redundant in GHC 7.16+ import qualified Control.Monad.Fail as Fail #endif import Control.Monad instance Monad Foo where (>>=) = <...bind impl...> -- NB: `return` defaults to `pure` #if !MIN_VERSION_base(4,11,0) -- Monad(fail) will be removed in GHC 7.16+ fail = Fail.fail #endif instance MonadFail Foo where fail = <...fail implementation...> ``` 2. Change your pattern to be irrefutable 3. Emulate the old behaviour by desugaring the pattern match by hand: ```haskell do Left e <- foobar stuff ``` becomes ```haskell do x <- foobar e <- case foobar of Left e' -> e' Right r -> error "Pattern match failed" -- Boooo stuff ``` The point is you'll have to do your dirty laundry yourself now if you have a value that *you* know will always match, and if you don't handle the other patterns you'll get incompleteness warnings, and the compiler won't silently eat those for you. - - Help! My code is broken because you removed `fail` from `Monad`, but my class defines it! *Delete that part of the instance definition.* Esimating the breakage - ---------------------- Using our initial implementation, I compiled stackage-nightly, and grepped the logs for found "invalid use of fail desugaring". Assuming my implementation is correct, the number of "missing `MonadFail`" warnings generated is 487. Note that I filtered out `[]`, `Maybe` and `ReadPrec`, since those can be given a `MonadFail` instance from within GHC, and no breakage is expected from them. The build logs can be found [here][stackage-logs]. Search for "failable pattern" to find your way to the still pretty raw warnings. Transitional strategy - --------------------- The roadmap is similar to the [AMP][amp], the main difference being that since `MonadFail` does not exist yet, we have to introduce new functionality and then switch to it. * **GHC 7.12 / base-4.9** - Add module `Control.Monad.Fail` with new class `MonadFail(fail)` so people can start writing instances for it. `Control.Monad` only re-exports the class `MonadFail`, but not its `fail` method. NB: At this point, `Control.Monad.Fail.fail` clashes with `Prelude.fail` and `Control.Monad.fail`. - *(non-essential)* Add a language extension `-XMonadFail` that changes desugaring to use `MonadFail(fail)` instead of `Monad(fail)`. This has the effect that typechecking will infer a `MonadFail` constraint for `do` blocks with failable patterns, just as it is planned to do when the entire thing is done. - Warn when a `do`-block that contains a failable pattern is desugared, but there is no `MonadFail`-instance in scope: "Please add the instance or change your pattern matching." Add a flag to control whether this warning appears. - Warn when an instance implements the `fail` function (or when `fail` is imported as a method of `Monad`), as it will be removed from the `Monad` class in the future. (See also [GHC #10071][trac-10071]) 3. GHC 7.14 - Switch `-XMonadFail` on by default. - Remove the desugaring warnings. 3. GHC 7.16 - Remove `-XMonadFail`, leaving its effects on at all times. - Remove `fail` from `Monad`. - Instead, re-export `Control.Monad.Fail.fail` as `Prelude.fail` and `Control.Monad.fail`. - `Control.Monad.Fail` is now a redundant module that can be considered deprecated. Current status - -------------- - - [ZuriHac 2015 (29.5. - 31.5.)][zurihac]: Franz Thoma (@fmthoma) and me (David Luposchainsky aka @quchen) started implementing the MFP in GHC. - Desugaring to the new `fail` can be controlled via a new langauge extension, `MonadFailDesugaring`. - If the language extension is turned off, a warning will be emitted for code that would break if it was enabled. - Warnings are emitted for types that *have* a *MonadFail* instance. This still needs to be fixed. - The error message are readable, but should be more so. We're still on this. - - 2015-06-09: Estimated breakage by compiling Stackage. Smaller than expected. [amp]: https://github.com/quchen/articles/blob/master/applicative_monad.md [stackage-logs]: https://www.dropbox.com/s/knz0i979skam4zs/stackage-build.tar.xz?dl=0 [trac-10071]: https://ghc.haskell.org/trac/ghc/ticket/10071 [zurihac]: https://wiki.haskell.org/ZuriHac2015 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAEBAgAGBQJVd0/yAAoJELrQsaT5WQUshbUH/A3W0itVAk7ao8rtxId5unCJ 7StriKVkTyLAkkrbRJngM4MHEKiCsoyIgr8kBIwSHgk194GxeP2NCF4ijuBZoDBt +Uci+6BCBinV8+OzfrfTcJb4+8iw1j+eLWJ/Nz/JDMDNCiyzyC0SMsqGa+ssOz7H /2mqPkQjQgpHuP5PTRLHKPPIsayCQvTbZR1f14KhuMN2SPDE+WY4rqugu//XuIkN u1YssIf5l8mEez/1ljaqGL55cTI0UNg2z0iA0bFl/ajHaeQ6mc5BAevWfSohAMW7 7PIt13p9NIaMHnikmI+YJszm2IEaXuv47mGgbyDV//nHq3fwWN+naB+1mPX2eSU= =vPAL -----END PGP SIGNATURE----- From lemming at henning-thielemann.de Tue Jun 9 20:52:54 2015 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Tue, 9 Jun 2015 22:52:54 +0200 (CEST) Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55774FF2.8020505@gmail.com> References: <55774FF2.8020505@gmail.com> Message-ID: On Tue, 9 Jun 2015, David Luposchainsky wrote: > the subject says it all. After we successfully put `=>` > into Monad, it is time to remove something in return: `fail`. Let me start the "+1" flood with my own +1. > - - Stackage showed an upper bound of less than 500 breaking > code fragments when compiled with the new desugaring. I found that code breakage generally is not a big problem for me. I can fix code and that's it. I am more concerned with writing code that can be compiled by several GHC versions. From qdunkan at gmail.com Tue Jun 9 21:04:02 2015 From: qdunkan at gmail.com (Evan Laforge) Date: Tue, 9 Jun 2015 14:04:02 -0700 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55774FF2.8020505@gmail.com> References: <55774FF2.8020505@gmail.com> Message-ID: Definitely +1 here, but if you have an irrefutable pattern: ~(Just x) <- action ... expresison involving x ... My understanding is that 'fail' is only called if you evaluate 'x'. So I guess any expression with 'x' in it would also imply the MonadFail constraint. So ~ might just move the constraint until the next line. Or if you pass 'x' to someone else, do they now get MonadFail? Would it be worth pointing that out? On Tue, Jun 9, 2015 at 1:43 PM, David Luposchainsky wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Hello *, > > the subject says it all. After we successfully put `=>` > into Monad, it is time to remove something in return: `fail`. > > Like with the AMP, I wrote up the proposal in Markdown > format on Github, which you can find below as a URL, and in > verbatim copy at the end of this email. It provides an > overview over the intended outcome, which design decisions > we had to take, and how our initial plan for the transition > looks like. There are also some issues left open to > discussion. > > https://github.com/quchen/articles/blob/master/monad_fail.md > > Here's a short abstract: > > - - Move `fail` from `Monad` into a new class `MonadFail`. > - - Code using failable patterns will receive a more > restrictive `MonadFail` constraint. Code without this > constraint will be safe to use for all Monads. > - - Transition will take at least two GHC releases. > GHC 7.12 will include the new class, and generate > warnings asking users to make their failable patterns > compliant. > - - Stackage showed an upper bound of less than 500 breaking > code fragments when compiled with the new desugaring. > > For more details, refer to the link or the paste at the end. > > > Let's get going! > > David aka quchen > > > > > > =============================================================== > =============================================================== > =============================================================== > > > > > > `MonadFail` proposal (MFP) > ========================== > > A couple of years ago, we proposed to make `Applicative` a superclass of > `Monad`, which successfully killed the single most ugly thing in Haskell > as of GHC 7.10. > > Now, it's time to tackle the other major issue with `Monad`: `fail` being a > part of it. > > You can contact me as usual via IRC/Freenode as *quchen*, or by email to > *dluposchainsky at the email service of Google*. This file will also be posted > on the ghc-devs@ and libraries@ mailing lists, as well as on Reddit. > > > > Overview > - -------- > > - - **The problem** - reason for the proposal > - - **MonadFail class** - the solution > - - **Discussion** - explaining our design choices > - - **Adapting old code** - how to prepare current code to transition smoothly > - - **Esimating the breakage** - how much stuff we will break (spoiler: not much) > - - **Transitional strategy** - how to break as little as possible while > transitioning > - - **Current status** > > > > > The problem > - ----------- > > Currently, the `<-` symbol is unconditionally desugared as follows: > > ```haskell > do pat <- computation >>> let f pat = more > more >>> f _ = fail "..." > >>> in computation >>= f > ``` > > The problem with this is that `fail` cannot (!) be sensibly implemented for > many monads, for example `State`, `IO`, `Reader`. In those cases it defaults to > `error`. As a consequence, in current Haskell, you can not use > `Monad`-polymorphic code safely, because although it claims to work for all > `Monad`s, it might just crash on you. This kind of implicit non-totality baked > into the class is *terrible*. > > The goal of this proposal is adding the `fail` only when necessary and > reflecting that in the type signature of the `do` block, so that it can be used > safely, and more importantly, is guaranteed not to be used if the type > signature does not say so. > > > > `MonadFail` class > - ----------------- > > To fix this, introduce a new typeclass: > > ```haskell > class Monad m => MonadFail m where > fail :: String -> m a > ``` > > Desugaring can now be changed to produce this constraint when necessary. For > this, we have to decide when a pattern match can not fail; if this is the case, > we can omit inserting the `fail` call. > > The most trivial examples of unfailable patterns are of course those that match > anywhere unconditionally, > > ```haskell > do x <- action >>> let f x = more > more >>> in action >>= f > ``` > > In particular, the programmer can assert any pattern be unfailable by making it > irrefutable using a prefix tilde: > > ```haskell > do ~pat <- action >>> let f ~pat = more > more >>> in action >>= f > ``` > > A class of patterns that are conditionally failable are `newtype`s, and single > constructor `data` types, which are unfailable by themselves, but may fail > if matching on their fields is done with failable paterns. > > ```haskell > data Newtype a = Newtype a > > - -- "x" cannot fail > do Newtype x <- action >>> let f (Newtype x) = more > more >>> in action >>= f > > - -- "Just x" can fail > do Newtype (Just x) <- action >>> let f (Newtype (Just x)) = more > more >>> f _ = fail "..." > >>> in action >>= f > ``` > > `ViewPatterns` are as failable as the pattern the view is matched against. > Patterns like `(Just -> Just x)` should generate a `MonadFail` constraint even > when it's "obvious" from the view's implementation that the pattern will always > match. From an implementor's perspective, this means that only types (and their > constructors) have to be looked at, not arbitrary values (like functions), > which is impossible to do statically in general. > > ```haskell > do (view -> pat) <- action >>> let f (view -> pat) = more > more >>> f _ = fail "..." > >>> in action >>= f > > do (view -> ~pat) <- action >>> let f (view -> ~pat) = more > more >>> in action >>= f > ``` > > A similar issue arises for `PatternSynonyms`, which we cannot inspect during > compilation sufficiently. A pattern synonym will therefore always be considered > failable. > > ```haskell > do PatternSynonym x <- action >>> let f PatternSynonym x = more > more >>> in f _ = fail "..." > >>> in action >>= f > ``` > > > > Discussion > - ---------- > > - - Although for many `MonadPlus` `fail _ = mzero`, a separate `MonadFail` class > should be created instead of just using that. > > - A parser might fail with an error message involving positional > information. Some libraries, like `Binary`, provide `fail` as their > only interface to fail a decoding step. > > - Although `STM` is `MonadPlus`, it uses the default `fail = error`. It > will therefore not get a `MonadFail` instance. > > - - What laws should `fail` follow? **Left zero**, > > ```haskell > ? s f. fail s >>= f ? fail s > ``` > > A call to `fail` should abort the computation. In this sense, `fail` would > become a close relative of `mzero`. It would work well with the common > definition `fail _ = mzero`, and give a simple guideline to the intended > usage and effect of the `MonadFail` class. > > - - Rename `fail`? **No.** Old code might use `fail` explicitly and we might > avoid breaking it, the Report talks about `fail`, and we have a solid > migration strategy that does not require a renaming. > > - - Remove the `String` argument? **No.** The `String` might help error reporting > and debugging. `String` may be ugly, but it's the de facto standard for > simple text in GHC. No high performance string operations are to be > expected with `fail`, so this breaking change would in no way be justified. > Also note that explicit `fail` calls would break if we removed the argument. > > - - How sensitive would existing code be to subtle changes in the strictness > behaviour of `do` notation pattern matching? **It doesn't.** The > implementation does not affect strictness at all, only the desugaring step. > Care must be taken when fixing warnings by making patterns irrefutable using > `~`, as that *does* affect strictness. (Cf. difference between lazy/strict > State) > > - - The `Monad` constraint for `MonadFail` seems unnecessary. Should we drop or > relax it? What other things should be considered? > > - Applicative `do` notation is coming sooner or later, `fail` might be useful > in this more general scenario. Due to the AMP, it is trivial to change > the `MonadFail` superclass to `Applicative` later. (The name will be a bit > misleading, but it's a very small price to pay.) > - The class might be misused for a strange pointed type if left without > any constraint. This is not the intended use at all. > > I think we should keep the `Monad` superclass for three main reasons: > > - We don't want to see `(Monad m, MonadFail m) =>` all over the place. > - The primary intended use of `fail` is for desugaring do-notation anyway. > - Retroactively removing superclasses is easy, but adding them is hard > (see AMP). > > > > > Adapting old code > - ----------------- > > - - Help! My code is broken because of a missing `MonadFail` instance! > > *Here are your options:* > > 1. Write a `MonadFail` instance (and bring it into scope) > > ```haskell > #if !MIN_VERSION_base(4,11,0) > -- Control.Monad.Fail import will become redundant in GHC 7.16+ > import qualified Control.Monad.Fail as Fail > #endif > import Control.Monad > > instance Monad Foo where > (>>=) = <...bind impl...> > -- NB: `return` defaults to `pure` > > #if !MIN_VERSION_base(4,11,0) > -- Monad(fail) will be removed in GHC 7.16+ > fail = Fail.fail > #endif > > instance MonadFail Foo where > fail = <...fail implementation...> > ``` > > 2. Change your pattern to be irrefutable > > 3. Emulate the old behaviour by desugaring the pattern match by hand: > > ```haskell > do Left e <- foobar > stuff > ``` > > becomes > > ```haskell > do x <- foobar > e <- case foobar of > Left e' -> e' > Right r -> error "Pattern match failed" -- Boooo > stuff > ``` > > The point is you'll have to do your dirty laundry yourself now if you > have a value that *you* know will always match, and if you don't handle > the other patterns you'll get incompleteness warnings, and the compiler > won't silently eat those for you. > > - - Help! My code is broken because you removed `fail` from `Monad`, but my class > defines it! > > *Delete that part of the instance definition.* > > > > Esimating the breakage > - ---------------------- > > Using our initial implementation, I compiled stackage-nightly, and grepped the > logs for found "invalid use of fail desugaring". Assuming my implementation > is correct, the number of "missing `MonadFail`" warnings generated is 487. > Note that I filtered out `[]`, `Maybe` and `ReadPrec`, since those can be given > a `MonadFail` instance from within GHC, and no breakage is expected from them. > > The build logs can be found [here][stackage-logs]. Search for "failable > pattern" to find your way to the still pretty raw warnings. > > > > > Transitional strategy > - --------------------- > > The roadmap is similar to the [AMP][amp], the main difference being that since > `MonadFail` does not exist yet, we have to introduce new functionality and then > switch to it. > > * **GHC 7.12 / base-4.9** > > - Add module `Control.Monad.Fail` with new class `MonadFail(fail)` so > people can start writing instances for it. > > `Control.Monad` only re-exports the class `MonadFail`, but not its > `fail` method. > > NB: At this point, `Control.Monad.Fail.fail` clashes with > `Prelude.fail` and `Control.Monad.fail`. > > - *(non-essential)* Add a language extension `-XMonadFail` that > changes desugaring to use `MonadFail(fail)` instead of `Monad(fail)`. > > This has the effect that typechecking will infer a `MonadFail` constraint > for `do` blocks with failable patterns, just as it is planned to do when > the entire thing is done. > > - Warn when a `do`-block that contains a failable pattern is > desugared, but there is no `MonadFail`-instance in scope: "Please add the > instance or change your pattern matching." Add a flag to control whether > this warning appears. > > - Warn when an instance implements the `fail` function (or when `fail` > is imported as a method of `Monad`), as it will be removed from the > `Monad` class in the future. (See also [GHC #10071][trac-10071]) > > 3. GHC 7.14 > > - Switch `-XMonadFail` on by default. > - Remove the desugaring warnings. > > 3. GHC 7.16 > > - Remove `-XMonadFail`, leaving its effects on at all times. > - Remove `fail` from `Monad`. > - Instead, re-export `Control.Monad.Fail.fail` as `Prelude.fail` and > `Control.Monad.fail`. > - `Control.Monad.Fail` is now a redundant module that can be considered > deprecated. > > > > Current status > - -------------- > > - - [ZuriHac 2015 (29.5. - 31.5.)][zurihac]: Franz Thoma (@fmthoma) and me > (David Luposchainsky aka @quchen) started implementing the MFP in GHC. > > - Desugaring to the new `fail` can be controlled via a new langauge > extension, `MonadFailDesugaring`. > - If the language extension is turned off, a warning will be emitted for > code that would break if it was enabled. > - Warnings are emitted for types that *have* a *MonadFail* instance. This > still needs to be fixed. > - The error message are readable, but should be more so. We're still > on this. > - - 2015-06-09: Estimated breakage by compiling Stackage. Smaller than expected. > > > > [amp]: https://github.com/quchen/articles/blob/master/applicative_monad.md > [stackage-logs]: https://www.dropbox.com/s/knz0i979skam4zs/stackage-build.tar.xz?dl=0 > [trac-10071]: https://ghc.haskell.org/trac/ghc/ticket/10071 > [zurihac]: https://wiki.haskell.org/ZuriHac2015 > > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1 > > iQEcBAEBAgAGBQJVd0/yAAoJELrQsaT5WQUshbUH/A3W0itVAk7ao8rtxId5unCJ > 7StriKVkTyLAkkrbRJngM4MHEKiCsoyIgr8kBIwSHgk194GxeP2NCF4ijuBZoDBt > +Uci+6BCBinV8+OzfrfTcJb4+8iw1j+eLWJ/Nz/JDMDNCiyzyC0SMsqGa+ssOz7H > /2mqPkQjQgpHuP5PTRLHKPPIsayCQvTbZR1f14KhuMN2SPDE+WY4rqugu//XuIkN > u1YssIf5l8mEez/1ljaqGL55cTI0UNg2z0iA0bFl/ajHaeQ6mc5BAevWfSohAMW7 > 7PIt13p9NIaMHnikmI+YJszm2IEaXuv47mGgbyDV//nHq3fwWN+naB+1mPX2eSU= > =vPAL > -----END PGP SIGNATURE----- > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From lemming at henning-thielemann.de Tue Jun 9 21:09:28 2015 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Tue, 9 Jun 2015 23:09:28 +0200 (CEST) Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> Message-ID: On Tue, 9 Jun 2015, Evan Laforge wrote: > Definitely +1 here, but if you have an irrefutable pattern: > > ~(Just x) <- action > ... expresison involving x ... > > My understanding is that 'fail' is only called if you evaluate 'x'. I think you would no longer have an (overloadable) "fail", but a (hardwired) "error". From hvr at gnu.org Tue Jun 9 21:09:35 2015 From: hvr at gnu.org (Herbert Valerio Riedel) Date: Tue, 09 Jun 2015 23:09:35 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55774FF2.8020505@gmail.com> (David Luposchainsky's message of "Tue, 09 Jun 2015 22:43:30 +0200") References: <55774FF2.8020505@gmail.com> Message-ID: <87twugbncg.fsf@gnu.org> On 2015-06-09 at 22:43:30 +0200, David Luposchainsky wrote: [...] > https://github.com/quchen/articles/blob/master/monad_fail.md > > Here's a short abstract: > > - Move `fail` from `Monad` into a new class `MonadFail`. [...] +1 obviously :-) From mail at joachim-breitner.de Tue Jun 9 21:23:55 2015 From: mail at joachim-breitner.de (Joachim Breitner) Date: Tue, 09 Jun 2015 23:23:55 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55774FF2.8020505@gmail.com> References: <55774FF2.8020505@gmail.com> Message-ID: <1433885035.9832.0.camel@joachim-breitner.de> Hi, Am Dienstag, den 09.06.2015, 22:43 +0200 schrieb David Luposchainsky: > the subject says it all. After we successfully put `=>` > into Monad, it is time to remove something in return: `fail`. your proposal is solid work and very thorough. Thanks! Greetings, Joachim -- Joachim ?nomeata? Breitner mail at joachim-breitner.de ? http://www.joachim-breitner.de/ Jabber: nomeata at joachim-breitner.de ? GPG-Key: 0xF0FBF51F Debian Developer: nomeata at debian.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: This is a digitally signed message part URL: From lemming at henning-thielemann.de Tue Jun 9 21:56:59 2015 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Tue, 9 Jun 2015 23:56:59 +0200 (CEST) Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55774FF2.8020505@gmail.com> References: <55774FF2.8020505@gmail.com> Message-ID: now some details to the discussion: On Tue, 9 Jun 2015, David Luposchainsky wrote: > https://github.com/quchen/articles/blob/master/monad_fail.md > > Here's a short abstract: > > - - Move `fail` from `Monad` into a new class `MonadFail`. You think about making MonadFail a subclass of Applicative where the name MonadFail becomes misleading - how about naming it Fail instead? > - - Remove the `String` argument? **No.** The `String` might help error reporting > and debugging. `String` may be ugly, but it's the de facto standard for > simple text in GHC. No high performance string operations are to be > expected with `fail`, so this breaking change would in no way be justified. > Also note that explicit `fail` calls would break if we removed the argument. You know that I am concerned with a strict separation of programming errors and exceptions. "fail" is part of the confusion between the two concepts. If "fail" is inserted by the compiler as desugaring of a pattern match then it gets a compiler generated string as argument. This string refers to program details like source locations and constructor names that have no meaning for the program user. They are intended for debugging, they address the programmer. This implies that "fail" indicates a programming error. In contrast to that, in a monad like Maybe we want to convert a mismatching pattern to Nothing. The compiler generated argument to "fail" does not show up in the Nothing result. This usecase is clearly not for debugging but for regular use in a program. We only want to get the exceptional value Nothing. We should clearly decide what "fail" is intended for - for programming errors or for exceptions. I guess that people want to use it in the second sense, e.g. something like "guard" driven by a pattern match in the Maybe or list monad. But then "fail" must not have an argument because what user related information can the compiler add automatically? Instead of removing the String argument from "fail", the compiler could simply call "mzero" instead. If we want to use "fail" for exceptions then it would be also ok for parser libraries to use it for parser failures. Nonetheless they might be better served with an Except-like monad where they can choose more specific types for the exception messages, e.g. parser errors with source location. In summary I think that the cleanest solution would be to phase out "fail" completely in the long run. But using "mzero" instead of "fail" for monadic pattern matches would alter the proposal considerably. Using "mzero" requires a monad with "mplus" and for support of monads with "mzero" but no "mplus" we need to split MonadPlus, too. From ekmett at gmail.com Tue Jun 9 22:19:00 2015 From: ekmett at gmail.com (Edward Kmett) Date: Wed, 10 Jun 2015 00:19:00 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55774FF2.8020505@gmail.com> References: <55774FF2.8020505@gmail.com> Message-ID: +1 from me for both the spirit and the substance of this proposal. We've been talking about this in the abstract for a while now (since ICFP 2013 or so) and as concrete plans go, this strikes me as straightforward and implementable. -Edward On Tue, Jun 9, 2015 at 10:43 PM, David Luposchainsky < dluposchainsky at googlemail.com> wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Hello *, > > the subject says it all. After we successfully put `=>` > into Monad, it is time to remove something in return: `fail`. > > Like with the AMP, I wrote up the proposal in Markdown > format on Github, which you can find below as a URL, and in > verbatim copy at the end of this email. It provides an > overview over the intended outcome, which design decisions > we had to take, and how our initial plan for the transition > looks like. There are also some issues left open to > discussion. > > https://github.com/quchen/articles/blob/master/monad_fail.md > > Here's a short abstract: > > - - Move `fail` from `Monad` into a new class `MonadFail`. > - - Code using failable patterns will receive a more > restrictive `MonadFail` constraint. Code without this > constraint will be safe to use for all Monads. > - - Transition will take at least two GHC releases. > GHC 7.12 will include the new class, and generate > warnings asking users to make their failable patterns > compliant. > - - Stackage showed an upper bound of less than 500 breaking > code fragments when compiled with the new desugaring. > > For more details, refer to the link or the paste at the end. > > > Let's get going! > > David aka quchen > > > > > > =============================================================== > =============================================================== > =============================================================== > > > > > > `MonadFail` proposal (MFP) > ========================== > > A couple of years ago, we proposed to make `Applicative` a superclass of > `Monad`, which successfully killed the single most ugly thing in Haskell > as of GHC 7.10. > > Now, it's time to tackle the other major issue with `Monad`: `fail` being a > part of it. > > You can contact me as usual via IRC/Freenode as *quchen*, or by email to > *dluposchainsky at the email service of Google*. This file will also be > posted > on the ghc-devs@ and libraries@ mailing lists, as well as on Reddit. > > > > Overview > - -------- > > - - **The problem** - reason for the proposal > - - **MonadFail class** - the solution > - - **Discussion** - explaining our design choices > - - **Adapting old code** - how to prepare current code to transition > smoothly > - - **Esimating the breakage** - how much stuff we will break (spoiler: > not much) > - - **Transitional strategy** - how to break as little as possible while > transitioning > - - **Current status** > > > > > The problem > - ----------- > > Currently, the `<-` symbol is unconditionally desugared as follows: > > ```haskell > do pat <- computation >>> let f pat = more > more >>> f _ = fail "..." > >>> in computation >>= f > ``` > > The problem with this is that `fail` cannot (!) be sensibly implemented for > many monads, for example `State`, `IO`, `Reader`. In those cases it > defaults to > `error`. As a consequence, in current Haskell, you can not use > `Monad`-polymorphic code safely, because although it claims to work for all > `Monad`s, it might just crash on you. This kind of implicit non-totality > baked > into the class is *terrible*. > > The goal of this proposal is adding the `fail` only when necessary and > reflecting that in the type signature of the `do` block, so that it can be > used > safely, and more importantly, is guaranteed not to be used if the type > signature does not say so. > > > > `MonadFail` class > - ----------------- > > To fix this, introduce a new typeclass: > > ```haskell > class Monad m => MonadFail m where > fail :: String -> m a > ``` > > Desugaring can now be changed to produce this constraint when necessary. > For > this, we have to decide when a pattern match can not fail; if this is the > case, > we can omit inserting the `fail` call. > > The most trivial examples of unfailable patterns are of course those that > match > anywhere unconditionally, > > ```haskell > do x <- action >>> let f x = more > more >>> in action >>= f > ``` > > In particular, the programmer can assert any pattern be unfailable by > making it > irrefutable using a prefix tilde: > > ```haskell > do ~pat <- action >>> let f ~pat = more > more >>> in action >>= f > ``` > > A class of patterns that are conditionally failable are `newtype`s, and > single > constructor `data` types, which are unfailable by themselves, but may fail > if matching on their fields is done with failable paterns. > > ```haskell > data Newtype a = Newtype a > > - -- "x" cannot fail > do Newtype x <- action >>> let f (Newtype x) = more > more >>> in action >>= f > > - -- "Just x" can fail > do Newtype (Just x) <- action >>> let f (Newtype (Just x)) = more > more >>> f _ = fail "..." > >>> in action >>= f > ``` > > `ViewPatterns` are as failable as the pattern the view is matched against. > Patterns like `(Just -> Just x)` should generate a `MonadFail` constraint > even > when it's "obvious" from the view's implementation that the pattern will > always > match. From an implementor's perspective, this means that only types (and > their > constructors) have to be looked at, not arbitrary values (like functions), > which is impossible to do statically in general. > > ```haskell > do (view -> pat) <- action >>> let f (view -> pat) = more > more >>> f _ = fail "..." > >>> in action >>= f > > do (view -> ~pat) <- action >>> let f (view -> ~pat) = more > more >>> in action >>= f > ``` > > A similar issue arises for `PatternSynonyms`, which we cannot inspect > during > compilation sufficiently. A pattern synonym will therefore always be > considered > failable. > > ```haskell > do PatternSynonym x <- action >>> let f PatternSynonym x = more > more >>> in f _ = fail "..." > >>> in action >>= f > ``` > > > > Discussion > - ---------- > > - - Although for many `MonadPlus` `fail _ = mzero`, a separate `MonadFail` > class > should be created instead of just using that. > > - A parser might fail with an error message involving positional > information. Some libraries, like `Binary`, provide `fail` as their > only interface to fail a decoding step. > > - Although `STM` is `MonadPlus`, it uses the default `fail = error`. It > will therefore not get a `MonadFail` instance. > > - - What laws should `fail` follow? **Left zero**, > > ```haskell > ? s f. fail s >>= f ? fail s > ``` > > A call to `fail` should abort the computation. In this sense, `fail` > would > become a close relative of `mzero`. It would work well with the common > definition `fail _ = mzero`, and give a simple guideline to the intended > usage and effect of the `MonadFail` class. > > - - Rename `fail`? **No.** Old code might use `fail` explicitly and we > might > avoid breaking it, the Report talks about `fail`, and we have a solid > migration strategy that does not require a renaming. > > - - Remove the `String` argument? **No.** The `String` might help error > reporting > and debugging. `String` may be ugly, but it's the de facto standard for > simple text in GHC. No high performance string operations are to be > expected with `fail`, so this breaking change would in no way be > justified. > Also note that explicit `fail` calls would break if we removed the > argument. > > - - How sensitive would existing code be to subtle changes in the > strictness > behaviour of `do` notation pattern matching? **It doesn't.** The > implementation does not affect strictness at all, only the desugaring > step. > Care must be taken when fixing warnings by making patterns irrefutable > using > `~`, as that *does* affect strictness. (Cf. difference between > lazy/strict > State) > > - - The `Monad` constraint for `MonadFail` seems unnecessary. Should we > drop or > relax it? What other things should be considered? > > - Applicative `do` notation is coming sooner or later, `fail` might be > useful > in this more general scenario. Due to the AMP, it is trivial to change > the `MonadFail` superclass to `Applicative` later. (The name will be a > bit > misleading, but it's a very small price to pay.) > - The class might be misused for a strange pointed type if left without > any constraint. This is not the intended use at all. > > I think we should keep the `Monad` superclass for three main reasons: > > - We don't want to see `(Monad m, MonadFail m) =>` all over the place. > - The primary intended use of `fail` is for desugaring do-notation > anyway. > - Retroactively removing superclasses is easy, but adding them is hard > (see AMP). > > > > > Adapting old code > - ----------------- > > - - Help! My code is broken because of a missing `MonadFail` instance! > > *Here are your options:* > > 1. Write a `MonadFail` instance (and bring it into scope) > > ```haskell > #if !MIN_VERSION_base(4,11,0) > -- Control.Monad.Fail import will become redundant in GHC 7.16+ > import qualified Control.Monad.Fail as Fail > #endif > import Control.Monad > > instance Monad Foo where > (>>=) = <...bind impl...> > -- NB: `return` defaults to `pure` > > #if !MIN_VERSION_base(4,11,0) > -- Monad(fail) will be removed in GHC 7.16+ > fail = Fail.fail > #endif > > instance MonadFail Foo where > fail = <...fail implementation...> > ``` > > 2. Change your pattern to be irrefutable > > 3. Emulate the old behaviour by desugaring the pattern match by hand: > > ```haskell > do Left e <- foobar > stuff > ``` > > becomes > > ```haskell > do x <- foobar > e <- case foobar of > Left e' -> e' > Right r -> error "Pattern match failed" -- Boooo > stuff > ``` > > The point is you'll have to do your dirty laundry yourself now if > you > have a value that *you* know will always match, and if you don't > handle > the other patterns you'll get incompleteness warnings, and the > compiler > won't silently eat those for you. > > - - Help! My code is broken because you removed `fail` from `Monad`, but > my class > defines it! > > *Delete that part of the instance definition.* > > > > Esimating the breakage > - ---------------------- > > Using our initial implementation, I compiled stackage-nightly, and grepped > the > logs for found "invalid use of fail desugaring". Assuming my implementation > is correct, the number of "missing `MonadFail`" warnings generated is 487. > Note that I filtered out `[]`, `Maybe` and `ReadPrec`, since those can be > given > a `MonadFail` instance from within GHC, and no breakage is expected from > them. > > The build logs can be found [here][stackage-logs]. Search for "failable > pattern" to find your way to the still pretty raw warnings. > > > > > Transitional strategy > - --------------------- > > The roadmap is similar to the [AMP][amp], the main difference being that > since > `MonadFail` does not exist yet, we have to introduce new functionality and > then > switch to it. > > * **GHC 7.12 / base-4.9** > > - Add module `Control.Monad.Fail` with new class `MonadFail(fail)` so > people can start writing instances for it. > > `Control.Monad` only re-exports the class `MonadFail`, but not its > `fail` method. > > NB: At this point, `Control.Monad.Fail.fail` clashes with > `Prelude.fail` and `Control.Monad.fail`. > > - *(non-essential)* Add a language extension `-XMonadFail` that > changes desugaring to use `MonadFail(fail)` instead of `Monad(fail)`. > > This has the effect that typechecking will infer a `MonadFail` > constraint > for `do` blocks with failable patterns, just as it is planned to do > when > the entire thing is done. > > - Warn when a `do`-block that contains a failable pattern is > desugared, but there is no `MonadFail`-instance in scope: "Please > add the > instance or change your pattern matching." Add a flag to control > whether > this warning appears. > > - Warn when an instance implements the `fail` function (or when `fail` > is imported as a method of `Monad`), as it will be removed from the > `Monad` class in the future. (See also [GHC #10071][trac-10071]) > > 3. GHC 7.14 > > - Switch `-XMonadFail` on by default. > - Remove the desugaring warnings. > > 3. GHC 7.16 > > - Remove `-XMonadFail`, leaving its effects on at all times. > - Remove `fail` from `Monad`. > - Instead, re-export `Control.Monad.Fail.fail` as `Prelude.fail` and > `Control.Monad.fail`. > - `Control.Monad.Fail` is now a redundant module that can be considered > deprecated. > > > > Current status > - -------------- > > - - [ZuriHac 2015 (29.5. - 31.5.)][zurihac]: Franz Thoma (@fmthoma) and me > (David Luposchainsky aka @quchen) started implementing the MFP in GHC. > > - Desugaring to the new `fail` can be controlled via a new langauge > extension, `MonadFailDesugaring`. > - If the language extension is turned off, a warning will be emitted > for > code that would break if it was enabled. > - Warnings are emitted for types that *have* a *MonadFail* instance. > This > still needs to be fixed. > - The error message are readable, but should be more so. We're still > on this. > - - 2015-06-09: Estimated breakage by compiling Stackage. Smaller than > expected. > > > > [amp]: https://github.com/quchen/articles/blob/master/applicative_monad.md > [stackage-logs]: > https://www.dropbox.com/s/knz0i979skam4zs/stackage-build.tar.xz?dl=0 > [trac-10071]: https://ghc.haskell.org/trac/ghc/ticket/10071 > [zurihac]: https://wiki.haskell.org/ZuriHac2015 > > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1 > > iQEcBAEBAgAGBQJVd0/yAAoJELrQsaT5WQUshbUH/A3W0itVAk7ao8rtxId5unCJ > 7StriKVkTyLAkkrbRJngM4MHEKiCsoyIgr8kBIwSHgk194GxeP2NCF4ijuBZoDBt > +Uci+6BCBinV8+OzfrfTcJb4+8iw1j+eLWJ/Nz/JDMDNCiyzyC0SMsqGa+ssOz7H > /2mqPkQjQgpHuP5PTRLHKPPIsayCQvTbZR1f14KhuMN2SPDE+WY4rqugu//XuIkN > u1YssIf5l8mEez/1ljaqGL55cTI0UNg2z0iA0bFl/ajHaeQ6mc5BAevWfSohAMW7 > 7PIt13p9NIaMHnikmI+YJszm2IEaXuv47mGgbyDV//nHq3fwWN+naB+1mPX2eSU= > =vPAL > -----END PGP SIGNATURE----- > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From dluposchainsky at googlemail.com Tue Jun 9 22:21:02 2015 From: dluposchainsky at googlemail.com (David Luposchainsky) Date: Wed, 10 Jun 2015 00:21:02 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> Message-ID: <557766CE.6080202@gmail.com> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 09.06.2015 23:56, Henning Thielemann wrote: > You think about making MonadFail a subclass of Applicative where the name > MonadFail becomes misleading - how about naming it Fail instead? I discussed this with Herbert a bit already. The problem with the name "Fail" is that, if Monad being superclasses of it, hides the fact that there is such a Monad constraint. Instead, the user has to know that Fail happens to be a subclass of Monad, and the Monad part is probably the most important thing in the type, not that there might be some failable pattern somewhere. The name MonadFail solves this issue by containing "Monad" in its name, but the price we pay for that is the awkwardness if we relax the superclass. > We should clearly decide what "fail" is intended for - for programming errors > or for exceptions. I guess that people want to use it in the second sense, > e.g. something like "guard" driven by a pattern match in the Maybe or list > monad. But then "fail" must not have an argument because what user related > information can the compiler add automatically? Instead of removing the > String argument from "fail", the compiler could simply call "mzero" instead. mzero is only available in MonadPlus, which we want to be independent of MonadFail. I don't see a way to accomplish this goal without adding more complicated desugaring rules. > If we want to use "fail" for exceptions then it would be also ok for parser > libraries to use it for parser failures. Nonetheless they might be better > served with an Except-like monad where they can choose more specific types > for the exception messages, e.g. parser errors with source location. But > using "mzero" instead of "fail" for monadic pattern matches would alter the > proposal considerably. Using "mzero" requires a monad with "mplus" and for > support of monads with "mzero" but no "mplus" we need to split MonadPlus, > too. > In summary I think that the cleanest solution would be to phase out "fail" > completely in the long run. If we desugar to anything but simply >>=, we're in a realm of mixups already. Splitting MonadPlus would be quite an effort, and I don't think it would be worth it. I agree that <- should desugar straight to >>=. I have not considered removing the fail desugaring altogether, but I have no idea how much code that would break. The build logs I posted show roughly 100 Maybe/List invocations with failable patterns, but we should also not forget about all the explicit "fail" calls that libraries might do. All things considered, I don't think we're ready for (judging) this, but maybe we can revisit the issue some day and simply deprecate MonadFail; in that sense, we're not going in the wrong direction right now at least. Greetings, David/quchen -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAEBAgAGBQJVd2bNAAoJELrQsaT5WQUsCOMH/0e73pZbXH8r98RpgB4sRU33 ZMZwmkA2wPA5nN996E+cqDmkbCm2qj+O0X3nVkdsM7qi+oRnubnlKWTe+YpPnBsP in1GGwo9eSry7z4Qyw6ZVIeRXufrjQrze+zQH+dBG/O6Qrrze+t9w9YGAWJxDMVa KcBdpd4gRXHZH6y0aXEK1eyroIF1k7XVrK4XVyI+WYu2JjpTHWLjaCBzDVS0+PXU mnTbnA0CrLpGrjCdSiIBeU4ezc57Sn3aNy5gKlZNIchTV81Q/5y5wGE6t/V9wqz4 2fTohs4GWhyjCjLnr6NXWSQDtJN8CUQOadgz9qYnyGOawrKjWQND/ybi3zWE2ZY= =1hmy -----END PGP SIGNATURE----- From johan.tibell at gmail.com Tue Jun 9 22:26:25 2015 From: johan.tibell at gmail.com (Johan Tibell) Date: Wed, 10 Jun 2015 00:26:25 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55774FF2.8020505@gmail.com> References: <55774FF2.8020505@gmail.com> Message-ID: Thanks for putting this together. The proposal says: "As a consequence, in current Haskell, you can not use Monad-polymorphic code safely, because although it claims to work for all Monads, it might just crash on you. This kind of implicit non-totality baked into the class is terrible." Is this actually a problem in practice? Is there any code we can point to that suffers because of the current state of affairs? Could it be included in the proposal? -------------- next part -------------- An HTML attachment was scrubbed... URL: From johnw at newartisans.com Tue Jun 9 22:32:14 2015 From: johnw at newartisans.com (John Wiegley) Date: Tue, 09 Jun 2015 17:32:14 -0500 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55774FF2.8020505@gmail.com> (David Luposchainsky's message of "Tue, 09 Jun 2015 22:43:30 +0200") References: <55774FF2.8020505@gmail.com> Message-ID: >>>>> David Luposchainsky writes: > the subject says it all. After we successfully put `=>` > into Monad, it is time to remove something in return: `fail`. +1 John From dluposchainsky at googlemail.com Tue Jun 9 22:42:12 2015 From: dluposchainsky at googlemail.com (David Luposchainsky) Date: Wed, 10 Jun 2015 00:42:12 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> Message-ID: <55776BC4.3050400@gmail.com> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 10.06.2015 00:26, Johan Tibell wrote: > "As a consequence, in current Haskell, you can not use Monad-polymorphic code > safely, because although it claims to work for all Monads, it might just crash > on you. This kind of implicit non-totality baked into the class is terrible." > > Is this actually a problem in practice? Is there any code we can point to > that suffers because of the current state of affairs? Could it be included in > the proposal? I don't have hard evidence, but the Monad class being partial strikes me as pretty backwards in a language where totality and no implicit failures are important to the programmers. We try our best to advocate not using certain functions like "head" carelessly, but do-notation comes with similar partiality. One concrete example that I know is bimap, but that's something I stumbled upon months ago by accident. Another is that Binary does not have a monomorphic "fail" function and it hurts me a bit to use the Monad-"fail" and write a comment on how that is safe to do in the current context. I think there are two important consequences of MonadFail. First of all, we can all safely write failable patterns if we so desire. Second, the compiler can ensure other people's codebases do not lie to us (knowingly or unknowingly). David/quchen -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAEBAgAGBQJVd2vEAAoJELrQsaT5WQUs+m8IAOWA9Hd52MG1wZ6g6FoOcXd6 x64dRDlilmkVu2IRxHADzip75Oji254yKQ5VY9yMGjYpFajtgf0Q8LrmA0ePTzhg E/oxdm1vyRoJab1C5TfdrzPM/voP+wHi7y2ak1j0hTNky+wETj4MKtJ/Jef225nd APUq05t6nPwzEDCz37RitfbA6/nwwYShaVjNe0tRluPrJuxdBu0+aobFc2lzVL+s J7egnV1kqEOhc7INOhWYsvAJPAJSiY950y/Nmxb2/r5orTfN3tsr98d1zwRxhCmq UNXhUaj5xD7BK2Rn1Zy7VwUv1T8IRLZuOQrlZh3HWz4t1SI0tTu3tdS468s/B1g= =4mEU -----END PGP SIGNATURE----- From tikhon at jelv.is Tue Jun 9 23:02:06 2015 From: tikhon at jelv.is (Tikhon Jelvis) Date: Tue, 9 Jun 2015 16:02:06 -0700 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55776BC4.3050400@gmail.com> References: <55774FF2.8020505@gmail.com> <55776BC4.3050400@gmail.com> Message-ID: +1. This sounds like a good change and, for the most part, doesn't seem all that painful. As far as naming goes, perhaps we could make the name refer to do-notation? Something like DoFail. I mean, that doesn't sound great, but it makes it clear where fail comes in and how it might apply to non-monad type stuff. (ApplicativeDo, for example?) It's also good because nothing about fail is integral to the abstract idea of a monad or even an applicative. It's a function of convenience to make pattern matches in do-notation play out better in cases where it's meaningful. That's true in the other direction too: nothing about a `fail` function is particularly tied to monads or even applicatives. A Monad/Applicative superclass might make the desugaring easier and closer to current behavior, but the idea of a fail :: String -> f a is broadly applicable to fs that aren't necessarily either of those. On Tue, Jun 9, 2015 at 3:42 PM, David Luposchainsky < dluposchainsky at googlemail.com> wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > On 10.06.2015 00:26, Johan Tibell wrote: > > "As a consequence, in current Haskell, you can not use Monad-polymorphic > code > > safely, because although it claims to work for all Monads, it might just > crash > > on you. This kind of implicit non-totality baked into the class is > terrible." > > > > Is this actually a problem in practice? Is there any code we can point to > > that suffers because of the current state of affairs? Could it be > included in > > the proposal? > > I don't have hard evidence, but the Monad class being partial strikes me as > pretty backwards in a language where totality and no implicit failures are > important to the programmers. We try our best to advocate not using certain > functions like "head" carelessly, but do-notation comes with similar > partiality. > > One concrete example that I know is bimap, but that's something I stumbled > upon > months ago by accident. Another is that Binary does not have a monomorphic > "fail" > function and it hurts me a bit to use the Monad-"fail" and write a comment > on how > that is safe to do in the current context. > > I think there are two important consequences of MonadFail. First of all, > we can > all safely write failable patterns if we so desire. Second, the compiler > can > ensure other people's codebases do not lie to us (knowingly or > unknowingly). > > David/quchen > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1 > > iQEcBAEBAgAGBQJVd2vEAAoJELrQsaT5WQUs+m8IAOWA9Hd52MG1wZ6g6FoOcXd6 > x64dRDlilmkVu2IRxHADzip75Oji254yKQ5VY9yMGjYpFajtgf0Q8LrmA0ePTzhg > E/oxdm1vyRoJab1C5TfdrzPM/voP+wHi7y2ak1j0hTNky+wETj4MKtJ/Jef225nd > APUq05t6nPwzEDCz37RitfbA6/nwwYShaVjNe0tRluPrJuxdBu0+aobFc2lzVL+s > J7egnV1kqEOhc7INOhWYsvAJPAJSiY950y/Nmxb2/r5orTfN3tsr98d1zwRxhCmq > UNXhUaj5xD7BK2Rn1Zy7VwUv1T8IRLZuOQrlZh3HWz4t1SI0tTu3tdS468s/B1g= > =4mEU > -----END PGP SIGNATURE----- > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ekmett at gmail.com Wed Jun 10 01:44:40 2015 From: ekmett at gmail.com (Edward Kmett) Date: Wed, 10 Jun 2015 03:44:40 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> Message-ID: I can give a couple of "rather academic" issues that the status quo causes: An example of where this has bit us in the hindquarters in the past is that the old Error class based instance for Monad (Either a) from the mtl incurred a constraint on the entire Monad instance in order to support 'fail'. This ruled out many applications for the Either monad, e.g. apo/gapo are based on the real (Either e) monad, just as para/zygo are based on the "real" ((,) e) comonad. This rather complicated the use of recursion schemes and in fact was what drove me to write what turned into the "either" package in the first place. Now we don't try to support 'fail' at all for that Monad. Under this proposal though, one _could_ add a MonadFail instance that incurred a rather ad hoc constraint on the left hand side of the sum without encumbering the Monad itself. In general you have no way of knowing that you stick to the product-like structure of the Monad in the current ecosystem, because 'fail' is always there, you can get to values in the Monad you couldn't reach with just return and (>>=). Ideally you'd have (forall m. Monad m => m a) being isomorphic to a, this can be useful for ensuring we can plumb user-defined effects through code: http://comonad.com/reader/2011/searching-infinity/ but in Haskell as it exists today you always have to worry about it invoking a call to fail, and having a special form of _distinguishable_ bottom available from that computation so it is really more like `Either String a`. Can you just say "don't do that?" Sure, but it is the moral equivalent of programming with nulls all over your code. -Edward On Wed, Jun 10, 2015 at 12:26 AM, Johan Tibell wrote: > Thanks for putting this together. > > The proposal says: > > "As a consequence, in current Haskell, you can not use Monad-polymorphic > code safely, because although it claims to work for all Monads, it might > just crash on you. This kind of implicit non-totality baked into the class > is terrible." > > Is this actually a problem in practice? Is there any code we can point to > that suffers because of the current state of affairs? Could it be included > in the proposal? > > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From felipe.lessa at gmail.com Wed Jun 10 02:01:51 2015 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Tue, 09 Jun 2015 23:01:51 -0300 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> Message-ID: <55779A8F.4010005@gmail.com> +1, even more so after the not-so-academic issues pointed out by Edward. Cheers, -- Felipe. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: From david.feuer at gmail.com Wed Jun 10 02:23:18 2015 From: david.feuer at gmail.com (David Feuer) Date: Tue, 9 Jun 2015 22:23:18 -0400 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55779A8F.4010005@gmail.com> References: <55774FF2.8020505@gmail.com> <55779A8F.4010005@gmail.com> Message-ID: +1 to taking fail out of Monad. +0 to any particular failure class; the issues seem a bit complex, and I haven't studied them closely enough to have an opinion. On Tue, Jun 9, 2015 at 10:01 PM, Felipe Lessa wrote: > +1, even more so after the not-so-academic issues pointed out by Edward. > > Cheers, > > -- > Felipe. > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > From spam at scientician.net Wed Jun 10 03:19:54 2015 From: spam at scientician.net (Bardur Arantsson) Date: Wed, 10 Jun 2015 05:19:54 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55774FF2.8020505@gmail.com> References: <55774FF2.8020505@gmail.com> Message-ID: On 06/09/2015 10:43 PM, David Luposchainsky wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > +1 From carter.schonwald at gmail.com Wed Jun 10 04:27:12 2015 From: carter.schonwald at gmail.com (Carter Schonwald) Date: Wed, 10 Jun 2015 00:27:12 -0400 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> Message-ID: i'll add my token +1 to the land slide On Tue, Jun 9, 2015 at 11:19 PM, Bardur Arantsson wrote: > On 06/09/2015 10:43 PM, David Luposchainsky wrote: > > -----BEGIN PGP SIGNED MESSAGE----- > > Hash: SHA1 > > > > +1 > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From nikita.y.volkov at gmail.com Wed Jun 10 06:07:01 2015 From: nikita.y.volkov at gmail.com (Nikita Volkov) Date: Wed, 10 Jun 2015 09:07:01 +0300 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> Message-ID: +1 Been dreaming about this for so long! 2015-06-10 7:27 GMT+03:00 Carter Schonwald : > i'll add my token +1 to the land slide > > On Tue, Jun 9, 2015 at 11:19 PM, Bardur Arantsson > wrote: > >> On 06/09/2015 10:43 PM, David Luposchainsky wrote: >> > -----BEGIN PGP SIGNED MESSAGE----- >> > Hash: SHA1 >> > >> >> +1 >> >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hvr at gnu.org Wed Jun 10 06:46:56 2015 From: hvr at gnu.org (Herbert Valerio Riedel) Date: Wed, 10 Jun 2015 08:46:56 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: (Henning Thielemann's message of "Tue, 9 Jun 2015 23:56:59 +0200 (CEST)") References: <55774FF2.8020505@gmail.com> Message-ID: <87wpzc12n3.fsf@gnu.org> On 2015-06-09 at 23:56:59 +0200, Henning Thielemann wrote: [...] > You think about making MonadFail a subclass of Applicative where the > name MonadFail becomes misleading - how about naming it Fail instead? 'Fail' would be a good name, if it became an independent class (w/o a superclass to either 'Applicative' or 'Monad'). But the cost for that is having to use `(Fail m, Monad m) =>` Or rely on e.g. constraint synonyms, via e.g. {-# LANGUAGE ConstraintKinds #-} type MonadFail m = (Fail m, Monad m) type ApplicativeFail m = (Fail m, Applicative m) for convenience. I've also heard the suggestion 'FailDo', which could make sense if it became a superclass of Applicative (but then we'd still have to use '(FailDo m, Monad m)' or a constraint-synonym for the majority of cases, where 'fail' is used in a 'Monad' context) Otoh, the reason I suggested to just go w/ 'MonadFail' to keep it simple was that I doubted that that 'fail' in a '-XApplicativeDo' made much sense. But maybe it does make sense? I.e. while 'fail' has laws w/ 'Monad', what would be the respective laws for 'fail' in an 'Applicative' context? Cheers, hvr From malcolm.wallace at me.com Wed Jun 10 07:27:54 2015 From: malcolm.wallace at me.com (Malcolm Wallace) Date: Wed, 10 Jun 2015 08:27:54 +0100 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> Message-ID: <5EABF3D5-7923-4C37-8AC8-FDCCD0FF8C3D@me.com> I'm a +1 on this proposal as well. In our private Haskell compiler at work, we have had separate Monad and MonadFail classes since 2010, and it is clearly the more principled way to handle partiality: make it visible in the inferred types. I found that there were very few instances when porting Hackage libraries to our compiler that we came across a need to change type signatures because of MonadFail, and making the change was in all cases easy anyway. Regards, Malcolm On 9 Jun 2015, at 23:19, Edward Kmett wrote: > +1 from me for both the spirit and the substance of this proposal. We've been talking about this in the abstract for a while now (since ICFP 2013 or so) and as concrete plans go, this strikes me as straightforward and implementable. > > -Edward > > On Tue, Jun 9, 2015 at 10:43 PM, David Luposchainsky wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Hello *, > > the subject says it all. After we successfully put `=>` > into Monad, it is time to remove something in return: `fail`. > > Like with the AMP, I wrote up the proposal in Markdown > format on Github, which you can find below as a URL, and in > verbatim copy at the end of this email. It provides an > overview over the intended outcome, which design decisions > we had to take, and how our initial plan for the transition > looks like. There are also some issues left open to > discussion. > > https://github.com/quchen/articles/blob/master/monad_fail.md > > Here's a short abstract: > > - - Move `fail` from `Monad` into a new class `MonadFail`. > - - Code using failable patterns will receive a more > restrictive `MonadFail` constraint. Code without this > constraint will be safe to use for all Monads. > - - Transition will take at least two GHC releases. > GHC 7.12 will include the new class, and generate > warnings asking users to make their failable patterns > compliant. > - - Stackage showed an upper bound of less than 500 breaking > code fragments when compiled with the new desugaring. > > For more details, refer to the link or the paste at the end. > > > Let's get going! > > David aka quchen > > > > > > =============================================================== > =============================================================== > =============================================================== > > > > > > `MonadFail` proposal (MFP) > ========================== > > A couple of years ago, we proposed to make `Applicative` a superclass of > `Monad`, which successfully killed the single most ugly thing in Haskell > as of GHC 7.10. > > Now, it's time to tackle the other major issue with `Monad`: `fail` being a > part of it. > > You can contact me as usual via IRC/Freenode as *quchen*, or by email to > *dluposchainsky at the email service of Google*. This file will also be posted > on the ghc-devs@ and libraries@ mailing lists, as well as on Reddit. > > > > Overview > - -------- > > - - **The problem** - reason for the proposal > - - **MonadFail class** - the solution > - - **Discussion** - explaining our design choices > - - **Adapting old code** - how to prepare current code to transition smoothly > - - **Esimating the breakage** - how much stuff we will break (spoiler: not much) > - - **Transitional strategy** - how to break as little as possible while > transitioning > - - **Current status** > > > > > The problem > - ----------- > > Currently, the `<-` symbol is unconditionally desugared as follows: > > ```haskell > do pat <- computation >>> let f pat = more > more >>> f _ = fail "..." > >>> in computation >>= f > ``` > > The problem with this is that `fail` cannot (!) be sensibly implemented for > many monads, for example `State`, `IO`, `Reader`. In those cases it defaults to > `error`. As a consequence, in current Haskell, you can not use > `Monad`-polymorphic code safely, because although it claims to work for all > `Monad`s, it might just crash on you. This kind of implicit non-totality baked > into the class is *terrible*. > > The goal of this proposal is adding the `fail` only when necessary and > reflecting that in the type signature of the `do` block, so that it can be used > safely, and more importantly, is guaranteed not to be used if the type > signature does not say so. > > > > `MonadFail` class > - ----------------- > > To fix this, introduce a new typeclass: > > ```haskell > class Monad m => MonadFail m where > fail :: String -> m a > ``` > > Desugaring can now be changed to produce this constraint when necessary. For > this, we have to decide when a pattern match can not fail; if this is the case, > we can omit inserting the `fail` call. > > The most trivial examples of unfailable patterns are of course those that match > anywhere unconditionally, > > ```haskell > do x <- action >>> let f x = more > more >>> in action >>= f > ``` > > In particular, the programmer can assert any pattern be unfailable by making it > irrefutable using a prefix tilde: > > ```haskell > do ~pat <- action >>> let f ~pat = more > more >>> in action >>= f > ``` > > A class of patterns that are conditionally failable are `newtype`s, and single > constructor `data` types, which are unfailable by themselves, but may fail > if matching on their fields is done with failable paterns. > > ```haskell > data Newtype a = Newtype a > > - -- "x" cannot fail > do Newtype x <- action >>> let f (Newtype x) = more > more >>> in action >>= f > > - -- "Just x" can fail > do Newtype (Just x) <- action >>> let f (Newtype (Just x)) = more > more >>> f _ = fail "..." > >>> in action >>= f > ``` > > `ViewPatterns` are as failable as the pattern the view is matched against. > Patterns like `(Just -> Just x)` should generate a `MonadFail` constraint even > when it's "obvious" from the view's implementation that the pattern will always > match. From an implementor's perspective, this means that only types (and their > constructors) have to be looked at, not arbitrary values (like functions), > which is impossible to do statically in general. > > ```haskell > do (view -> pat) <- action >>> let f (view -> pat) = more > more >>> f _ = fail "..." > >>> in action >>= f > > do (view -> ~pat) <- action >>> let f (view -> ~pat) = more > more >>> in action >>= f > ``` > > A similar issue arises for `PatternSynonyms`, which we cannot inspect during > compilation sufficiently. A pattern synonym will therefore always be considered > failable. > > ```haskell > do PatternSynonym x <- action >>> let f PatternSynonym x = more > more >>> in f _ = fail "..." > >>> in action >>= f > ``` > > > > Discussion > - ---------- > > - - Although for many `MonadPlus` `fail _ = mzero`, a separate `MonadFail` class > should be created instead of just using that. > > - A parser might fail with an error message involving positional > information. Some libraries, like `Binary`, provide `fail` as their > only interface to fail a decoding step. > > - Although `STM` is `MonadPlus`, it uses the default `fail = error`. It > will therefore not get a `MonadFail` instance. > > - - What laws should `fail` follow? **Left zero**, > > ```haskell > ? s f. fail s >>= f ? fail s > ``` > > A call to `fail` should abort the computation. In this sense, `fail` would > become a close relative of `mzero`. It would work well with the common > definition `fail _ = mzero`, and give a simple guideline to the intended > usage and effect of the `MonadFail` class. > > - - Rename `fail`? **No.** Old code might use `fail` explicitly and we might > avoid breaking it, the Report talks about `fail`, and we have a solid > migration strategy that does not require a renaming. > > - - Remove the `String` argument? **No.** The `String` might help error reporting > and debugging. `String` may be ugly, but it's the de facto standard for > simple text in GHC. No high performance string operations are to be > expected with `fail`, so this breaking change would in no way be justified. > Also note that explicit `fail` calls would break if we removed the argument. > > - - How sensitive would existing code be to subtle changes in the strictness > behaviour of `do` notation pattern matching? **It doesn't.** The > implementation does not affect strictness at all, only the desugaring step. > Care must be taken when fixing warnings by making patterns irrefutable using > `~`, as that *does* affect strictness. (Cf. difference between lazy/strict > State) > > - - The `Monad` constraint for `MonadFail` seems unnecessary. Should we drop or > relax it? What other things should be considered? > > - Applicative `do` notation is coming sooner or later, `fail` might be useful > in this more general scenario. Due to the AMP, it is trivial to change > the `MonadFail` superclass to `Applicative` later. (The name will be a bit > misleading, but it's a very small price to pay.) > - The class might be misused for a strange pointed type if left without > any constraint. This is not the intended use at all. > > I think we should keep the `Monad` superclass for three main reasons: > > - We don't want to see `(Monad m, MonadFail m) =>` all over the place. > - The primary intended use of `fail` is for desugaring do-notation anyway. > - Retroactively removing superclasses is easy, but adding them is hard > (see AMP). > > > > > Adapting old code > - ----------------- > > - - Help! My code is broken because of a missing `MonadFail` instance! > > *Here are your options:* > > 1. Write a `MonadFail` instance (and bring it into scope) > > ```haskell > #if !MIN_VERSION_base(4,11,0) > -- Control.Monad.Fail import will become redundant in GHC 7.16+ > import qualified Control.Monad.Fail as Fail > #endif > import Control.Monad > > instance Monad Foo where > (>>=) = <...bind impl...> > -- NB: `return` defaults to `pure` > > #if !MIN_VERSION_base(4,11,0) > -- Monad(fail) will be removed in GHC 7.16+ > fail = Fail.fail > #endif > > instance MonadFail Foo where > fail = <...fail implementation...> > ``` > > 2. Change your pattern to be irrefutable > > 3. Emulate the old behaviour by desugaring the pattern match by hand: > > ```haskell > do Left e <- foobar > stuff > ``` > > becomes > > ```haskell > do x <- foobar > e <- case foobar of > Left e' -> e' > Right r -> error "Pattern match failed" -- Boooo > stuff > ``` > > The point is you'll have to do your dirty laundry yourself now if you > have a value that *you* know will always match, and if you don't handle > the other patterns you'll get incompleteness warnings, and the compiler > won't silently eat those for you. > > - - Help! My code is broken because you removed `fail` from `Monad`, but my class > defines it! > > *Delete that part of the instance definition.* > > > > Esimating the breakage > - ---------------------- > > Using our initial implementation, I compiled stackage-nightly, and grepped the > logs for found "invalid use of fail desugaring". Assuming my implementation > is correct, the number of "missing `MonadFail`" warnings generated is 487. > Note that I filtered out `[]`, `Maybe` and `ReadPrec`, since those can be given > a `MonadFail` instance from within GHC, and no breakage is expected from them. > > The build logs can be found [here][stackage-logs]. Search for "failable > pattern" to find your way to the still pretty raw warnings. > > > > > Transitional strategy > - --------------------- > > The roadmap is similar to the [AMP][amp], the main difference being that since > `MonadFail` does not exist yet, we have to introduce new functionality and then > switch to it. > > * **GHC 7.12 / base-4.9** > > - Add module `Control.Monad.Fail` with new class `MonadFail(fail)` so > people can start writing instances for it. > > `Control.Monad` only re-exports the class `MonadFail`, but not its > `fail` method. > > NB: At this point, `Control.Monad.Fail.fail` clashes with > `Prelude.fail` and `Control.Monad.fail`. > > - *(non-essential)* Add a language extension `-XMonadFail` that > changes desugaring to use `MonadFail(fail)` instead of `Monad(fail)`. > > This has the effect that typechecking will infer a `MonadFail` constraint > for `do` blocks with failable patterns, just as it is planned to do when > the entire thing is done. > > - Warn when a `do`-block that contains a failable pattern is > desugared, but there is no `MonadFail`-instance in scope: "Please add the > instance or change your pattern matching." Add a flag to control whether > this warning appears. > > - Warn when an instance implements the `fail` function (or when `fail` > is imported as a method of `Monad`), as it will be removed from the > `Monad` class in the future. (See also [GHC #10071][trac-10071]) > > 3. GHC 7.14 > > - Switch `-XMonadFail` on by default. > - Remove the desugaring warnings. > > 3. GHC 7.16 > > - Remove `-XMonadFail`, leaving its effects on at all times. > - Remove `fail` from `Monad`. > - Instead, re-export `Control.Monad.Fail.fail` as `Prelude.fail` and > `Control.Monad.fail`. > - `Control.Monad.Fail` is now a redundant module that can be considered > deprecated. > > > > Current status > - -------------- > > - - [ZuriHac 2015 (29.5. - 31.5.)][zurihac]: Franz Thoma (@fmthoma) and me > (David Luposchainsky aka @quchen) started implementing the MFP in GHC. > > - Desugaring to the new `fail` can be controlled via a new langauge > extension, `MonadFailDesugaring`. > - If the language extension is turned off, a warning will be emitted for > code that would break if it was enabled. > - Warnings are emitted for types that *have* a *MonadFail* instance. This > still needs to be fixed. > - The error message are readable, but should be more so. We're still > on this. > - - 2015-06-09: Estimated breakage by compiling Stackage. Smaller than expected. > > > > [amp]: https://github.com/quchen/articles/blob/master/applicative_monad.md > [stackage-logs]: https://www.dropbox.com/s/knz0i979skam4zs/stackage-build.tar.xz?dl=0 > [trac-10071]: https://ghc.haskell.org/trac/ghc/ticket/10071 > [zurihac]: https://wiki.haskell.org/ZuriHac2015 > > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1 > > iQEcBAEBAgAGBQJVd0/yAAoJELrQsaT5WQUshbUH/A3W0itVAk7ao8rtxId5unCJ > 7StriKVkTyLAkkrbRJngM4MHEKiCsoyIgr8kBIwSHgk194GxeP2NCF4ijuBZoDBt > +Uci+6BCBinV8+OzfrfTcJb4+8iw1j+eLWJ/Nz/JDMDNCiyzyC0SMsqGa+ssOz7H > /2mqPkQjQgpHuP5PTRLHKPPIsayCQvTbZR1f14KhuMN2SPDE+WY4rqugu//XuIkN > u1YssIf5l8mEez/1ljaqGL55cTI0UNg2z0iA0bFl/ajHaeQ6mc5BAevWfSohAMW7 > 7PIt13p9NIaMHnikmI+YJszm2IEaXuv47mGgbyDV//nHq3fwWN+naB+1mPX2eSU= > =vPAL > -----END PGP SIGNATURE----- > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From roma at ro-che.info Wed Jun 10 08:11:43 2015 From: roma at ro-che.info (Roman Cheplyaka) Date: Wed, 10 Jun 2015 11:11:43 +0300 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55774FF2.8020505@gmail.com> References: <55774FF2.8020505@gmail.com> Message-ID: <5577F13F.3080001@ro-che.info> +1 -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: From hvr at gnu.org Wed Jun 10 10:34:50 2015 From: hvr at gnu.org (Herbert Valerio Riedel) Date: Wed, 10 Jun 2015 12:34:50 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55776BC4.3050400@gmail.com> (David Luposchainsky's message of "Wed, 10 Jun 2015 00:42:12 +0200") References: <55774FF2.8020505@gmail.com> <55776BC4.3050400@gmail.com> Message-ID: <874mmf26np.fsf@gnu.org> On 2015-06-10 at 00:42:12 +0200, David Luposchainsky wrote: [...] > I think there are two important consequences of MonadFail. First of all, we can > all safely write failable patterns if we so desire. Second, the compiler can > ensure other people's codebases do not lie to us (knowingly or unknowingly). ...as a data-point, when turning on MonadFail during testing, I've seen at least one place in GHC's own code-base that directly calls 'fail' for a Monad instance which did *not* have its 'fail' method overridden. Moreover, I've seen at least one (other) case, where failable pattern matches occurred (intentionally or not[1]), but the respective Monad instance didn't have the 'fail' method overridden either. [1]: Failable patterns can in theory snuck in non-intentionally, e.g. they can be introduced during refactoring if e.g. a single-constructor type gets added new constructors. If the context was previously constraint to a 'Monad', after the refactoring the typechecker would point out that now there's a failable pattern not accounted for. From ekmett at gmail.com Wed Jun 10 10:55:10 2015 From: ekmett at gmail.com (Edward Kmett) Date: Wed, 10 Jun 2015 12:55:10 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <87wpzc12n3.fsf@gnu.org> References: <55774FF2.8020505@gmail.com> <87wpzc12n3.fsf@gnu.org> Message-ID: On Wed, Jun 10, 2015 at 8:46 AM, Herbert Valerio Riedel wrote: > {-# LANGUAGE ConstraintKinds #-} > type MonadFail m = (Fail m, Monad m) > type ApplicativeFail m = (Fail m, Applicative m) If we're forced into a situation where we need to factor it into a separate class and build aliases like this, then switching to undecidable instances and encoding that as class (Monad m, Fail m) => MonadFail m instance (Monad m, Fail m) => MonadFail m etc. would be much better than using the ConstraintKinds extension and a type alias. The type synonym you gave doesn't let you use "MonadFail" as a first class inhabitant of kind (* -> *) -> Constraint, you can only pass it once it has been applied to an `m`. This rules out many useful type level tricks. -Edward > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From bertram.felgenhauer at googlemail.com Wed Jun 10 11:19:36 2015 From: bertram.felgenhauer at googlemail.com (Bertram Felgenhauer) Date: Wed, 10 Jun 2015 13:19:36 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> Message-ID: <20150610111936.GB2061@24f89f8c-e6a1-4e75-85ee-bb8a3743bb9f> Henning Thielemann wrote: > We should clearly decide what "fail" is intended for - for programming > errors or for exceptions. I guess that people want to use it in the second > sense, e.g. something like "guard" driven by a pattern match in the Maybe or > list monad. But then "fail" must not have an argument because what user > related information can the compiler add automatically? Instead of removing > the String argument from "fail", the compiler could simply call "mzero" > instead. And then there's ErrorT, which does actually make the information available to the user. I agree that the current situation is a bit messy, but at the same time I believe the choices made for fail make sense and are very convenient. Perhaps more importantly, I see no sane way to "clean up the mess" even if that's desired. We've already had that experience on a small scale, when the Error class constraint was removed from the Monad instance for Either e. The problem with this change was that code kept compiling, but started to raise runtime errors where previously there hadn't been any. Tracking down these uses of Either and replacing them by ErrorT was quite tedious. To summarize, I believe we should keep the current semantics of fail, even if it's moved to a new class. Cheers, Bertram From johan.tibell at gmail.com Wed Jun 10 11:22:43 2015 From: johan.tibell at gmail.com (Johan Tibell) Date: Wed, 10 Jun 2015 13:22:43 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55776BC4.3050400@gmail.com> References: <55774FF2.8020505@gmail.com> <55776BC4.3050400@gmail.com> Message-ID: On Wed, Jun 10, 2015 at 12:42 AM, David Luposchainsky < dluposchainsky at googlemail.com> wrote: > I think there are two important consequences of MonadFail. First of all, > we can > all safely write failable patterns if we so desire. Second, the compiler > can > ensure other people's codebases do not lie to us (knowingly or > unknowingly). > The second is a bit overstated I think. Any function you call can still have partial pattern matches in all the other places Haskell allows them and you wouldn't know from the type. -------------- next part -------------- An HTML attachment was scrubbed... URL: From ganesh at earth.li Wed Jun 10 11:58:09 2015 From: ganesh at earth.li (Ganesh Sittampalam) Date: Wed, 10 Jun 2015 12:58:09 +0100 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> Message-ID: <55782651.9010105@earth.li> On 09/06/2015 23:26, Johan Tibell wrote: > Thanks for putting this together. > > The proposal says: > > "As a consequence, in current Haskell, you can not use Monad-polymorphic > code safely, because although it claims to work for all Monads, it might > just crash on you. This kind of implicit non-totality baked into the > class is terrible." > > Is this actually a problem in practice? Is there any code we can point > to that suffers because of the current state of affairs? Could it be > included in the proposal? Here's a concrete example: https://mail.haskell.org/pipermail/libraries/2015-March/025166.html I needed to change some code that used a monad with an explicit fail to use one without, and I couldn't get the compiler to tell me if it was using partial pattern matches or not. If it had been then the refactoring would have caused a nasty behaviour change. Ganesh From blamario at ciktel.net Wed Jun 10 12:32:57 2015 From: blamario at ciktel.net (=?UTF-8?B?TWFyaW8gQmxhxb5ldmnEhw==?=) Date: Wed, 10 Jun 2015 08:32:57 -0400 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55774FF2.8020505@gmail.com> References: <55774FF2.8020505@gmail.com> Message-ID: <55782E79.5090109@ciktel.net> +1 from me. A minor nitpick: the proposal should clarify which of the existing instances of Monad from base get a MonadFail instance. My understanding is that none of them would define fail = error, but that has not been made explicit. From johan.tibell at gmail.com Wed Jun 10 13:00:35 2015 From: johan.tibell at gmail.com (Johan Tibell) Date: Wed, 10 Jun 2015 15:00:35 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55782E79.5090109@ciktel.net> References: <55774FF2.8020505@gmail.com> <55782E79.5090109@ciktel.net> Message-ID: An idea. Could the new desugaring be the same as for normal functions with a missing case? Code that uses fail would have to add the constraint still, but code that really didn't want to use fail would 1) get a warning about an incomplete pattern match and 2) get a runtime error for the failed pattern match produced by GHC. Is there anything I'm not thinking of here why this wouldn't work? -------------- next part -------------- An HTML attachment was scrubbed... URL: From hesselink at gmail.com Wed Jun 10 13:40:23 2015 From: hesselink at gmail.com (Erik Hesselink) Date: Wed, 10 Jun 2015 15:40:23 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> <55782E79.5090109@ciktel.net> Message-ID: That would make it impossible to have a failed pattern match become an automatic 'fail' with a MonadFail constraint, right? I think that's a pretty nice feature, actually. But perhaps I misunderstand your idea. Erik On Wed, Jun 10, 2015 at 3:00 PM, Johan Tibell wrote: > An idea. Could the new desugaring be the same as for normal functions with a > missing case? Code that uses fail would have to add the constraint still, > but code that really didn't want to use fail would 1) get a warning about an > incomplete pattern match and 2) get a runtime error for the failed pattern > match produced by GHC. Is there anything I'm not thinking of here why this > wouldn't work? > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > From ekmett at gmail.com Wed Jun 10 13:59:33 2015 From: ekmett at gmail.com (Edward Kmett) Date: Wed, 10 Jun 2015 15:59:33 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> <55782E79.5090109@ciktel.net> Message-ID: I don't quite follow how that would work in a way that doesn't violate the open world assumption. If you pattern match in a do-binding and don't have a MonadFail instance in scope you'd get a different desugaring? This would make the presence / absence of an instance change code generation. Adding instances shouldn't change generated code. -Edward On Wed, Jun 10, 2015 at 3:00 PM, Johan Tibell wrote: > An idea. Could the new desugaring be the same as for normal functions with > a missing case? Code that uses fail would have to add the constraint still, > but code that really didn't want to use fail would 1) get a warning about > an incomplete pattern match and 2) get a runtime error for the failed > pattern match produced by GHC. Is there anything I'm not thinking of here > why this wouldn't work? > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.feuer at gmail.com Wed Jun 10 14:19:05 2015 From: david.feuer at gmail.com (David Feuer) Date: Wed, 10 Jun 2015 10:19:05 -0400 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55782E79.5090109@ciktel.net> References: <55774FF2.8020505@gmail.com> <55782E79.5090109@ciktel.net> Message-ID: Here's a crazy question: would a version of MonadError without the fundep do the trick? class Monad m => MonadFail e m where fail :: e -> m a instance MonadFail a [] where fail = const [] instance (a ~ e) => MonadFail e (Either a) where fail = Left instance MonadFail SomeException IO where fail = throwIO instance MonadFail IOException IO where fail = throwIO ... instance MonadFail String IO where fail = throwIO . userError On Wed, Jun 10, 2015 at 8:32 AM, Mario Bla?evi? wrote: > +1 from me. > > A minor nitpick: the proposal should clarify which of the existing > instances of Monad from base get a MonadFail instance. My understanding is > that none of them would define fail = error, but that has not been made > explicit. > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From ekmett at gmail.com Wed Jun 10 14:55:30 2015 From: ekmett at gmail.com (Edward Kmett) Date: Wed, 10 Jun 2015 16:55:30 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> <55782E79.5090109@ciktel.net> Message-ID: This would require you to add MPTCs to the language standard, which means standardizing how they work. Any solution involving SomeException or any of its variants is going to drag in GADTs, Typeable, higher rank types. ... and it would drag them inexorably into the Prelude, not just base. Compared to a simple class Monad m => MonadFail m where fail :: String -> m a that is a very hard sell! On the other hand, I do think what we could do is add more information about pattern match failures by adding another member to the class class Monad m => MonadFail m where patternMatchFailure :: Location -> String -> whatever else you like -> m a patternMatchFailure l s ... = fail (code to generate the string we generate in the compiler using just the parts we're passed) fail :: String -> m a Then the existing 'fail' desugaring could be done in terms of this additional member and its default implementation. This remains entirely in the "small" subset of Haskell that is well behaved. It doesn't change if we go and radically redefine the way the exception hierarchy works, and it doesn't require a ton of standardization effort. Now if we want to make the fail instance for IO or other MonadThrow instances package up the patternMatchFailure and throw it in an exception we have the freedom, but we're avoid locking ourselves in to actually trying to figure out how to standardize all of the particulars of the exception machinery into the language standard. -Edward On Wed, Jun 10, 2015 at 4:19 PM, David Feuer wrote: > Here's a crazy question: would a version of MonadError without the > fundep do the trick? > > class Monad m => MonadFail e m where > fail :: e -> m a > > instance MonadFail a [] where > fail = const [] > > instance (a ~ e) => MonadFail e (Either a) where > fail = Left > > instance MonadFail SomeException IO where > fail = throwIO > instance MonadFail IOException IO where > fail = throwIO > ... > instance MonadFail String IO where > fail = throwIO . userError > > On Wed, Jun 10, 2015 at 8:32 AM, Mario Bla?evi? > wrote: > > +1 from me. > > > > A minor nitpick: the proposal should clarify which of the existing > > instances of Monad from base get a MonadFail instance. My understanding > is > > that none of them would define fail = error, but that has not been made > > explicit. > > > > > > _______________________________________________ > > Libraries mailing list > > Libraries at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From simonpj at microsoft.com Wed Jun 10 15:33:02 2015 From: simonpj at microsoft.com (Simon Peyton Jones) Date: Wed, 10 Jun 2015 15:33:02 +0000 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> <55782E79.5090109@ciktel.net> Message-ID: <7cd7b8f2ddf8484fb5071ba98d1d12f6@DB4PR30MB030.064d.mgd.msft.net> But what is the inferred type for f x = do { [v] <- x, return v } I think the proposal is to have a MonadFail constraint. As far as I understand what you are saying, it would make sense for f :: Monad m => m [a] -> m a g x = do { [v] <- x; return v } (with failure giving a runtime error). From: Libraries [mailto:libraries-bounces at haskell.org] On Behalf Of Johan Tibell Sent: 10 June 2015 14:01 To: Mario Bla?evi? Cc: Haskell Libraries Subject: Re: MonadFail proposal (MFP): Moving fail out of Monad An idea. Could the new desugaring be the same as for normal functions with a missing case? Code that uses fail would have to add the constraint still, but code that really didn't want to use fail would 1) get a warning about an incomplete pattern match and 2) get a runtime error for the failed pattern match produced by GHC. Is there anything I'm not thinking of here why this wouldn't work? -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.feuer at gmail.com Wed Jun 10 15:44:15 2015 From: david.feuer at gmail.com (David Feuer) Date: Wed, 10 Jun 2015 11:44:15 -0400 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> <55782E79.5090109@ciktel.net> Message-ID: My main concern, I suppose, is that I don't see a way (without extensions) to deal with even the most basic interesting failure monad: Either e. It therefore seems really only to be suitable for pattern match failure and user-generated IOErrors, which don't really strike me as terribly natural bedfellows. On Wed, Jun 10, 2015 at 10:55 AM, Edward Kmett wrote: > This would require you to add MPTCs to the language standard, which means > standardizing how they work. > > Any solution involving SomeException or any of its variants is going to drag > in GADTs, Typeable, higher rank types. > > ... and it would drag them inexorably into the Prelude, not just base. > > Compared to a simple > > class Monad m => MonadFail m where > fail :: String -> m a > > that is a very hard sell! > > On the other hand, I do think what we could do is add more information about > pattern match failures by adding another member to the class > > class Monad m => MonadFail m where > patternMatchFailure :: Location -> String -> whatever else you like -> m a > patternMatchFailure l s ... = fail (code to generate the string we > generate in the compiler using just the parts we're passed) > > fail :: String -> m a > > Then the existing 'fail' desugaring could be done in terms of this > additional member and its default implementation. > > This remains entirely in the "small" subset of Haskell that is well behaved. > It doesn't change if we go and radically redefine the way the exception > hierarchy works, and it doesn't require a ton of standardization effort. > > Now if we want to make the fail instance for IO or other MonadThrow > instances package up the patternMatchFailure and throw it in an exception we > have the freedom, but we're avoid locking ourselves in to actually trying to > figure out how to standardize all of the particulars of the exception > machinery into the language standard. > > -Edward > > On Wed, Jun 10, 2015 at 4:19 PM, David Feuer wrote: >> >> Here's a crazy question: would a version of MonadError without the >> fundep do the trick? >> >> class Monad m => MonadFail e m where >> fail :: e -> m a >> >> instance MonadFail a [] where >> fail = const [] >> >> instance (a ~ e) => MonadFail e (Either a) where >> fail = Left >> >> instance MonadFail SomeException IO where >> fail = throwIO >> instance MonadFail IOException IO where >> fail = throwIO >> ... >> instance MonadFail String IO where >> fail = throwIO . userError >> >> On Wed, Jun 10, 2015 at 8:32 AM, Mario Bla?evi? >> wrote: >> > +1 from me. >> > >> > A minor nitpick: the proposal should clarify which of the existing >> > instances of Monad from base get a MonadFail instance. My understanding >> > is >> > that none of them would define fail = error, but that has not been made >> > explicit. >> > >> > >> > _______________________________________________ >> > Libraries mailing list >> > Libraries at haskell.org >> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > From allbery.b at gmail.com Wed Jun 10 15:49:51 2015 From: allbery.b at gmail.com (Brandon Allbery) Date: Wed, 10 Jun 2015 11:49:51 -0400 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> <55782E79.5090109@ciktel.net> Message-ID: On Wed, Jun 10, 2015 at 11:44 AM, David Feuer wrote: > It therefore seems really only to be suitable for > pattern match failure and user-generated IOErrors > I feel like even that second one is not really appropriate. If you want a user-generated IOError, create one yourself; don't make assumptions about availability or API for what should really be considered a compiler or language implementation detail. -- brandon s allbery kf8nh sine nomine associates allbery.b at gmail.com ballbery at sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net -------------- next part -------------- An HTML attachment was scrubbed... URL: From ekmett at gmail.com Wed Jun 10 15:53:07 2015 From: ekmett at gmail.com (Edward Kmett) Date: Wed, 10 Jun 2015 17:53:07 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> <55782E79.5090109@ciktel.net> Message-ID: You could handle that case explicitly by giving a class that converted a string into e and putting that constraint on the MonadFail instance for Either: class Error a where strMsg :: String -> a instance Error e => MonadFail (Either e) where fail = Left . strMsg We used to do this in the mtl, with the Error class, but it then had to encumber the entire Monad, so even folks who didn't want it needed to supply a garbage instance. Right now, fail for Either is necessarily _error_ because we can't put it in the left side without incurring a constraint on every user of the monad. At least here the ad hoc construction can be offloaded to the particular MonadFail instance, or to whatever monad someone makes up for working with their Either-like construction. -Edward On Wed, Jun 10, 2015 at 5:44 PM, David Feuer wrote: > My main concern, I suppose, is that I don't see a way (without > extensions) to deal with even the most basic interesting failure > monad: Either e. It therefore seems really only to be suitable for > pattern match failure and user-generated IOErrors, which don't really > strike me as terribly natural bedfellows. > > On Wed, Jun 10, 2015 at 10:55 AM, Edward Kmett wrote: > > This would require you to add MPTCs to the language standard, which means > > standardizing how they work. > > > > Any solution involving SomeException or any of its variants is going to > drag > > in GADTs, Typeable, higher rank types. > > > > ... and it would drag them inexorably into the Prelude, not just base. > > > > Compared to a simple > > > > class Monad m => MonadFail m where > > fail :: String -> m a > > > > that is a very hard sell! > > > > On the other hand, I do think what we could do is add more information > about > > pattern match failures by adding another member to the class > > > > class Monad m => MonadFail m where > > patternMatchFailure :: Location -> String -> whatever else you like -> > m a > > patternMatchFailure l s ... = fail (code to generate the string we > > generate in the compiler using just the parts we're passed) > > > > fail :: String -> m a > > > > Then the existing 'fail' desugaring could be done in terms of this > > additional member and its default implementation. > > > > This remains entirely in the "small" subset of Haskell that is well > behaved. > > It doesn't change if we go and radically redefine the way the exception > > hierarchy works, and it doesn't require a ton of standardization effort. > > > > Now if we want to make the fail instance for IO or other MonadThrow > > instances package up the patternMatchFailure and throw it in an > exception we > > have the freedom, but we're avoid locking ourselves in to actually > trying to > > figure out how to standardize all of the particulars of the exception > > machinery into the language standard. > > > > -Edward > > > > On Wed, Jun 10, 2015 at 4:19 PM, David Feuer > wrote: > >> > >> Here's a crazy question: would a version of MonadError without the > >> fundep do the trick? > >> > >> class Monad m => MonadFail e m where > >> fail :: e -> m a > >> > >> instance MonadFail a [] where > >> fail = const [] > >> > >> instance (a ~ e) => MonadFail e (Either a) where > >> fail = Left > >> > >> instance MonadFail SomeException IO where > >> fail = throwIO > >> instance MonadFail IOException IO where > >> fail = throwIO > >> ... > >> instance MonadFail String IO where > >> fail = throwIO . userError > >> > >> On Wed, Jun 10, 2015 at 8:32 AM, Mario Bla?evi? > >> wrote: > >> > +1 from me. > >> > > >> > A minor nitpick: the proposal should clarify which of the existing > >> > instances of Monad from base get a MonadFail instance. My > understanding > >> > is > >> > that none of them would define fail = error, but that has not been > made > >> > explicit. > >> > > >> > > >> > _______________________________________________ > >> > Libraries mailing list > >> > Libraries at haskell.org > >> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > >> _______________________________________________ > >> Libraries mailing list > >> Libraries at haskell.org > >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.feuer at gmail.com Wed Jun 10 16:07:00 2015 From: david.feuer at gmail.com (David Feuer) Date: Wed, 10 Jun 2015 12:07:00 -0400 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> <55782E79.5090109@ciktel.net> Message-ID: But why does a string actually make sense in the context of handling pattern match failures? Sticking to a Haskell 98 solution, I would think MonadZero would be the way to go for those, rather than MonadFail. What, after all, can you really do with the string generated by a pattern match failure? For everything other than pattern match failures, I would think the user should use MonadError, a non-fundep MonadError, or just work directly without classes. On Wed, Jun 10, 2015 at 11:53 AM, Edward Kmett wrote: > You could handle that case explicitly by giving a class that converted a > string into e and putting that constraint on the MonadFail instance for > Either: > > class Error a where > strMsg :: String -> a > > instance Error e => MonadFail (Either e) where > fail = Left . strMsg > > We used to do this in the mtl, with the Error class, but it then had to > encumber the entire Monad, so even folks who didn't want it needed to supply > a garbage instance. > > Right now, fail for Either is necessarily _error_ because we can't put it in > the left side without incurring a constraint on every user of the monad. > > At least here the ad hoc construction can be offloaded to the particular > MonadFail instance, or to whatever monad someone makes up for working with > their Either-like construction. > > -Edward > > On Wed, Jun 10, 2015 at 5:44 PM, David Feuer wrote: >> >> My main concern, I suppose, is that I don't see a way (without >> extensions) to deal with even the most basic interesting failure >> monad: Either e. It therefore seems really only to be suitable for >> pattern match failure and user-generated IOErrors, which don't really >> strike me as terribly natural bedfellows. >> >> On Wed, Jun 10, 2015 at 10:55 AM, Edward Kmett wrote: >> > This would require you to add MPTCs to the language standard, which >> > means >> > standardizing how they work. >> > >> > Any solution involving SomeException or any of its variants is going to >> > drag >> > in GADTs, Typeable, higher rank types. >> > >> > ... and it would drag them inexorably into the Prelude, not just base. >> > >> > Compared to a simple >> > >> > class Monad m => MonadFail m where >> > fail :: String -> m a >> > >> > that is a very hard sell! >> > >> > On the other hand, I do think what we could do is add more information >> > about >> > pattern match failures by adding another member to the class >> > >> > class Monad m => MonadFail m where >> > patternMatchFailure :: Location -> String -> whatever else you like -> >> > m a >> > patternMatchFailure l s ... = fail (code to generate the string we >> > generate in the compiler using just the parts we're passed) >> > >> > fail :: String -> m a >> > >> > Then the existing 'fail' desugaring could be done in terms of this >> > additional member and its default implementation. >> > >> > This remains entirely in the "small" subset of Haskell that is well >> > behaved. >> > It doesn't change if we go and radically redefine the way the exception >> > hierarchy works, and it doesn't require a ton of standardization effort. >> > >> > Now if we want to make the fail instance for IO or other MonadThrow >> > instances package up the patternMatchFailure and throw it in an >> > exception we >> > have the freedom, but we're avoid locking ourselves in to actually >> > trying to >> > figure out how to standardize all of the particulars of the exception >> > machinery into the language standard. >> > >> > -Edward >> > >> > On Wed, Jun 10, 2015 at 4:19 PM, David Feuer >> > wrote: >> >> >> >> Here's a crazy question: would a version of MonadError without the >> >> fundep do the trick? >> >> >> >> class Monad m => MonadFail e m where >> >> fail :: e -> m a >> >> >> >> instance MonadFail a [] where >> >> fail = const [] >> >> >> >> instance (a ~ e) => MonadFail e (Either a) where >> >> fail = Left >> >> >> >> instance MonadFail SomeException IO where >> >> fail = throwIO >> >> instance MonadFail IOException IO where >> >> fail = throwIO >> >> ... >> >> instance MonadFail String IO where >> >> fail = throwIO . userError >> >> >> >> On Wed, Jun 10, 2015 at 8:32 AM, Mario Bla?evi? >> >> wrote: >> >> > +1 from me. >> >> > >> >> > A minor nitpick: the proposal should clarify which of the >> >> > existing >> >> > instances of Monad from base get a MonadFail instance. My >> >> > understanding >> >> > is >> >> > that none of them would define fail = error, but that has not been >> >> > made >> >> > explicit. >> >> > >> >> > >> >> > _______________________________________________ >> >> > Libraries mailing list >> >> > Libraries at haskell.org >> >> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> >> _______________________________________________ >> >> Libraries mailing list >> >> Libraries at haskell.org >> >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> > >> > > > From ekmett at gmail.com Wed Jun 10 19:48:07 2015 From: ekmett at gmail.com (Edward Kmett) Date: Wed, 10 Jun 2015 21:48:07 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> <55782E79.5090109@ciktel.net> Message-ID: I mentioned in another thread on this topic that it may be perfectly reasonable to extend the class with another method that handles just the pattern match failure case with the details necessary to reproduce the current errors. class Monad m => MonadFail m where fail :: String -> m a patternMatchFailure :: Location -> CallStack -> Whatever Other Information You Like -> String -> m a patternMatchFailure l w ... = fail (code to generate the string we produce now using the inputs given) Then a particular concrete MonadFail instance could choose to throw a GHC style extensible exception, it could format the string, it could default to mzero, etc. instance MonadFail IO where patternMatchFailure a b c .. = throwIO $ PatternMatchFailure a b c .. But if we don't capture the location information / string / whatever _somehow_ then we lose information relative to the status quo, just by going down to mzero on a failure. Users use this in their debugging today to find where code went wrong that they weren't expecting to go wrong. Beyond handling these two "traditional" error cases, I think everything else should be left to something that doesn't infect as central a place as Prelude. Doing a "general" MonadError with fundeps or without fundeps and just MPTCs still requires you to extend the language of the standard to support language features it doesn't currently incorporate. Trying to upgrade 'fail' itself to take an argument that isn't just a String breaks all the code that uses -XOverloadedStrings, so if you want more information it is going to have to be in a different method than fail, but it could live in the same class. Finally fail has different semantics than mzero for important monads like STM that exist today. -Edward On Wed, Jun 10, 2015 at 6:07 PM, David Feuer wrote: > But why does a string actually make sense in the context of handling > pattern match failures? Sticking to a Haskell 98 solution, I would > think MonadZero would be the way to go for those, rather than > MonadFail. What, after all, can you really do with the string > generated by a pattern match failure? For everything other than > pattern match failures, I would think the user should use MonadError, > a non-fundep MonadError, or just work directly without classes. > > On Wed, Jun 10, 2015 at 11:53 AM, Edward Kmett wrote: > > You could handle that case explicitly by giving a class that converted a > > string into e and putting that constraint on the MonadFail instance for > > Either: > > > > class Error a where > > strMsg :: String -> a > > > > instance Error e => MonadFail (Either e) where > > fail = Left . strMsg > > > > We used to do this in the mtl, with the Error class, but it then had to > > encumber the entire Monad, so even folks who didn't want it needed to > supply > > a garbage instance. > > > > Right now, fail for Either is necessarily _error_ because we can't put > it in > > the left side without incurring a constraint on every user of the monad. > > > > At least here the ad hoc construction can be offloaded to the particular > > MonadFail instance, or to whatever monad someone makes up for working > with > > their Either-like construction. > > > > -Edward > > > > On Wed, Jun 10, 2015 at 5:44 PM, David Feuer > wrote: > >> > >> My main concern, I suppose, is that I don't see a way (without > >> extensions) to deal with even the most basic interesting failure > >> monad: Either e. It therefore seems really only to be suitable for > >> pattern match failure and user-generated IOErrors, which don't really > >> strike me as terribly natural bedfellows. > >> > >> On Wed, Jun 10, 2015 at 10:55 AM, Edward Kmett > wrote: > >> > This would require you to add MPTCs to the language standard, which > >> > means > >> > standardizing how they work. > >> > > >> > Any solution involving SomeException or any of its variants is going > to > >> > drag > >> > in GADTs, Typeable, higher rank types. > >> > > >> > ... and it would drag them inexorably into the Prelude, not just base. > >> > > >> > Compared to a simple > >> > > >> > class Monad m => MonadFail m where > >> > fail :: String -> m a > >> > > >> > that is a very hard sell! > >> > > >> > On the other hand, I do think what we could do is add more information > >> > about > >> > pattern match failures by adding another member to the class > >> > > >> > class Monad m => MonadFail m where > >> > patternMatchFailure :: Location -> String -> whatever else you like > -> > >> > m a > >> > patternMatchFailure l s ... = fail (code to generate the string we > >> > generate in the compiler using just the parts we're passed) > >> > > >> > fail :: String -> m a > >> > > >> > Then the existing 'fail' desugaring could be done in terms of this > >> > additional member and its default implementation. > >> > > >> > This remains entirely in the "small" subset of Haskell that is well > >> > behaved. > >> > It doesn't change if we go and radically redefine the way the > exception > >> > hierarchy works, and it doesn't require a ton of standardization > effort. > >> > > >> > Now if we want to make the fail instance for IO or other MonadThrow > >> > instances package up the patternMatchFailure and throw it in an > >> > exception we > >> > have the freedom, but we're avoid locking ourselves in to actually > >> > trying to > >> > figure out how to standardize all of the particulars of the exception > >> > machinery into the language standard. > >> > > >> > -Edward > >> > > >> > On Wed, Jun 10, 2015 at 4:19 PM, David Feuer > >> > wrote: > >> >> > >> >> Here's a crazy question: would a version of MonadError without the > >> >> fundep do the trick? > >> >> > >> >> class Monad m => MonadFail e m where > >> >> fail :: e -> m a > >> >> > >> >> instance MonadFail a [] where > >> >> fail = const [] > >> >> > >> >> instance (a ~ e) => MonadFail e (Either a) where > >> >> fail = Left > >> >> > >> >> instance MonadFail SomeException IO where > >> >> fail = throwIO > >> >> instance MonadFail IOException IO where > >> >> fail = throwIO > >> >> ... > >> >> instance MonadFail String IO where > >> >> fail = throwIO . userError > >> >> > >> >> On Wed, Jun 10, 2015 at 8:32 AM, Mario Bla?evi? > > >> >> wrote: > >> >> > +1 from me. > >> >> > > >> >> > A minor nitpick: the proposal should clarify which of the > >> >> > existing > >> >> > instances of Monad from base get a MonadFail instance. My > >> >> > understanding > >> >> > is > >> >> > that none of them would define fail = error, but that has not been > >> >> > made > >> >> > explicit. > >> >> > > >> >> > > >> >> > _______________________________________________ > >> >> > Libraries mailing list > >> >> > Libraries at haskell.org > >> >> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > >> >> _______________________________________________ > >> >> Libraries mailing list > >> >> Libraries at haskell.org > >> >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > >> > > >> > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From tikhon at jelv.is Wed Jun 10 20:30:46 2015 From: tikhon at jelv.is (Tikhon Jelvis) Date: Wed, 10 Jun 2015 13:30:46 -0700 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> <55782E79.5090109@ciktel.net> Message-ID: I'm a really big fan of Edward's `patternMatchFailure` suggestion. It's clear, useful and has an obvious name. (The fact that `fail` is related to pattern matching is by no means obvious!) It also moves the class even further away from Monad, at least conceptually, so I think a more generic naming convention and possibly fairly relaxed superclass requirements make sense. On Wed, Jun 10, 2015 at 12:48 PM, Edward Kmett wrote: > I mentioned in another thread on this topic that it may be perfectly > reasonable to extend the class with another method that handles just the > pattern match failure case with the details necessary to reproduce the > current errors. > > class Monad m => MonadFail m where > fail :: String -> m a > patternMatchFailure :: Location -> CallStack -> Whatever Other > Information You Like -> String -> m a > patternMatchFailure l w ... = fail (code to generate the string we > produce now using the inputs given) > > Then a particular concrete MonadFail instance could choose to throw a GHC > style extensible exception, it could format the string, it could default to > mzero, etc. > > instance MonadFail IO where > patternMatchFailure a b c .. = throwIO $ PatternMatchFailure a b c .. > > But if we don't capture the location information / string / whatever > _somehow_ then we lose information relative to the status quo, just by > going down to mzero on a failure. Users use this in their debugging today > to find where code went wrong that they weren't expecting to go wrong. > > Beyond handling these two "traditional" error cases, I think everything > else should be left to something that doesn't infect as central a place as > Prelude. > > Doing a "general" MonadError with fundeps or without fundeps and just > MPTCs still requires you to extend the language of the standard to support > language features it doesn't currently incorporate. > > Trying to upgrade 'fail' itself to take an argument that isn't just a > String breaks all the code that uses -XOverloadedStrings, so if you want > more information it is going to have to be in a different method than fail, > but it could live in the same class. > > Finally fail has different semantics than mzero for important monads like > STM that exist today. > > -Edward > > On Wed, Jun 10, 2015 at 6:07 PM, David Feuer > wrote: > >> But why does a string actually make sense in the context of handling >> pattern match failures? Sticking to a Haskell 98 solution, I would >> think MonadZero would be the way to go for those, rather than >> MonadFail. What, after all, can you really do with the string >> generated by a pattern match failure? For everything other than >> pattern match failures, I would think the user should use MonadError, >> a non-fundep MonadError, or just work directly without classes. >> >> On Wed, Jun 10, 2015 at 11:53 AM, Edward Kmett wrote: >> > You could handle that case explicitly by giving a class that converted a >> > string into e and putting that constraint on the MonadFail instance for >> > Either: >> > >> > class Error a where >> > strMsg :: String -> a >> > >> > instance Error e => MonadFail (Either e) where >> > fail = Left . strMsg >> > >> > We used to do this in the mtl, with the Error class, but it then had to >> > encumber the entire Monad, so even folks who didn't want it needed to >> supply >> > a garbage instance. >> > >> > Right now, fail for Either is necessarily _error_ because we can't put >> it in >> > the left side without incurring a constraint on every user of the monad. >> > >> > At least here the ad hoc construction can be offloaded to the particular >> > MonadFail instance, or to whatever monad someone makes up for working >> with >> > their Either-like construction. >> > >> > -Edward >> > >> > On Wed, Jun 10, 2015 at 5:44 PM, David Feuer >> wrote: >> >> >> >> My main concern, I suppose, is that I don't see a way (without >> >> extensions) to deal with even the most basic interesting failure >> >> monad: Either e. It therefore seems really only to be suitable for >> >> pattern match failure and user-generated IOErrors, which don't really >> >> strike me as terribly natural bedfellows. >> >> >> >> On Wed, Jun 10, 2015 at 10:55 AM, Edward Kmett >> wrote: >> >> > This would require you to add MPTCs to the language standard, which >> >> > means >> >> > standardizing how they work. >> >> > >> >> > Any solution involving SomeException or any of its variants is going >> to >> >> > drag >> >> > in GADTs, Typeable, higher rank types. >> >> > >> >> > ... and it would drag them inexorably into the Prelude, not just >> base. >> >> > >> >> > Compared to a simple >> >> > >> >> > class Monad m => MonadFail m where >> >> > fail :: String -> m a >> >> > >> >> > that is a very hard sell! >> >> > >> >> > On the other hand, I do think what we could do is add more >> information >> >> > about >> >> > pattern match failures by adding another member to the class >> >> > >> >> > class Monad m => MonadFail m where >> >> > patternMatchFailure :: Location -> String -> whatever else you >> like -> >> >> > m a >> >> > patternMatchFailure l s ... = fail (code to generate the string we >> >> > generate in the compiler using just the parts we're passed) >> >> > >> >> > fail :: String -> m a >> >> > >> >> > Then the existing 'fail' desugaring could be done in terms of this >> >> > additional member and its default implementation. >> >> > >> >> > This remains entirely in the "small" subset of Haskell that is well >> >> > behaved. >> >> > It doesn't change if we go and radically redefine the way the >> exception >> >> > hierarchy works, and it doesn't require a ton of standardization >> effort. >> >> > >> >> > Now if we want to make the fail instance for IO or other MonadThrow >> >> > instances package up the patternMatchFailure and throw it in an >> >> > exception we >> >> > have the freedom, but we're avoid locking ourselves in to actually >> >> > trying to >> >> > figure out how to standardize all of the particulars of the exception >> >> > machinery into the language standard. >> >> > >> >> > -Edward >> >> > >> >> > On Wed, Jun 10, 2015 at 4:19 PM, David Feuer >> >> > wrote: >> >> >> >> >> >> Here's a crazy question: would a version of MonadError without the >> >> >> fundep do the trick? >> >> >> >> >> >> class Monad m => MonadFail e m where >> >> >> fail :: e -> m a >> >> >> >> >> >> instance MonadFail a [] where >> >> >> fail = const [] >> >> >> >> >> >> instance (a ~ e) => MonadFail e (Either a) where >> >> >> fail = Left >> >> >> >> >> >> instance MonadFail SomeException IO where >> >> >> fail = throwIO >> >> >> instance MonadFail IOException IO where >> >> >> fail = throwIO >> >> >> ... >> >> >> instance MonadFail String IO where >> >> >> fail = throwIO . userError >> >> >> >> >> >> On Wed, Jun 10, 2015 at 8:32 AM, Mario Bla?evi? < >> blamario at ciktel.net> >> >> >> wrote: >> >> >> > +1 from me. >> >> >> > >> >> >> > A minor nitpick: the proposal should clarify which of the >> >> >> > existing >> >> >> > instances of Monad from base get a MonadFail instance. My >> >> >> > understanding >> >> >> > is >> >> >> > that none of them would define fail = error, but that has not been >> >> >> > made >> >> >> > explicit. >> >> >> > >> >> >> > >> >> >> > _______________________________________________ >> >> >> > Libraries mailing list >> >> >> > Libraries at haskell.org >> >> >> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> >> >> _______________________________________________ >> >> >> Libraries mailing list >> >> >> Libraries at haskell.org >> >> >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> >> > >> >> > >> > >> > >> > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.feuer at gmail.com Thu Jun 11 02:02:02 2015 From: david.feuer at gmail.com (David Feuer) Date: Wed, 10 Jun 2015 22:02:02 -0400 Subject: Proposal: Add IsList instance for ZipList Message-ID: foo = getZipList $ [f,g,h] <$> [a,b,c] <*> [d,e,i] looks a lot better than bar = getZipList $ ZipList [f,g,h] <$> ZipList [a,b,c] <*> ZipList [d,e,i] From ekmett at gmail.com Thu Jun 11 02:03:09 2015 From: ekmett at gmail.com (Edward Kmett) Date: Thu, 11 Jun 2015 04:03:09 +0200 Subject: Proposal: Add IsList instance for ZipList In-Reply-To: References: Message-ID: Makes sense to me. On Thu, Jun 11, 2015 at 4:02 AM, David Feuer wrote: > foo = getZipList $ [f,g,h] <$> [a,b,c] <*> [d,e,i] > > looks a lot better than > > bar = getZipList $ ZipList [f,g,h] <$> ZipList [a,b,c] <*> ZipList [d,e,i] > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From fumiexcel at gmail.com Thu Jun 11 03:26:09 2015 From: fumiexcel at gmail.com (Fumiaki Kinoshita) Date: Thu, 11 Jun 2015 12:26:09 +0900 Subject: Proposal: Add IsList instance for ZipList In-Reply-To: References: Message-ID: +1 2015-06-11 11:02 GMT+09:00 David Feuer : > foo = getZipList $ [f,g,h] <$> [a,b,c] <*> [d,e,i] > > looks a lot better than > > bar = getZipList $ ZipList [f,g,h] <$> ZipList [a,b,c] <*> ZipList [d,e,i] > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Thu Jun 11 09:26:02 2015 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Thu, 11 Jun 2015 11:26:02 +0200 (CEST) Subject: Proposal: Add IsList instance for ZipList In-Reply-To: References: Message-ID: On Wed, 10 Jun 2015, David Feuer wrote: > foo = getZipList $ [f,g,h] <$> [a,b,c] <*> [d,e,i] > > looks a lot better than > > bar = getZipList $ ZipList [f,g,h] <$> ZipList [a,b,c] <*> ZipList [d,e,i] But the second one is less surprising. For my taste it would have been better to give the ZipList semantics to the list type by default, because there are more data types that we can give a ZipList-like Applicative instance. The current non-determinism implementation for Applicative [] and Monad [] could have been used for a special non-determinism list type. But this instance was defined when there was no Applicative. :-( From ekmett at gmail.com Thu Jun 11 11:22:43 2015 From: ekmett at gmail.com (Edward Kmett) Date: Thu, 11 Jun 2015 13:22:43 +0200 Subject: Proposal: Add IsList instance for ZipList In-Reply-To: References: Message-ID: I personally strongly believe in keeping the Applicative and Monad for a type compatible. Otherwise why the heck did we make Applicative a superclass of Monad? In this case the thing David wants only makes any difference if you explicitly turn on OverloadedLists, so if you never use that extension you'll never care about the instance anyways. -Edward On Thu, Jun 11, 2015 at 11:26 AM, Henning Thielemann < lemming at henning-thielemann.de> wrote: > > On Wed, 10 Jun 2015, David Feuer wrote: > > foo = getZipList $ [f,g,h] <$> [a,b,c] <*> [d,e,i] >> >> looks a lot better than >> >> bar = getZipList $ ZipList [f,g,h] <$> ZipList [a,b,c] <*> ZipList [d,e,i] >> > > But the second one is less surprising. > > For my taste it would have been better to give the ZipList semantics to > the list type by default, because there are more data types that we can > give a ZipList-like Applicative instance. The current non-determinism > implementation for Applicative [] and Monad [] could have been used for a > special non-determinism list type. But this instance was defined when there > was no Applicative. :-( > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From michael at snoyman.com Thu Jun 11 11:25:28 2015 From: michael at snoyman.com (Michael Snoyman) Date: Thu, 11 Jun 2015 11:25:28 +0000 Subject: Proposal: Add IsList instance for ZipList In-Reply-To: References: Message-ID: I agree with Edward and David, this instance looks like it would be a useful addition. On Thu, Jun 11, 2015, 2:22 PM Edward Kmett wrote: > I personally strongly believe in keeping the Applicative and Monad for a > type compatible. > > Otherwise why the heck did we make Applicative a superclass of Monad? > > In this case the thing David wants only makes any difference if you > explicitly turn on OverloadedLists, so if you never use that extension > you'll never care about the instance anyways. > > -Edward > > On Thu, Jun 11, 2015 at 11:26 AM, Henning Thielemann < > lemming at henning-thielemann.de> wrote: > >> >> On Wed, 10 Jun 2015, David Feuer wrote: >> >> foo = getZipList $ [f,g,h] <$> [a,b,c] <*> [d,e,i] >>> >>> looks a lot better than >>> >>> bar = getZipList $ ZipList [f,g,h] <$> ZipList [a,b,c] <*> ZipList >>> [d,e,i] >>> >> >> But the second one is less surprising. >> >> For my taste it would have been better to give the ZipList semantics to >> the list type by default, because there are more data types that we can >> give a ZipList-like Applicative instance. The current non-determinism >> implementation for Applicative [] and Monad [] could have been used for a >> special non-determinism list type. But this instance was defined when there >> was no Applicative. :-( >> >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From g9ks157k at acme.softbase.org Thu Jun 11 15:08:58 2015 From: g9ks157k at acme.softbase.org (Wolfgang Jeltsch) Date: Thu, 11 Jun 2015 18:08:58 +0300 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55774FF2.8020505@gmail.com> References: <55774FF2.8020505@gmail.com> Message-ID: <1434035338.2205.17.camel@idefix> Hi David, thank you very much for this proposal. I think having fail in Monad is just plain wrong, and I am therefore very happy to see it being moved out. I have some remarks, though: > A class of patterns that are conditionally failable are `newtype`s, > and single constructor `data` types, which are unfailable by > themselves, but may fail if matching on their fields is done with > failable paterns. The part about single-constructor data types is not true. A single-constructor data type has a value ? that is different from applying the data constructor to ??s. For example, ? and (?, ?) are two different values. Matching ? against the pattern (_, _) fails, matching (?, ?) against (_, _) succeeds. So single-constructor data types are not different from all other data types in this respect. The dividing line really runs between data types and newtypes. So only matches against patterns C p where C is a newtype constructor and p is unfailable should be considered unfailable. > - Applicative `do` notation is coming sooner or later, `fail` might > be useful in this more general scenario. Due to the AMP, it is > trivial to change the `MonadFail` superclass to `Applicative` > later. (The name will be a bit misleading, but it's a very small > price to pay.) I think it would be very misleading having a MonadFail class that might have instances that are not monads, and that this is a price we should not pay. So we should not name the class MonadFail. Maybe, Fail would be a good name. > I think we should keep the `Monad` superclass for three main reasons: > > - We don't want to see `(Monad m, MonadFail m) =>` all over the place. But exactly this will happen if we change the superclass of (Monad)Fail from Monad to Applicative. So it might be better to impose a more light-weight constraint in the first place. Functor m might be a good choice. All the best, Wolfgang From felipe.lessa at gmail.com Thu Jun 11 15:15:53 2015 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Thu, 11 Jun 2015 12:15:53 -0300 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <1434035338.2205.17.camel@idefix> References: <55774FF2.8020505@gmail.com> <1434035338.2205.17.camel@idefix> Message-ID: <5579A629.8000207@gmail.com> On 11-06-2015 12:08, Wolfgang Jeltsch wrote: >> A class of patterns that are conditionally failable are `newtype`s, >> and single constructor `data` types, which are unfailable by >> themselves, but may fail if matching on their fields is done with >> failable paterns. > > The part about single-constructor data types is not true. A > single-constructor data type has a value ? that is different from > applying the data constructor to ??s. For example, ? and (?, ?) are two > different values. Matching ? against the pattern (_, _) fails, matching > (?, ?) against (_, _) succeeds. So single-constructor data types are not > different from all other data types in this respect. The dividing line > really runs between data types and newtypes. So only matches against > patterns C p where C is a newtype constructor and p is unfailable should > be considered unfailable. I think that being failable is a property that is undefined for undefined. Ok, sorry :), what I mean is that you can't do anything to distinguish C p from _|_ within pure code. For example: Just a <- x You can distinguish Just a from Nothing in pure code, so that gets translated to a pattern match and a fail call. However: (a, b) <- x You can't distinguish (a, b) from _|_. In other words, the pattern (a, b) covers every possible value of its type. So it doesn't need a fail call. And it doesn't matter if it's a newtype or a single-constructor data type. Makes sense? Cheers, -- Felipe. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: From mblazevic at stilo.com Thu Jun 11 15:18:38 2015 From: mblazevic at stilo.com (=?UTF-8?B?TWFyaW8gQmxhxb5ldmnEhw==?=) Date: Thu, 11 Jun 2015 11:18:38 -0400 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> <55782E79.5090109@ciktel.net> Message-ID: <5579A6CE.3090808@stilo.com> On 15-06-10 03:48 PM, Edward Kmett wrote: > I mentioned in another thread on this topic that it may be perfectly > reasonable to extend the class with another method that handles just the > pattern match failure case with the details necessary to reproduce the > current errors. > > class Monad m => MonadFail m where > fail :: String -> m a > patternMatchFailure :: Location -> CallStack -> Whatever Other > Information You Like -> String -> m a > patternMatchFailure l w ... = fail (code to generate the string we > produce now using the inputs given) > > Then a particular concrete MonadFail instance could choose to throw a > GHC style extensible exception, it could format the string, it could > default to mzero, etc. I'm +1 on this extension. May I suggest some of Whatever Other Information You Like? I wonder if the following method would be implementable in GHC: > patternMatchFailureOnData :: (Data a, Data b) => > Location -> CallStack > -> String --^ the fail message > -> a --^ the RHS of the failed assignment > -> (a -> Maybe b) --^ the failed LHS pattern > -> (b -> m c) --^ do continuation > -> m a The method would default to plain patternMatchOnFailure, which would default to fail. It would be invoked on a pattern-match failure iff the type of the RHS has a Data instance in scope. This way an EDSL monad could get some actual use out of the fail mechanism and recover from a failure. > > instance MonadFail IO where > patternMatchFailure a b c .. = throwIO $ PatternMatchFailure a b c .. > > But if we don't capture the location information / string / whatever > _somehow_ then we lose information relative to the status quo, just by > going down to mzero on a failure. Users use this in their debugging > today to find where code went wrong that they weren't expecting to go wrong. > > Beyond handling these two "traditional" error cases, I think everything > else should be left to something that doesn't infect as central a place > as Prelude. > > Doing a "general" MonadError with fundeps or without fundeps and just > MPTCs still requires you to extend the language of the standard to > support language features it doesn't currently incorporate. > > Trying to upgrade 'fail' itself to take an argument that isn't just a > String breaks all the code that uses -XOverloadedStrings, so if you want > more information it is going to have to be in a different method than > fail, but it could live in the same class. > > Finally fail has different semantics than mzero for important monads > like STM that exist today. > > -Edward From g9ks157k at acme.softbase.org Thu Jun 11 15:28:20 2015 From: g9ks157k at acme.softbase.org (Wolfgang Jeltsch) Date: Thu, 11 Jun 2015 18:28:20 +0300 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> <1434035338.2205.17.camel@idefix> Message-ID: <1434036500.2205.25.camel@idefix> Are you sure that desugaring works this way? If yes, this should be considered a bug and be fixed, I would say. It is very illogical. All the best, Wolfgang Am Donnerstag, den 11.06.2015, 16:23 +0100 schrieb David Turner: > AIUI the point about ? and (?, ?) being different doesn't matter here: > a bind for a single-constructor datatype never desugars in a way that > uses fail (which isn't to say that it can't be undefined) > > For instance: > > runErrorT (do { (_,_) <- return undefined; return () } :: ErrorT String IO ()) > > throws an exception, even though the bind is in ErrorT where fail just > returns left: > > runErrorT (do { fail "oops"; return () } :: ErrorT String IO ()) > > => Left "oops" > > Hope that helps, and hope I understand correctly! > > David > > > On 11 June 2015 at 16:08, Wolfgang Jeltsch wrote: > > Hi David, > > > > thank you very much for this proposal. I think having fail in Monad is > > just plain wrong, and I am therefore very happy to see it being moved > > out. > > > > I have some remarks, though: > > > >> A class of patterns that are conditionally failable are `newtype`s, > >> and single constructor `data` types, which are unfailable by > >> themselves, but may fail if matching on their fields is done with > >> failable paterns. > > > > The part about single-constructor data types is not true. A > > single-constructor data type has a value ? that is different from > > applying the data constructor to ??s. For example, ? and (?, ?) are two > > different values. Matching ? against the pattern (_, _) fails, matching > > (?, ?) against (_, _) succeeds. So single-constructor data types are not > > different from all other data types in this respect. The dividing line > > really runs between data types and newtypes. So only matches against > > patterns C p where C is a newtype constructor and p is unfailable should > > be considered unfailable. > > > >> - Applicative `do` notation is coming sooner or later, `fail` might > >> be useful in this more general scenario. Due to the AMP, it is > >> trivial to change the `MonadFail` superclass to `Applicative` > >> later. (The name will be a bit misleading, but it's a very small > >> price to pay.) > > > > I think it would be very misleading having a MonadFail class that might > > have instances that are not monads, and that this is a price we should > > not pay. So we should not name the class MonadFail. Maybe, Fail would be > > a good name. > > > >> I think we should keep the `Monad` superclass for three main reasons: > >> > >> - We don't want to see `(Monad m, MonadFail m) =>` all over the place. > > > > But exactly this will happen if we change the superclass of (Monad)Fail > > from Monad to Applicative. So it might be better to impose a more > > light-weight constraint in the first place. Functor m might be a good > > choice. > > > > All the best, > > Wolfgang > > > > _______________________________________________ > > ghc-devs mailing list > > ghc-devs at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs From david.feuer at gmail.com Thu Jun 11 15:36:23 2015 From: david.feuer at gmail.com (David Feuer) Date: Thu, 11 Jun 2015 11:36:23 -0400 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <1434036500.2205.25.camel@idefix> References: <55774FF2.8020505@gmail.com> <1434035338.2205.17.camel@idefix> <1434036500.2205.25.camel@idefix> Message-ID: Pattern matching on `undefined` is not like pattern match failure. Single-constructor types are only special if they're unlifted: `newtype` and GHC's unboxed tuples are the only examples I know of, and you can't use unboxed tuples in this context. On Thu, Jun 11, 2015 at 11:28 AM, Wolfgang Jeltsch wrote: > Are you sure that desugaring works this way? If yes, this should be > considered a bug and be fixed, I would say. It is very illogical. > > All the best, > Wolfgang > > Am Donnerstag, den 11.06.2015, 16:23 +0100 schrieb David Turner: >> AIUI the point about ? and (?, ?) being different doesn't matter here: >> a bind for a single-constructor datatype never desugars in a way that >> uses fail (which isn't to say that it can't be undefined) >> >> For instance: >> >> runErrorT (do { (_,_) <- return undefined; return () } :: ErrorT String IO ()) >> >> throws an exception, even though the bind is in ErrorT where fail just >> returns left: >> >> runErrorT (do { fail "oops"; return () } :: ErrorT String IO ()) >> >> => Left "oops" >> >> Hope that helps, and hope I understand correctly! >> >> David >> >> >> On 11 June 2015 at 16:08, Wolfgang Jeltsch wrote: >> > Hi David, >> > >> > thank you very much for this proposal. I think having fail in Monad is >> > just plain wrong, and I am therefore very happy to see it being moved >> > out. >> > >> > I have some remarks, though: >> > >> >> A class of patterns that are conditionally failable are `newtype`s, >> >> and single constructor `data` types, which are unfailable by >> >> themselves, but may fail if matching on their fields is done with >> >> failable paterns. >> > >> > The part about single-constructor data types is not true. A >> > single-constructor data type has a value ? that is different from >> > applying the data constructor to ??s. For example, ? and (?, ?) are two >> > different values. Matching ? against the pattern (_, _) fails, matching >> > (?, ?) against (_, _) succeeds. So single-constructor data types are not >> > different from all other data types in this respect. The dividing line >> > really runs between data types and newtypes. So only matches against >> > patterns C p where C is a newtype constructor and p is unfailable should >> > be considered unfailable. >> > >> >> - Applicative `do` notation is coming sooner or later, `fail` might >> >> be useful in this more general scenario. Due to the AMP, it is >> >> trivial to change the `MonadFail` superclass to `Applicative` >> >> later. (The name will be a bit misleading, but it's a very small >> >> price to pay.) >> > >> > I think it would be very misleading having a MonadFail class that might >> > have instances that are not monads, and that this is a price we should >> > not pay. So we should not name the class MonadFail. Maybe, Fail would be >> > a good name. >> > >> >> I think we should keep the `Monad` superclass for three main reasons: >> >> >> >> - We don't want to see `(Monad m, MonadFail m) =>` all over the place. >> > >> > But exactly this will happen if we change the superclass of (Monad)Fail >> > from Monad to Applicative. So it might be better to impose a more >> > light-weight constraint in the first place. Functor m might be a good >> > choice. >> > >> > All the best, >> > Wolfgang >> > >> > _______________________________________________ >> > ghc-devs mailing list >> > ghc-devs at haskell.org >> > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From g9ks157k at acme.softbase.org Thu Jun 11 15:58:19 2015 From: g9ks157k at acme.softbase.org (Wolfgang Jeltsch) Date: Thu, 11 Jun 2015 18:58:19 +0300 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> <1434035338.2205.17.camel@idefix> <1434036500.2205.25.camel@idefix> Message-ID: <1434038299.2205.32.camel@idefix> Ah, I see. Even if you desugar pattern matching against (_, _) in a do block like you do for multi-constructor data types, ? still does not result in an invocation of fail, since matching ? against (_, _) leads to divergence. To illustrate this, let f be defined as follows: f (_, _) = True f _ = False Applying f to an expression of the form (x, y) results in True, applying it to ? results in ?. False can never be the result. That said, it would seem more logical to me if all data types would be treated equal in monadic pattern matching. All the best, Wolfgang Am Donnerstag, den 11.06.2015, 11:36 -0400 schrieb David Feuer: > Pattern matching on `undefined` is not like pattern match failure. > Single-constructor types are only special if they're unlifted: > `newtype` and GHC's unboxed tuples are the only examples I know of, > and you can't use unboxed tuples in this context. > > On Thu, Jun 11, 2015 at 11:28 AM, Wolfgang Jeltsch > wrote: > > Are you sure that desugaring works this way? If yes, this should be > > considered a bug and be fixed, I would say. It is very illogical. > > > > All the best, > > Wolfgang > > > > Am Donnerstag, den 11.06.2015, 16:23 +0100 schrieb David Turner: > >> AIUI the point about ? and (?, ?) being different doesn't matter here: > >> a bind for a single-constructor datatype never desugars in a way that > >> uses fail (which isn't to say that it can't be undefined) > >> > >> For instance: > >> > >> runErrorT (do { (_,_) <- return undefined; return () } :: ErrorT String IO ()) > >> > >> throws an exception, even though the bind is in ErrorT where fail just > >> returns left: > >> > >> runErrorT (do { fail "oops"; return () } :: ErrorT String IO ()) > >> > >> => Left "oops" > >> > >> Hope that helps, and hope I understand correctly! > >> > >> David > >> > >> > >> On 11 June 2015 at 16:08, Wolfgang Jeltsch wrote: > >> > Hi David, > >> > > >> > thank you very much for this proposal. I think having fail in Monad is > >> > just plain wrong, and I am therefore very happy to see it being moved > >> > out. > >> > > >> > I have some remarks, though: > >> > > >> >> A class of patterns that are conditionally failable are `newtype`s, > >> >> and single constructor `data` types, which are unfailable by > >> >> themselves, but may fail if matching on their fields is done with > >> >> failable paterns. > >> > > >> > The part about single-constructor data types is not true. A > >> > single-constructor data type has a value ? that is different from > >> > applying the data constructor to ??s. For example, ? and (?, ?) are two > >> > different values. Matching ? against the pattern (_, _) fails, matching > >> > (?, ?) against (_, _) succeeds. So single-constructor data types are not > >> > different from all other data types in this respect. The dividing line > >> > really runs between data types and newtypes. So only matches against > >> > patterns C p where C is a newtype constructor and p is unfailable should > >> > be considered unfailable. > >> > > >> >> - Applicative `do` notation is coming sooner or later, `fail` might > >> >> be useful in this more general scenario. Due to the AMP, it is > >> >> trivial to change the `MonadFail` superclass to `Applicative` > >> >> later. (The name will be a bit misleading, but it's a very small > >> >> price to pay.) > >> > > >> > I think it would be very misleading having a MonadFail class that might > >> > have instances that are not monads, and that this is a price we should > >> > not pay. So we should not name the class MonadFail. Maybe, Fail would be > >> > a good name. > >> > > >> >> I think we should keep the `Monad` superclass for three main reasons: > >> >> > >> >> - We don't want to see `(Monad m, MonadFail m) =>` all over the place. > >> > > >> > But exactly this will happen if we change the superclass of (Monad)Fail > >> > from Monad to Applicative. So it might be better to impose a more > >> > light-weight constraint in the first place. Functor m might be a good > >> > choice. > >> > > >> > All the best, > >> > Wolfgang > >> > > >> > _______________________________________________ > >> > ghc-devs mailing list > >> > ghc-devs at haskell.org > >> > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > > > > > _______________________________________________ > > Libraries mailing list > > Libraries at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From g9ks157k at acme.softbase.org Thu Jun 11 16:03:01 2015 From: g9ks157k at acme.softbase.org (Wolfgang Jeltsch) Date: Thu, 11 Jun 2015 19:03:01 +0300 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <5579A629.8000207@gmail.com> References: <55774FF2.8020505@gmail.com> <1434035338.2205.17.camel@idefix> <5579A629.8000207@gmail.com> Message-ID: <1434038581.2205.35.camel@idefix> Am Donnerstag, den 11.06.2015, 12:15 -0300 schrieb Felipe Lessa: > On 11-06-2015 12:08, Wolfgang Jeltsch wrote: > >> A class of patterns that are conditionally failable are `newtype`s, > >> and single constructor `data` types, which are unfailable by > >> themselves, but may fail if matching on their fields is done with > >> failable paterns. > > > > The part about single-constructor data types is not true. A > > single-constructor data type has a value ? that is different from > > applying the data constructor to ??s. For example, ? and (?, ?) are two > > different values. Matching ? against the pattern (_, _) fails, matching > > (?, ?) against (_, _) succeeds. So single-constructor data types are not > > different from all other data types in this respect. The dividing line > > really runs between data types and newtypes. So only matches against > > patterns C p where C is a newtype constructor and p is unfailable should > > be considered unfailable. > > I think that being failable is a property that is undefined for > undefined. Ok, sorry :), what I mean is that you can't do anything to > distinguish C p from _|_ within pure code. > > For example: > > Just a <- x > > You can distinguish Just a from Nothing in pure code, so that gets > translated to a pattern match and a fail call. > > However: > > (a, b) <- x > > You can't distinguish (a, b) from _|_. In other words, the pattern (a, > b) covers every possible value of its type. So it doesn't need a fail > call. And it doesn't matter if it's a newtype or a single-constructor > data type. Makes sense? Well, the pattern (a, b) does not cover every possible value, but every non-? value, but you cannot use pattern matching to choose a different branch for ?, since matching ? against any refutable pattern, like (a, b), results in a runtime error. Makes sense. :-) All the best, Wolfgang From dan.doel at gmail.com Thu Jun 11 16:20:02 2015 From: dan.doel at gmail.com (Dan Doel) Date: Thu, 11 Jun 2015 12:20:02 -0400 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: References: <55774FF2.8020505@gmail.com> <1434035338.2205.17.camel@idefix> <1434036500.2205.25.camel@idefix> Message-ID: This is all well defined in the Haskell 1.4 report. Back then Haskell had "unfailable" patterns for desugaring do notation, because there was no fail (it was introduced in H98). I believe a pattern is classified as unfailable there if it is irrefutable or refutable only by bottom. Which of course is the distinction here, (x,y) is unfailable, but not irrefutable. And of course, it seems that GHC never actually stopped implementing unfailable patterns, even though they were removed from the report (or someone added it back at some point). You just have to know how to observe this fact. -- Dan On Thu, Jun 11, 2015 at 12:11 PM, David Turner < dct25-561bs at mythic-beasts.com> wrote: > Quoting the Haskell 2010 Report section 3.17.2: Attempting to match a > pattern can have one of three results: it may fail; it may succeed > ...; or it may diverge. Then in paragraph 5: > > Matching the pattern con pat1 ... patn against a value, where con is a > constructor defined by data, depends on the value: > - If the value is of the form con v1 ... vn, sub-patterns are matched > left-to-right against the components of the data value; if all matches > succeed, the overall match succeeds; the first to fail or diverge > causes the overall match to fail or diverge, respectively. > - If the value is of the form con' v1 ... vm, where con is a different > constructor to con', the match fails. > - If the value is ?, the match diverges. > > In particular, matching (_,_) can only succeed or diverge: failure is > not an option! Desugaring 'do' handles match failure with a catch-all > case that calls 'fail' but doesn't handle ?. > > > > On 11 June 2015 at 16:28, Wolfgang Jeltsch > wrote: > > Are you sure that desugaring works this way? If yes, this should be > > considered a bug and be fixed, I would say. It is very illogical. > > > > All the best, > > Wolfgang > > > > Am Donnerstag, den 11.06.2015, 16:23 +0100 schrieb David Turner: > >> AIUI the point about ? and (?, ?) being different doesn't matter here: > >> a bind for a single-constructor datatype never desugars in a way that > >> uses fail (which isn't to say that it can't be undefined) > >> > >> For instance: > >> > >> runErrorT (do { (_,_) <- return undefined; return () } :: ErrorT String > IO ()) > >> > >> throws an exception, even though the bind is in ErrorT where fail just > >> returns left: > >> > >> runErrorT (do { fail "oops"; return () } :: ErrorT String IO ()) > >> > >> => Left "oops" > >> > >> Hope that helps, and hope I understand correctly! > >> > >> David > >> > >> > >> On 11 June 2015 at 16:08, Wolfgang Jeltsch > wrote: > >> > Hi David, > >> > > >> > thank you very much for this proposal. I think having fail in Monad is > >> > just plain wrong, and I am therefore very happy to see it being moved > >> > out. > >> > > >> > I have some remarks, though: > >> > > >> >> A class of patterns that are conditionally failable are `newtype`s, > >> >> and single constructor `data` types, which are unfailable by > >> >> themselves, but may fail if matching on their fields is done with > >> >> failable paterns. > >> > > >> > The part about single-constructor data types is not true. A > >> > single-constructor data type has a value ? that is different from > >> > applying the data constructor to ??s. For example, ? and (?, ?) are > two > >> > different values. Matching ? against the pattern (_, _) fails, > matching > >> > (?, ?) against (_, _) succeeds. So single-constructor data types are > not > >> > different from all other data types in this respect. The dividing line > >> > really runs between data types and newtypes. So only matches against > >> > patterns C p where C is a newtype constructor and p is unfailable > should > >> > be considered unfailable. > >> > > >> >> - Applicative `do` notation is coming sooner or later, `fail` might > >> >> be useful in this more general scenario. Due to the AMP, it is > >> >> trivial to change the `MonadFail` superclass to `Applicative` > >> >> later. (The name will be a bit misleading, but it's a very small > >> >> price to pay.) > >> > > >> > I think it would be very misleading having a MonadFail class that > might > >> > have instances that are not monads, and that this is a price we should > >> > not pay. So we should not name the class MonadFail. Maybe, Fail would > be > >> > a good name. > >> > > >> >> I think we should keep the `Monad` superclass for three main reasons: > >> >> > >> >> - We don't want to see `(Monad m, MonadFail m) =>` all over the > place. > >> > > >> > But exactly this will happen if we change the superclass of > (Monad)Fail > >> > from Monad to Applicative. So it might be better to impose a more > >> > light-weight constraint in the first place. Functor m might be a good > >> > choice. > >> > > >> > All the best, > >> > Wolfgang > >> > > >> > _______________________________________________ > >> > ghc-devs mailing list > >> > ghc-devs at haskell.org > >> > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > > > > > _______________________________________________ > > ghc-devs mailing list > > ghc-devs at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Fri Jun 12 01:49:37 2015 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Fri, 12 Jun 2015 03:49:37 +0200 (CEST) Subject: Proposal: Add IsList instance for ZipList In-Reply-To: References: Message-ID: On Thu, 11 Jun 2015, Edward Kmett wrote: > I personally strongly believe in keeping the Applicative and Monad for a > type compatible. Otherwise why the heck did we make Applicative a > superclass of Monad? I was extending the thought of treating a list like it would have ZipList semantics. I thought loudly about what I would have done if I could re-invent Haskell 98. If list would have an Applicative instance with ZipList semantics then it would not have a Monad instance, at all. > In this case the thing David wants only makes any difference if you > explicitly turn on OverloadedLists, so if you never use that extension > you'll never care about the instance anyways. When I speak about surprises then I mean the situation where I read code of others, since I am not as much surprised about my own code. In this case someone else has enabled OverloadedLists. From abela at chalmers.se Fri Jun 12 07:06:01 2015 From: abela at chalmers.se (Andreas Abel) Date: Fri, 12 Jun 2015 09:06:01 +0200 Subject: Proposal: Add IsList instance for ZipList In-Reply-To: References: Message-ID: <557A84D9.3040501@chalmers.se> I'd like to avoid situations where adding a LANGUAGE pragma changes the semantics of code Is this one? On 12.06.2015 03:49, Henning Thielemann wrote: > > On Thu, 11 Jun 2015, Edward Kmett wrote: > >> I personally strongly believe in keeping the Applicative and Monad for >> a type compatible. Otherwise why the heck did we make Applicative a >> superclass of Monad? > > I was extending the thought of treating a list like it would have > ZipList semantics. I thought loudly about what I would have done if I > could re-invent Haskell 98. If list would have an Applicative instance > with ZipList semantics then it would not have a Monad instance, at all. > > >> In this case the thing David wants only makes any difference if you >> explicitly turn on OverloadedLists, so if you never use that extension >> you'll never care about the instance anyways. > > When I speak about surprises then I mean the situation where I read code > of others, since I am not as much surprised about my own code. In this > case someone else has enabled OverloadedLists. > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries -- Andreas Abel <>< Du bist der geliebte Mensch. Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden andreas.abel at gu.se http://www2.tcs.ifi.lmu.de/~abel/ From lemming at henning-thielemann.de Fri Jun 12 08:27:46 2015 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Fri, 12 Jun 2015 10:27:46 +0200 (CEST) Subject: Proposal: Add IsList instance for ZipList In-Reply-To: <557A84D9.3040501@chalmers.se> References: <557A84D9.3040501@chalmers.se> Message-ID: On Fri, 12 Jun 2015, Andreas Abel wrote: > I'd like to avoid situations where adding a LANGUAGE pragma changes the > semantics of code Is this one? No, it allows code that would be forbidden without the pragma. From abela at chalmers.se Fri Jun 12 08:48:56 2015 From: abela at chalmers.se (Andreas Abel) Date: Fri, 12 Jun 2015 10:48:56 +0200 Subject: Proposal: Add IsList instance for ZipList In-Reply-To: References: <557A84D9.3040501@chalmers.se> Message-ID: <557A9CF8.2090609@chalmers.se> Good. :) On 12.06.2015 10:27, Henning Thielemann wrote: > > On Fri, 12 Jun 2015, Andreas Abel wrote: > >> I'd like to avoid situations where adding a LANGUAGE pragma changes >> the semantics of code Is this one? > > No, it allows code that would be forbidden without the pragma. -- Andreas Abel <>< Du bist der geliebte Mensch. Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden andreas.abel at gu.se http://www2.tcs.ifi.lmu.de/~abel/ From abela at chalmers.se Fri Jun 12 08:49:02 2015 From: abela at chalmers.se (Andreas Abel) Date: Fri, 12 Jun 2015 10:49:02 +0200 Subject: Proposal: Add IsList instance for ZipList In-Reply-To: References: <557A84D9.3040501@chalmers.se> Message-ID: <557A9CFE.7080403@chalmers.se> Good. :) On 12.06.2015 10:27, Henning Thielemann wrote: > > On Fri, 12 Jun 2015, Andreas Abel wrote: > >> I'd like to avoid situations where adding a LANGUAGE pragma changes >> the semantics of code Is this one? > > No, it allows code that would be forbidden without the pragma. -- Andreas Abel <>< Du bist der geliebte Mensch. Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden andreas.abel at gu.se http://www2.tcs.ifi.lmu.de/~abel/ From alexander at plaimi.net Fri Jun 12 13:12:27 2015 From: alexander at plaimi.net (Alexander Berntsen) Date: Fri, 12 Jun 2015 15:12:27 +0200 Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55774FF2.8020505@gmail.com> References: <55774FF2.8020505@gmail.com> Message-ID: <557ADABB.2050509@plaimi.net> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 On 09/06/15 22:43, David Luposchainsky wrote: > - - Move `fail` from `Monad` into a new class `MonadFail`. +1. - -- Alexander alexander at plaimi.net https://secure.plaimi.net/~alexander -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCgAGBQJVetq6AAoJENQqWdRUGk8B1xoQAPQDm/U9kCOkZK2K8sDWtPTA eUC6Y7xCScYF2SM70gsGvGxqSzk6TxQWTshKkcBIskdgrN8bwW+v20gC2gmfAlh8 CbjtRdozVI54Hjh0Q/dflF7NK8ohRCEAxN4WjwhAkXwuN9WOnNKCUbASGmyjckve z+tY4F17L0hhtAYR7bjZEDjsv6+9FZMvQW6/Az/O/DBihZX/o5MpD9YZ99Bw7hUK oLKEnpNZJwLOkHgPtTJn9V/qUuL3XgXC/lGPP2DmaMPyTrINux2CNhLGHDhPgq9H fvLhehCNT+JVGjAaWqy9y+eUX+9lqZc8u/N+jrnFLteacMF/vEbhjerxbhmDqgKn VRBQqJ3sNeCquZzeXUjfYZkgkl3AL7DRuEUZ5n3wXTACvOjYUqc2JZ3Mb3uhC0bM XbCz3SHdP05x9QSYRh+SWWMNKMSfChOMg3ae6nNd8BWtKr/v2kwPxp2D97yTAPKn lrwR3xdKxs1VN6MALAfFtj7MZWMruFSfhHzZeGmEPZgx/0BU1e2/3VW/JXkA/wOm tOn2l6N9gyuFpSScbfiZmlzCz2AXJ/pCFYlPMOYIN1NCb9T1sHQSYVbG+mf+wgU2 QIcMAP/gJCvAAIg+VKfEpK0TJnQWeQx0OfQABM5A359TezTIYXN4MZ6ZVhZVo2vg 0LDiJjXCCg/I6H6lige8 =H6Um -----END PGP SIGNATURE----- From lemming at henning-thielemann.de Sat Jun 13 07:59:15 2015 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Sat, 13 Jun 2015 09:59:15 +0200 (CEST) Subject: MonadFail proposal (MFP): Moving fail out of Monad In-Reply-To: <55776BC4.3050400@gmail.com> References: <55774FF2.8020505@gmail.com> <55776BC4.3050400@gmail.com> Message-ID: On Wed, 10 Jun 2015, David Luposchainsky wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > On 10.06.2015 00:26, Johan Tibell wrote: >> "As a consequence, in current Haskell, you can not use Monad-polymorphic code >> safely, because although it claims to work for all Monads, it might just crash >> on you. This kind of implicit non-totality baked into the class is terrible." >> >> Is this actually a problem in practice? Is there any code we can point to >> that suffers because of the current state of affairs? Could it be included in >> the proposal? > > I don't have hard evidence, but the Monad class being partial strikes me as > pretty backwards in a language where totality and no implicit failures are > important to the programmers. We try our best to advocate not using certain > functions like "head" carelessly, but do-notation comes with similar partiality. As far as I remember, I have never implemented 'fail' in the Monad instances I wrote over the years. Thus, splitting off MonadFail would reward me with more precise type signatures: The constraint (Monad m) would prevent people from calling 'fail' which I have never implemented. From dominic at steinitz.org Sun Jun 14 21:06:39 2015 From: dominic at steinitz.org (Dominic Steinitz) Date: Sun, 14 Jun 2015 21:06:39 +0000 (UTC) Subject: Math in Haddock Message-ID: I thought folks might be interested in a little example of what is now possible in Haddock (assuming my PR is accepted): https://hackage.haskell.org/package/Kalman-0.1.0.1/docs/Kalman.html Anyone wanting to live on the edge can build their own haddock and upload their haddocks manually to hackage: https://github.com/idontgetoutmuch/haddock Dominic Steinitz dominic at steinitz.org http://idontgetoutmuch.wordpress.com From dominic at steinitz.org Sun Jun 14 21:01:10 2015 From: dominic at steinitz.org (Dominic Steinitz) Date: Sun, 14 Jun 2015 22:01:10 +0100 Subject: Math in Haddock Message-ID: <373B6C87-1867-433E-80BC-3F1001DACA1D@steinitz.org> I thought folks might be interested in a little example of what is now possible in Haddock (assuming my PR is accepted): https://hackage.haskell.org/package/Kalman-0.1.0.1/docs/Kalman.html Anyone wanting to live on the edge can build their own haddock and upload their haddocks manually to hackage: https://github.com/idontgetoutmuch/haddock Dominic Steinitz dominic at steinitz.org http://idontgetoutmuch.wordpress.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From dluposchainsky at googlemail.com Tue Jun 16 15:07:50 2015 From: dluposchainsky at googlemail.com (David Luposchainsky) Date: Tue, 16 Jun 2015 17:07:50 +0200 Subject: MFP updates: ideas worth discussing In-Reply-To: <55774FF2.8020505@gmail.com> References: <55774FF2.8020505@gmail.com> Message-ID: <55803BC6.7040706@gmail.com> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 MonadFail proposal update 1 =========================== Rendered version of this text: https://github.com/quchen/articles/blob/master/monad_fail_update1.md Original MFP: https://github.com/quchen/articles/blob/master/monad_fail.md Short summary - ------------- A week has passed since I posted the MFP, and the initial discussion is mostly over. Here are my observations: - - Everyone agrees that `fail` should not be in `Monad`. - - Almost everyone agrees that it should be thrown out of it. - - Some would prefer to see the special desugaring be gone entirely. - - The name `MonadFail` is controversial, because of a potential `Applicative` constraint. - - We're still unsure about whether `IO` should get a `MonadFail` instance, but the bias seems to be towards "yes". New ideas worth thinking about - ------------------------------ ### Special desugaring or not Johann suggested an optional warning whenever something desugars to use `fail`. I think that's an idea we should think about. It is easily implemented in the compiler, and would probably behave similar to -fwarn-unused-do-binds in practice: notation that is not wrong, but might not be what the programmer intended. ### Errors vs. Exceptions Henning is concerned about the confusion between exceptions and programming errors. In his words, > We should clearly decide what "fail" is intended for - for programming > errors or for exceptions. What I see clashing with his point is backwards compatibility. Removing the `String` argument breaks all explicit invocations of `fail`. Unfortunately, we're not in a position to break very much. If someone has a better idea I'd love to hear about it though. ### ApplicativeDo ApplicativeDo is somewhere out there on the horizon, and we're not sure yet how much `fail` makes sense in the context of `Applicative`. An Applicative computation is statically determined in its shape, so it either always or never fails. Depending on previous results would introduce the `Monad` constraint anyway. Probing status - -------------- Henning has started to look at the impact of the proposal when explicit invocations of `fail` are considered as well, something I have not done in my original survey. Luckily, things don't look too bad, Lens and its forest of dependencies can be fixed in around ten trivial changes, for example. Greetings, David/quchen -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAEBAgAGBQJVgDvGAAoJELrQsaT5WQUspmIIAJi9UVYIitHv2CKvWSmk1fg0 hYaPRXDJMnyFS21v57+JeTPhM/dnI4k0guUUrlIB9k5WPaySQ6MKIAnB51o5O9Gv zt87FII5/oYsJtVPruKgBtLPbJVhg6zGUXmNco1S2wvB5m5HdBooQsiBRY+qiFfZ MJOdzXpRCrYJk/0PeF7sglBOElSwsSmGq/klvJUo4VeVAdi8bU+lKRfET/AmAAM5 oqckAI0SEaFo+w6EXBLPiL/F5SoFBmKR50Nu4NKWRBcoNGq7AwvWEKDZeU0PvC3a dykqSnFTRtL5LeWZnByuZTVVqlDG3afjX6ZYkrUbMKQeE9rVf24Gx9jlRusxSds= =zUDu -----END PGP SIGNATURE----- From taruti at taruti.net Wed Jun 17 07:33:32 2015 From: taruti at taruti.net (Taru Karttunen) Date: Wed, 17 Jun 2015 10:33:32 +0300 Subject: Math in Haddock In-Reply-To: References: Message-ID: On 14.06 21:06, Dominic Steinitz wrote: > I thought folks might be interested in a little example of what is now > possible in Haddock (assuming my PR is accepted): > > https://hackage.haskell.org/package/Kalman-0.1.0.1/docs/Kalman.html > Would it be possible to have better degradation for cases with Javascript blocked? - Taru Karttunen From dominic at steinitz.org Wed Jun 17 08:08:21 2015 From: dominic at steinitz.org (Dominic Steinitz) Date: Wed, 17 Jun 2015 09:08:21 +0100 Subject: Math in Haddock In-Reply-To: References: Message-ID: You can install your own copy of mathjax and then use haddock --mathjax=URL. If you prefer something else, let me know and I will see if it is possible to add it. Ah but you are talking about Javascript, a subject about which I am completely ignorant. If you mean your browser does not support Javascript then I am at a loss. Maybe someone on this list can help? Dominic Steinitz dominic at steinitz.org http://idontgetoutmuch.wordpress.com > On 17 Jun 2015, at 08:33, Taru Karttunen wrote: > > On 14.06 21:06, Dominic Steinitz wrote: >> I thought folks might be interested in a little example of what is now >> possible in Haddock (assuming my PR is accepted): >> >> https://hackage.haskell.org/package/Kalman-0.1.0.1/docs/Kalman.html >> > > Would it be possible to have better degradation for cases with > Javascript blocked? > > - Taru Karttunen From abela at chalmers.se Wed Jun 17 12:00:02 2015 From: abela at chalmers.se (Andreas Abel) Date: Wed, 17 Jun 2015 14:00:02 +0200 Subject: zlib-0.6.1 bug? Message-ID: <55816142.9000801@chalmers.se> Agda sees some segmentation faults when compiled with zlib-0.6.1.x, but not with zlib-0.5.4.2. https://code.google.com/p/agda/issues/detail?can=2&q=1518 You might want to constrain zlib < 0.6 for now. (I reported the issue to the maintainer a couple of weeks ago, but have not gotten any response yet.) Cheers, Andreas -- Andreas Abel <>< Du bist der geliebte Mensch. Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden andreas.abel at gu.se http://www2.tcs.ifi.lmu.de/~abel/ From f at mazzo.li Wed Jun 17 12:01:39 2015 From: f at mazzo.li (Francesco Mazzoli) Date: Wed, 17 Jun 2015 14:01:39 +0200 Subject: zlib-0.6.1 bug? In-Reply-To: <55816142.9000801@chalmers.se> References: <55816142.9000801@chalmers.se> Message-ID: That link does not work. This does: https://code.google.com/p/agda/issues/detail?id=1518 . Francesco On 17 June 2015 at 14:00, Andreas Abel wrote: > Agda sees some segmentation faults when compiled with zlib-0.6.1.x, but > not with zlib-0.5.4.2. > > https://code.google.com/p/agda/issues/detail?can=2&q=1518 > > You might want to constrain zlib < 0.6 for now. > > (I reported the issue to the maintainer a couple of weeks ago, but have > not gotten any response yet.) > > Cheers, > Andreas > > -- > Andreas Abel <>< Du bist der geliebte Mensch. > > Department of Computer Science and Engineering > Chalmers and Gothenburg University, Sweden > > andreas.abel at gu.se > http://www2.tcs.ifi.lmu.de/~abel/ > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From asr at eafit.edu.co Wed Jun 17 12:40:17 2015 From: asr at eafit.edu.co (=?UTF-8?B?QW5kcsOpcyBTaWNhcmQtUmFtw61yZXo=?=) Date: Wed, 17 Jun 2015 07:40:17 -0500 Subject: zlib-0.6.1 bug? In-Reply-To: <55816142.9000801@chalmers.se> References: <55816142.9000801@chalmers.se> Message-ID: On 17 June 2015 at 07:00, Andreas Abel wrote: > Agda sees some segmentation faults when compiled with zlib-0.6.1.x, but not > with zlib-0.5.4.2. > > https://code.google.com/p/agda/issues/detail?can=2&q=1518 > > You might want to constrain zlib < 0.6 for now. > > (I reported the issue to the maintainer a couple of weeks ago, but have not > gotten any response yet.) The constrain zlib < 0.6.1 is enough. -- Andr?s From ekmett at gmail.com Wed Jun 17 13:33:31 2015 From: ekmett at gmail.com (Edward Kmett) Date: Wed, 17 Jun 2015 09:33:31 -0400 Subject: MFP updates: ideas worth discussing In-Reply-To: <55803BC6.7040706@gmail.com> References: <55774FF2.8020505@gmail.com> <55803BC6.7040706@gmail.com> Message-ID: There is a bit of a knee-jerk reaction that we should go to something simpler than Monad as a superclass constraint for MonadFail, but I think most of those reasons fall apart or at least lose much of their weight upon deeper inspection. Ultimately, I'm a not concerned about interactions between ApplicativeDo notation and fail. Any automatic desugaring into 'fail' will be in a context which is necessarily incurring a monad constraint. E.g. do Just x <- m ... has to pick up the Monad constraint anyways to deal with the binding! This leaves only code that does something like. foo = x <*> fail y which is hand written to invoke fail. Given that the entire "tree" of the Applicative" is available for inspection and that that fail can't depend on any context internal to the Applicative and remain 'just Applicative' I have a hard time foreseeing any real applications lost by continuing to assume a context of: class Monad m => MonadFail m and there is a lot of value in the simple context. Most of the value in ApplicativeDo notation comes from the opportunities for increased parallelism, not so much from the reduced constraints on the resulting code, and as we can see above, it'll never arise during the desguaring in a place that wouldn't incur a Monad constraint anyways. Even getting rid of the Monad constraint w/ ApplicativeDo is going to require gymnastics around `return`. -Edward P.S. On an unrelated note, for the record, I'm very strongly +1 on a MonadFail instance for IO. There we use throwIO explicitly, so it is even able to be handled and caught locally. The set of things you can do in IO is large enough to support and reason about explicit failure. P.P.S. I think if we extend the proposal to include an explicit member of the class for pattern match failure with the code we currently have lurking in the compiler for producing the string from the context, then most of the concerns raised by folks who would prefer to use a heavier weight -- but vastly harder to standardize -- exception mechanism would also be addressed in practice. On Tue, Jun 16, 2015 at 11:07 AM, David Luposchainsky < dluposchainsky at googlemail.com> wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > MonadFail proposal update 1 > =========================== > > > Rendered version of this text: > https://github.com/quchen/articles/blob/master/monad_fail_update1.md > > Original MFP: > https://github.com/quchen/articles/blob/master/monad_fail.md > > > Short summary > - ------------- > > A week has passed since I posted the MFP, and the initial discussion is > mostly > over. Here are my observations: > > - - Everyone agrees that `fail` should not be in `Monad`. > - - Almost everyone agrees that it should be thrown out of it. > - - Some would prefer to see the special desugaring be gone entirely. > - - The name `MonadFail` is controversial, because of a potential > `Applicative` > constraint. > - - We're still unsure about whether `IO` should get a `MonadFail` > instance, but > the bias seems to be towards "yes". > > > > New ideas worth thinking about > - ------------------------------ > > ### Special desugaring or not > > Johann suggested an optional warning whenever something desugars to use > `fail`. > I think that's an idea we should think about. It is easily implemented in > the > compiler, and would probably behave similar to -fwarn-unused-do-binds in > practice: notation that is not wrong, but might not be what the programmer > intended. > > > ### Errors vs. Exceptions > > Henning is concerned about the confusion between exceptions and programming > errors. In his words, > > > We should clearly decide what "fail" is intended for - for programming > > errors or for exceptions. > > What I see clashing with his point is backwards compatibility. Removing the > `String` argument breaks all explicit invocations of `fail`. Unfortunately, > we're not in a position to break very much. If someone has a better idea > I'd > love to hear about it though. > > > ### ApplicativeDo > > ApplicativeDo is somewhere out there on the horizon, and we're not sure > yet how > much `fail` makes sense in the context of `Applicative`. An Applicative > computation is statically determined in its shape, so it either always or > never > fails. Depending on previous results would introduce the `Monad` constraint > anyway. > > > > Probing status > - -------------- > > Henning has started to look at the impact of the proposal when explicit > invocations of `fail` are considered as well, something I have not done in > my > original survey. Luckily, things don't look too bad, Lens and its forest of > dependencies can be fixed in around ten trivial changes, for example. > > > Greetings, > David/quchen > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1 > > iQEcBAEBAgAGBQJVgDvGAAoJELrQsaT5WQUspmIIAJi9UVYIitHv2CKvWSmk1fg0 > hYaPRXDJMnyFS21v57+JeTPhM/dnI4k0guUUrlIB9k5WPaySQ6MKIAnB51o5O9Gv > zt87FII5/oYsJtVPruKgBtLPbJVhg6zGUXmNco1S2wvB5m5HdBooQsiBRY+qiFfZ > MJOdzXpRCrYJk/0PeF7sglBOElSwsSmGq/klvJUo4VeVAdi8bU+lKRfET/AmAAM5 > oqckAI0SEaFo+w6EXBLPiL/F5SoFBmKR50Nu4NKWRBcoNGq7AwvWEKDZeU0PvC3a > dykqSnFTRtL5LeWZnByuZTVVqlDG3afjX6ZYkrUbMKQeE9rVf24Gx9jlRusxSds= > =zUDu > -----END PGP SIGNATURE----- > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Lennart.Augustsson at sc.com Wed Jun 17 13:39:48 2015 From: Lennart.Augustsson at sc.com (Augustsson, Lennart) Date: Wed, 17 Jun 2015 13:39:48 +0000 Subject: MFP updates: ideas worth discussing In-Reply-To: References: <55774FF2.8020505@gmail.com> <55803BC6.7040706@gmail.com> Message-ID: <22B950C955F8AB4196E72698FBD00002B94BF534@UKWPIPXMB01A.zone1.scb.net> On this issue I totally agree with Ed. ? From: Libraries [mailto:libraries-bounces at haskell.org] On Behalf Of Edward Kmett Sent: 17 June 2015 14:34 To: David Luposchainsky Cc: Haskell Libraries; ghc-devs at haskell.org Subject: Re: MFP updates: ideas worth discussing There is a bit of a knee-jerk reaction that we should go to something simpler than Monad as a superclass constraint for MonadFail, but I think most of those reasons fall apart or at least lose much of their weight upon deeper inspection. Ultimately, I'm a not concerned about interactions between ApplicativeDo notation and fail. Any automatic desugaring into 'fail' will be in a context which is necessarily incurring a monad constraint. E.g. do Just x <- m ... has to pick up the Monad constraint anyways to deal with the binding! This leaves only code that does something like. foo = x <*> fail y which is hand written to invoke fail. Given that the entire "tree" of the Applicative" is available for inspection and that that fail can't depend on any context internal to the Applicative and remain 'just Applicative' I have a hard time foreseeing any real applications lost by continuing to assume a context of: class Monad m => MonadFail m and there is a lot of value in the simple context. Most of the value in ApplicativeDo notation comes from the opportunities for increased parallelism, not so much from the reduced constraints on the resulting code, and as we can see above, it'll never arise during the desguaring in a place that wouldn't incur a Monad constraint anyways. Even getting rid of the Monad constraint w/ ApplicativeDo is going to require gymnastics around `return`. -Edward P.S. On an unrelated note, for the record, I'm very strongly +1 on a MonadFail instance for IO. There we use throwIO explicitly, so it is even able to be handled and caught locally. The set of things you can do in IO is large enough to support and reason about explicit failure. P.P.S. I think if we extend the proposal to include an explicit member of the class for pattern match failure with the code we currently have lurking in the compiler for producing the string from the context, then most of the concerns raised by folks who would prefer to use a heavier weight -- but vastly harder to standardize -- exception mechanism would also be addressed in practice. On Tue, Jun 16, 2015 at 11:07 AM, David Luposchainsky > wrote: -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 MonadFail proposal update 1 =========================== Rendered version of this text: https://github.com/quchen/articles/blob/master/monad_fail_update1.md Original MFP: https://github.com/quchen/articles/blob/master/monad_fail.md Short summary - ------------- A week has passed since I posted the MFP, and the initial discussion is mostly over. Here are my observations: - - Everyone agrees that `fail` should not be in `Monad`. - - Almost everyone agrees that it should be thrown out of it. - - Some would prefer to see the special desugaring be gone entirely. - - The name `MonadFail` is controversial, because of a potential `Applicative` constraint. - - We're still unsure about whether `IO` should get a `MonadFail` instance, but the bias seems to be towards "yes". New ideas worth thinking about - ------------------------------ ### Special desugaring or not Johann suggested an optional warning whenever something desugars to use `fail`. I think that's an idea we should think about. It is easily implemented in the compiler, and would probably behave similar to -fwarn-unused-do-binds in practice: notation that is not wrong, but might not be what the programmer intended. ### Errors vs. Exceptions Henning is concerned about the confusion between exceptions and programming errors. In his words, > We should clearly decide what "fail" is intended for - for programming > errors or for exceptions. What I see clashing with his point is backwards compatibility. Removing the `String` argument breaks all explicit invocations of `fail`. Unfortunately, we're not in a position to break very much. If someone has a better idea I'd love to hear about it though. ### ApplicativeDo ApplicativeDo is somewhere out there on the horizon, and we're not sure yet how much `fail` makes sense in the context of `Applicative`. An Applicative computation is statically determined in its shape, so it either always or never fails. Depending on previous results would introduce the `Monad` constraint anyway. Probing status - -------------- Henning has started to look at the impact of the proposal when explicit invocations of `fail` are considered as well, something I have not done in my original survey. Luckily, things don't look too bad, Lens and its forest of dependencies can be fixed in around ten trivial changes, for example. Greetings, David/quchen -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAEBAgAGBQJVgDvGAAoJELrQsaT5WQUspmIIAJi9UVYIitHv2CKvWSmk1fg0 hYaPRXDJMnyFS21v57+JeTPhM/dnI4k0guUUrlIB9k5WPaySQ6MKIAnB51o5O9Gv zt87FII5/oYsJtVPruKgBtLPbJVhg6zGUXmNco1S2wvB5m5HdBooQsiBRY+qiFfZ MJOdzXpRCrYJk/0PeF7sglBOElSwsSmGq/klvJUo4VeVAdi8bU+lKRfET/AmAAM5 oqckAI0SEaFo+w6EXBLPiL/F5SoFBmKR50Nu4NKWRBcoNGq7AwvWEKDZeU0PvC3a dykqSnFTRtL5LeWZnByuZTVVqlDG3afjX6ZYkrUbMKQeE9rVf24Gx9jlRusxSds= =zUDu -----END PGP SIGNATURE----- _______________________________________________ Libraries mailing list Libraries at haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries This email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please delete all copies and notify the sender immediately. You may wish to refer to the incorporation details of Standard Chartered PLC, Standard Chartered Bank and their subsidiaries at http://www.standardchartered.com/en/incorporation-details.html Insofar as this communication contains any market commentary, the market commentary has been prepared by a sales and/or trading desk of Standard Chartered Bank or its affiliate. It is not and does not constitute research material, independent research, recommendation or financial advice. Any market commentary is for information purpose only and shall not be relied for any other purpose, and is subject to the relevant disclaimers available at http://wholesalebanking.standardchartered.com/en/utility/Pages/d-mkt.aspx Please visit http://wholesalebanking.standardchartered.com/en/capabilities/financialmarkets/Pages/doddfrankdisclosures.aspx for important information with respect to derivative products. -------------- next part -------------- An HTML attachment was scrubbed... URL: From petr.mvd at gmail.com Wed Jun 17 20:03:56 2015 From: petr.mvd at gmail.com (=?UTF-8?B?UGV0ciBQdWRsw6Fr?=) Date: Wed, 17 Jun 2015 22:03:56 +0200 Subject: SHA sums of cabal-install binaries Message-ID: Hi, are the SHA sums of cabal-install binaries available somewhere? GHC provides them on the download pages, but I couldn't find them anywhere for cabal-install. If not, would it be possible to provide them? Thanks, Petr -------------- next part -------------- An HTML attachment was scrubbed... URL: From hvr at gnu.org Thu Jun 18 08:32:05 2015 From: hvr at gnu.org (Herbert Valerio Riedel) Date: Thu, 18 Jun 2015 10:32:05 +0200 Subject: Native -XCPP Conclusion (was: RFC: "Native -XCPP" Proposal) In-Reply-To: <87zj5i55gs.fsf@gmail.com> (Herbert Valerio Riedel's message of "Wed, 06 May 2015 13:08:03 +0200") References: <87zj5i55gs.fsf@gmail.com> Message-ID: <87oakdo1ru.fsf@gmail.com> Hello *, Following up on the "Native -XCPP" Proposal discussion, it appears that cpphs' current LGPL+SLE licensing doesn't pose an *objective* showstopper problem but is rather more of an inconvenience as it causes argumentation/discussion overhead (which then /may/ actually result in Haskell being turned down eventually over alternatives that do without LGPL components). In order to acknowledge this discomfort, for GHC 7.12 we propose to follow "plan 4" according to [1] (i.e. calling out to a cpphs-executable as a separate process), thereby avoiding pulling any LGPL-subjected cpphs code into produced executables when linking against the 'ghc' package. "Plan 2" (i.e. embedding/linking cpphs' code directly into ghc) would reduce fork/exec overhead, which can be substantial on Windows [2], but plan 4 is no worse than what we have now. Last Call: Are there any objections with GHC adopting "plan 4"[1]? [1]: [2]: Thanks, HVR On 2015-05-06 at 13:08:03 +0200, Herbert Valerio Riedel wrote: > Hello *, > > As you may be aware, GHC's `{-# LANGUAGE CPP #-}` language extension > currently relies on the system's C-compiler bundled `cpp` program to > provide a "traditional mode" c-preprocessor. > > This has caused several problems in the past, since parsing Haskell code > with a preprocessor mode designed for use with C's tokenizer has caused > already quite some problems[1] in the past. I'd like to see GHC 7.12 > adopt an implemntation of `-XCPP` that does not rely on the shaky > system-`cpp` foundation. To this end I've created a wiki page > > https://ghc.haskell.org/trac/ghc/wiki/Proposal/NativeCpp > > to describe the actual problems in more detail, and a couple of possible > ways forward. Ideally, we'd simply integrate `cpphs` into GHC > (i.e. "plan 2"). However, due to `cpp`s non-BSD3 license this should be > discussed and debated since affects the overall-license of the GHC > code-base, which may or may not be a problem to GHC's user-base (and > that's what I hope this discussion will help to find out). > > So please go ahead and read the Wiki page... and then speak your mind! > > > Thanks, > HVR > > > [1]: ...does anybody remember the issues Haskell packages (& GHC) > encountered when Apple switched to the Clang tool-chain, thereby > causing code using `-XCPP` to suddenly break due to subtly > different `cpp`-semantics? -- "Elegance is not optional" -- Richard O'Keefe From andre.van.delden at uni-bremen.de Thu Jun 18 10:27:32 2015 From: andre.van.delden at uni-bremen.de (=?ISO-8859-1?Q?Andr=E9?= van Delden) Date: Thu, 18 Jun 2015 12:27:32 +0200 Subject: No way to retrieve the base of a Set or Map in O(1) Message-ID: <1434623252.28835.9.camel@uni-bremen.de> Hello, there seems to be no way to retrieve the base of a Set or Map in O(1), since there is no relevant function in the respective libraries and the constructors Bin and Tip are not exported in any module. I think retrieving any one element from a Set or Map might be useful sometimes, so I modestly ask for an implementation. I see that there is splitRoot, but the docs advice, not to rely on the current form of the resulting list, since it might be subject to change. Having this function, with its current result, it might be interesting to be able to efficiently build the union of the lower and the upper parts by simply connecting the trees at their bases. What do you think? Kind regards, Andr? From ivan.miljenovic at gmail.com Thu Jun 18 11:00:27 2015 From: ivan.miljenovic at gmail.com (Ivan Lazar Miljenovic) Date: Thu, 18 Jun 2015 21:00:27 +1000 Subject: No way to retrieve the base of a Set or Map in O(1) In-Reply-To: <1434623252.28835.9.camel@uni-bremen.de> References: <1434623252.28835.9.camel@uni-bremen.de> Message-ID: On 18 June 2015 at 20:27, Andr? van Delden wrote: > Hello, > > there seems to be no way to retrieve the base of a Set or Map in O(1), > since there is no relevant function in the respective libraries and the > constructors Bin and Tip are not exported in any module. > I think retrieving any one element from a Set or Map might be useful > sometimes, so I modestly ask for an implementation. For Set there's minView and maxView. For Map there's both {min,max}View (which returns only the value) and also {min,max}ViewWithKey which also returns the key. These are admittedly all O(log n) though. I suppose the reason for there being no way to obtain the root value is that it would be both implementation and creation (as in how the Set/Map was created, due to there being no balancing IIRC) dependent, and thus difficult to use in any reliable/reproducible fashion. -- Ivan Lazar Miljenovic Ivan.Miljenovic at gmail.com http://IvanMiljenovic.wordpress.com From fox at ucw.cz Thu Jun 18 11:01:14 2015 From: fox at ucw.cz (Milan Straka) Date: Thu, 18 Jun 2015 13:01:14 +0200 Subject: No way to retrieve the base of a Set or Map in O(1) In-Reply-To: <1434623252.28835.9.camel@uni-bremen.de> References: <1434623252.28835.9.camel@uni-bremen.de> Message-ID: <20150618110114.GA14492@auryn.cz> Hi Andr?, > -----Original message----- > From: Andr? van Delden > Sent: 18 Jun 2015, 12:27 > > there seems to be no way to retrieve the base of a Set or Map in O(1), > since there is no relevant function in the respective libraries and the > constructors Bin and Tip are not exported in any module. > I think retrieving any one element from a Set or Map might be useful > sometimes, so I modestly ask for an implementation. do you have any use-case where such function is useful? I am having troubles imagining one. Also note that for IntMap and IntSet you cannot provide such function. To me, this seems more like accessing the internal representation. There have been some discussions about exporting the internal representations in an Unsafe module, which would have no API guarantees (i.e., have Data.Set.Unsafe exporting the Set constructor). Do you really want the proposed function, or would you be more interested in accessing the internal representation? Cheers, Milan From ivan.miljenovic at gmail.com Thu Jun 18 11:09:41 2015 From: ivan.miljenovic at gmail.com (Ivan Lazar Miljenovic) Date: Thu, 18 Jun 2015 21:09:41 +1000 Subject: No way to retrieve the base of a Set or Map in O(1) In-Reply-To: <20150618110114.GA14492@auryn.cz> References: <1434623252.28835.9.camel@uni-bremen.de> <20150618110114.GA14492@auryn.cz> Message-ID: On 18 June 2015 at 21:01, Milan Straka wrote: > > do you have any use-case where such function is useful? I am having > troubles imagining one. In fgl we need to be able to obtain a "random" value for the matchAny function, which currently uses minView. I wouldn't mind an O(1) variant for both both Map and IntMap, but minView works well enough. -- Ivan Lazar Miljenovic Ivan.Miljenovic at gmail.com http://IvanMiljenovic.wordpress.com From andre.van.delden at uni-bremen.de Thu Jun 18 12:53:33 2015 From: andre.van.delden at uni-bremen.de (=?ISO-8859-1?Q?Andr=E9?= van Delden) Date: Thu, 18 Jun 2015 14:53:33 +0200 Subject: No way to retrieve the base of a Set or Map in O(1) In-Reply-To: <20150618110114.GA14492@auryn.cz> References: <1434623252.28835.9.camel@uni-bremen.de> <20150618110114.GA14492@auryn.cz> Message-ID: <1434632013.28835.17.camel@uni-bremen.de> Hello, > do you have any use-case where such function is useful? I am trying to generalize some combinatorial functions to a class of types containing any sort of element. For many combinatorial functions it is useful to split the elements at some element and recombine them after a recursion over the parts. That's what I was thinking of. But others seem to be interested aswell (although it is a beginner asking, so there might be a better solution to his problem): http://osdir.com/ml/beginners at haskell.org/2015-03/msg00091.html Kind regards, Andr? From ivan.miljenovic at gmail.com Thu Jun 18 13:01:02 2015 From: ivan.miljenovic at gmail.com (Ivan Lazar Miljenovic) Date: Thu, 18 Jun 2015 23:01:02 +1000 Subject: No way to retrieve the base of a Set or Map in O(1) In-Reply-To: <1434632013.28835.17.camel@uni-bremen.de> References: <1434623252.28835.9.camel@uni-bremen.de> <20150618110114.GA14492@auryn.cz> <1434632013.28835.17.camel@uni-bremen.de> Message-ID: On 18 June 2015 at 22:53, Andr? van Delden wrote: > Hello, > > >> do you have any use-case where such function is useful? > > I am trying to generalize some combinatorial functions to a class of > types containing any sort of element. For many combinatorial functions > it is useful to split the elements at some element and recombine them > after a recursion over the parts. That's what I was thinking of. > > But others seem to be interested aswell (although it is a beginner > asking, so there might be a better solution to his problem): > > http://osdir.com/ml/beginners at haskell.org/2015-03/msg00091.html minView applies to that one as well. -- Ivan Lazar Miljenovic Ivan.Miljenovic at gmail.com http://IvanMiljenovic.wordpress.com From marcin.jan.mrotek at gmail.com Sat Jun 20 09:04:49 2015 From: marcin.jan.mrotek at gmail.com (Marcin Mrotek) Date: Sat, 20 Jun 2015 11:04:49 +0200 Subject: MFP updates: ideas worth discussing In-Reply-To: <55803BC6.7040706@gmail.com> References: <55774FF2.8020505@gmail.com> <55803BC6.7040706@gmail.com> Message-ID: Hello, Are people actually using the string argument for anything else than throwing an error message into the user's face? (I've always seen Either String as a bit of a hack)? If not, I think it would be best to leave fail to errors (as in IO), and desugar failed pattern matches to mempty/empty instead. Best regards, Marcin Mrotek -------------- next part -------------- An HTML attachment was scrubbed... URL: From grantslatton at gmail.com Sun Jun 21 06:32:08 2015 From: grantslatton at gmail.com (Grant Slatton) Date: Sat, 20 Jun 2015 23:32:08 -0700 Subject: Proposal to generalize the type of List's deleteBy function Message-ID: Right now the type of deleteBy is: (a -> a -> Bool) -> a -> [a] -> [a] That is, it takes an equality predicate, a value, and a list, and deletes the first element in the list such that the equality predicate returns true for the given value and the element. This can be generalized to: (a -> b -> Bool) -> a -> [b] -> [b] Example use case: keyValues :: [(a, b)] key :: a deleteBy (\x (y, _) -> x == y) key keyValues Thanks Grant Slatton -------------- next part -------------- An HTML attachment was scrubbed... URL: From abela at chalmers.se Sun Jun 21 15:30:18 2015 From: abela at chalmers.se (Andreas Abel) Date: Sun, 21 Jun 2015 17:30:18 +0200 Subject: Proposal to generalize the type of List's deleteBy function In-Reply-To: References: Message-ID: <5586D88A.2050006@chalmers.se> +1. On 21.06.2015 08:32, Grant Slatton wrote: > Right now the type of deleteBy is: > > (a -> a -> Bool) -> a -> [a] -> [a] > > That is, it takes an equality predicate, a value, and a list, and > deletes the first element in the list such that the equality predicate > returns true for the given value and the element. > > This can be generalized to: > > (a -> b -> Bool) -> a -> [b] -> [b] > > > Example use case: > > keyValues :: [(a, b)] > > key :: a > > deleteBy (\x (y, _) -> x == y) key keyValues > > > > Thanks > > Grant Slatton > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -- Andreas Abel <>< Du bist der geliebte Mensch. Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden andreas.abel at gu.se http://www2.tcs.ifi.lmu.de/~abel/ From david.feuer at gmail.com Sun Jun 21 15:35:42 2015 From: david.feuer at gmail.com (David Feuer) Date: Sun, 21 Jun 2015 11:35:42 -0400 Subject: Proposal to generalize the type of List's deleteBy function In-Reply-To: References: Message-ID: +1, but what's wrong with just whatever::(a->Bool)->[a]->[a] Is this some subtle efficiency thing relating to closure creation? On Jun 21, 2015 2:32 AM, "Grant Slatton" wrote: > Right now the type of deleteBy is: > > (a -> a -> Bool) -> a -> [a] -> [a] > > That is, it takes an equality predicate, a value, and a list, and deletes > the first element in the list such that the equality predicate returns true > for the given value and the element. > > This can be generalized to: > > (a -> b -> Bool) -> a -> [b] -> [b] > > > Example use case: > > keyValues :: [(a, b)] > > key :: a > > deleteBy (\x (y, _) -> x == y) key keyValues > > > > Thanks > > Grant Slatton > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From grantslatton at gmail.com Sun Jun 21 18:27:00 2015 From: grantslatton at gmail.com (Grant Slatton) Date: Sun, 21 Jun 2015 11:27:00 -0700 Subject: Proposal to generalize the type of List's deleteBy function In-Reply-To: References: Message-ID: When I was talking about this on the IRC channel, I actually mentioned that I'd prefer (a -> Bool) -> [a] -> [a]. I guess you'd call that filterFirst or something. Edward Kmett mentioned on IRC that all the fooBy functions follow a pattern, which is why deleteBy isn't like that. On Sunday, June 21, 2015, David Feuer wrote: > +1, but what's wrong with just > > whatever::(a->Bool)->[a]->[a] > > Is this some subtle efficiency thing relating to closure creation? > On Jun 21, 2015 2:32 AM, "Grant Slatton" > wrote: > >> Right now the type of deleteBy is: >> >> (a -> a -> Bool) -> a -> [a] -> [a] >> >> That is, it takes an equality predicate, a value, and a list, and deletes >> the first element in the list such that the equality predicate returns true >> for the given value and the element. >> >> This can be generalized to: >> >> (a -> b -> Bool) -> a -> [b] -> [b] >> >> >> Example use case: >> >> keyValues :: [(a, b)] >> >> key :: a >> >> deleteBy (\x (y, _) -> x == y) key keyValues >> >> >> >> Thanks >> >> Grant Slatton >> >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From ivan.miljenovic at gmail.com Mon Jun 22 13:21:18 2015 From: ivan.miljenovic at gmail.com (Ivan Lazar Miljenovic) Date: Mon, 22 Jun 2015 23:21:18 +1000 Subject: ANNOUNCE: fgl-arbitrary Message-ID: I've just released the first version of fgl-arbitrary [1], which provides Arbitrary instances for fgl graphs for use with QuickCheck. Also provided are some wrapper newtypes to produce specific types of graphs, and also the ability to generate just valid node and edge lists for use with other graph-like data structures. [1]: http://hackage.haskell.org/package/fgl-arbitrary -- Ivan Lazar Miljenovic Ivan.Miljenovic at gmail.com http://IvanMiljenovic.wordpress.com From philip at mailworks.org Wed Jun 24 04:07:26 2015 From: philip at mailworks.org (Philip White) Date: Tue, 23 Jun 2015 21:07:26 -0700 Subject: Cabal cannot resolve dependencies for my Yesod website Message-ID: <743F84D2-693E-4801-A51C-E8AC9E876E46@mailworks.org> Hello, all, I am trying to make the next big thing with Yesod -- but for now, just a Hello World website. After getting it running locally, I tried to integrate it with Circle CI, which has support for cabal-based Haskell projects. Circle CI runs the following commands: cabal sandbox init cabal install --upgrade-dependencies --constraint="template-haskell installed" --dependencies-only --enable-tests With this invocation, cabal cannot resolve dependencies no matter how I change the cabal config. If, however, I run just `cabal install`, everything works. This cabal failure occurs both on a CircleCI host and my laptop exactly the same way, so I know it's not my environment. I wrote a StackOverflow question with more details: http://stackoverflow.com/questions/31010999/cabal-cannot-resolve-dependencies-chooses-wrong-version-of-containers The github repo, for ease of reproducing the problem: https://github.com/philipmw/yesod-website I hope that someone on the list is able to help. Thanks. -- Philip From michael at snoyman.com Wed Jun 24 04:47:13 2015 From: michael at snoyman.com (Michael Snoyman) Date: Wed, 24 Jun 2015 04:47:13 +0000 Subject: Cabal cannot resolve dependencies for my Yesod website In-Reply-To: <743F84D2-693E-4801-A51C-E8AC9E876E46@mailworks.org> References: <743F84D2-693E-4801-A51C-E8AC9E876E46@mailworks.org> Message-ID: I answered on Stack Overflow, but copying here: This looks like a typical cabal dependency solver shortcoming. Can you try running again with `--max-backjumps=-1 --reorder-goals`? On Wed, Jun 24, 2015 at 7:07 AM Philip White wrote: > Hello, all, > > I am trying to make the next big thing with Yesod -- but for now, just a > Hello World website. After getting it running locally, I tried to integrate > it with Circle CI, which has support for cabal-based Haskell projects. > > Circle CI runs the following commands: > cabal sandbox init > cabal install --upgrade-dependencies --constraint="template-haskell > installed" --dependencies-only --enable-tests > > With this invocation, cabal cannot resolve dependencies no matter how I > change the cabal config. If, however, I run just `cabal install`, > everything works. > > This cabal failure occurs both on a CircleCI host and my laptop exactly > the same way, so I know it's not my environment. > > I wrote a StackOverflow question with more details: > http://stackoverflow.com/questions/31010999/cabal-cannot-resolve-dependencies-chooses-wrong-version-of-containers > > The github repo, for ease of reproducing the problem: > https://github.com/philipmw/yesod-website > > I hope that someone on the list is able to help. Thanks. > > -- > Philip > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From philip at mailworks.org Wed Jun 24 05:03:35 2015 From: philip at mailworks.org (Philip White) Date: Tue, 23 Jun 2015 22:03:35 -0700 Subject: Cabal cannot resolve dependencies for my Yesod website In-Reply-To: References: <743F84D2-693E-4801-A51C-E8AC9E876E46@mailworks.org> Message-ID: Thanks for the quick reply. With your arguments, it worked! But that cabal invocation (without the add'l args) is set by CircleCI. From my brief research, both of the arguments you suggest result in more successful dependency resolutions, at the potential expense of time. Sounds like a good case for CircleCI to start passing these arguments to all Haskell projects by default. I'll contact them about this. > On Jun 23, 2015, at 9:47 PM, Michael Snoyman wrote: > > I answered on Stack Overflow, but copying here: > > This looks like a typical cabal dependency solver shortcoming. Can you try running again with `--max-backjumps=-1 --reorder-goals`? > > On Wed, Jun 24, 2015 at 7:07 AM Philip White > wrote: > Hello, all, > > I am trying to make the next big thing with Yesod -- but for now, just a Hello World website. After getting it running locally, I tried to integrate it with Circle CI, which has support for cabal-based Haskell projects. > > Circle CI runs the following commands: > cabal sandbox init > cabal install --upgrade-dependencies --constraint="template-haskell installed" --dependencies-only --enable-tests > > With this invocation, cabal cannot resolve dependencies no matter how I change the cabal config. If, however, I run just `cabal install`, everything works. > > This cabal failure occurs both on a CircleCI host and my laptop exactly the same way, so I know it's not my environment. > > I wrote a StackOverflow question with more details: http://stackoverflow.com/questions/31010999/cabal-cannot-resolve-dependencies-chooses-wrong-version-of-containers > > The github repo, for ease of reproducing the problem: https://github.com/philipmw/yesod-website > > I hope that someone on the list is able to help. Thanks. > > -- > Philip > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries -------------- next part -------------- An HTML attachment was scrubbed... URL: From greg at gregweber.info Wed Jun 24 16:20:06 2015 From: greg at gregweber.info (Greg Weber) Date: Wed, 24 Jun 2015 09:20:06 -0700 Subject: Cabal cannot resolve dependencies for my Yesod website In-Reply-To: References: <743F84D2-693E-4801-A51C-E8AC9E876E46@mailworks.org> Message-ID: I don't think this would be a good default for CircleCI. If you can install your dependencies once, then you can run `cabal freeze` and check in the resulting cabal.config which will allow cabal to install the packages immediately. On Tue, Jun 23, 2015 at 10:03 PM, Philip White wrote: > Thanks for the quick reply. With your arguments, it worked! But that cabal > invocation (without the add'l args) is set by CircleCI. > > From my brief research, both of the arguments you suggest result in more > successful dependency resolutions, at the potential expense of time. Sounds > like a good case for CircleCI to start passing these arguments to all > Haskell projects by default. I'll contact them about this. > > > On Jun 23, 2015, at 9:47 PM, Michael Snoyman wrote: > > I answered on Stack Overflow, but copying here: > > This looks like a typical cabal dependency solver shortcoming. Can you try > running again with `--max-backjumps=-1 --reorder-goals`? > > On Wed, Jun 24, 2015 at 7:07 AM Philip White wrote: > >> Hello, all, >> >> I am trying to make the next big thing with Yesod -- but for now, just a >> Hello World website. After getting it running locally, I tried to integrate >> it with Circle CI, which has support for cabal-based Haskell projects. >> >> Circle CI runs the following commands: >> cabal sandbox init >> cabal install --upgrade-dependencies --constraint="template-haskell >> installed" --dependencies-only --enable-tests >> >> With this invocation, cabal cannot resolve dependencies no matter how I >> change the cabal config. If, however, I run just `cabal install`, >> everything works. >> >> This cabal failure occurs both on a CircleCI host and my laptop exactly >> the same way, so I know it's not my environment. >> >> I wrote a StackOverflow question with more details: >> http://stackoverflow.com/questions/31010999/cabal-cannot-resolve-dependencies-chooses-wrong-version-of-containers >> >> The github repo, for ease of reproducing the problem: >> https://github.com/philipmw/yesod-website >> >> I hope that someone on the list is able to help. Thanks. >> >> -- >> Philip >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hvr at gnu.org Fri Jun 26 16:08:57 2015 From: hvr at gnu.org (Herbert Valerio Riedel) Date: Fri, 26 Jun 2015 18:08:57 +0200 Subject: Abstract FilePath Proposal Message-ID: <874mlu8nae.fsf@gnu.org> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hello *, What? ===== We (see From: & CC: headers) propose, plain and simple, to turn the currently defined type-synonym type FilePath = String into an abstract/opaque data type instead. Why/How/When? ============= For details (including motivation and a suggested transition scheme) please consult https://ghc.haskell.org/trac/ghc/wiki/Proposal/AbstractFilePath Suggested discussion period: 4 weeks -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAEBAgAGBQJVjXkZAAoJELo8uj/+IrV0WXUP/0romoKazwLbQpaMAKgCNZon BsY8Di44w6rkbdBXoky0xZooII8LJJyQfexH0BLRYEVLZFy0+LB8XzpPt8Ekg526 YlY4x0qFm9oiJbJDMqHUnb6z6Lr2KxzBcV37drTPbltUA+HB49DUVkkPbvHimpL2 28SIyhAr4fN6fLpGcFAkv6Rcs0mkvnTp7vsC0HNyshmGi6qQ+C+eB4mklQzWOPcn koHZ2wtI8AJmyTdHKcXKAIFM0r+xl4MJ5445IvDjvIuGXZCzybXMw9Ss/4wSG3VN qSIJVEDGZXrBCc12fPxPEB0Bqx9MIVytjplXKIo8rFrk93h3at9t9kDM26z+9PZ5 KYnEdjRKF4KL4j+3xqJDOEJT15GVRbGRRzb9A8xH0YIQ0S3Q3pt1PAfla1Hss75+ NRQgfowZYryL9dfCkAj2XNfdQ+pUk25N3bNig11se+zjk2JO77QRM0u3GOYZ9+CU tSlwhtIMF32xnjgQyWE5yBBiEg3/Y+S+809tVaPseUEzkQJXMGq5TFxBrN6bj1Vm awr6QghThKjeoRwky5bmFn/gept/lbYN6VV5B6gNznGP5xgFrmvVtmjbQJBRMYCv aEUnrYqxkkbIddJjD5gl771/LWH4M2F1yBgJjfiZw2paEVAXKxEr327LsbOQaPdb HjIPRrJbVK9AABo4AZ/Y =lg0o -----END PGP SIGNATURE----- From lemming at henning-thielemann.de Fri Jun 26 16:16:45 2015 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Fri, 26 Jun 2015 18:16:45 +0200 (CEST) Subject: Abstract FilePath Proposal In-Reply-To: <874mlu8nae.fsf@gnu.org> References: <874mlu8nae.fsf@gnu.org> Message-ID: On Fri, 26 Jun 2015, Herbert Valerio Riedel wrote: > What? > ===== > > We (see From: & CC: headers) propose, plain and simple, to turn the > currently defined type-synonym > > type FilePath = String > > into an abstract/opaque data type instead. Has someone else tried the pathtype package? http://hackage.haskell.org/package/pathtype I found its idea great, but in practice I could not use it because it always tries to canonicalize paths on initialization. From lemming at henning-thielemann.de Fri Jun 26 16:22:16 2015 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Fri, 26 Jun 2015 18:22:16 +0200 (CEST) Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> Message-ID: On Fri, 26 Jun 2015, Henning Thielemann wrote: > On Fri, 26 Jun 2015, Herbert Valerio Riedel wrote: > >> What? >> ===== >> >> We (see From: & CC: headers) propose, plain and simple, to turn the >> currently defined type-synonym >> >> type FilePath = String >> >> into an abstract/opaque data type instead. > > Has someone else tried the pathtype package? > http://hackage.haskell.org/package/pathtype Hm, your last point "Decisions assumed by this Proposal" seems to mean, that you want to leave out more specialised types from this proposal. That is, dir/file distinction might be defined on top of the new FilePath type. From hvr at gnu.org Sat Jun 27 07:36:22 2015 From: hvr at gnu.org (Herbert Valerio Riedel) Date: Sat, 27 Jun 2015 09:36:22 +0200 Subject: Abstract FilePath Proposal In-Reply-To: (Henning Thielemann's message of "Fri, 26 Jun 2015 18:22:16 +0200 (CEST)") References: <874mlu8nae.fsf@gnu.org> Message-ID: <87fv5dr4ax.fsf@gnu.org> On 2015-06-26 at 18:22:16 +0200, Henning Thielemann wrote: [...] >>> type FilePath = String >>> >>> into an abstract/opaque data type instead. >> >> Has someone else tried the pathtype package? >> http://hackage.haskell.org/package/pathtype > > Hm, your last point "Decisions assumed by this Proposal" seems to > mean, that you want to leave out more specialised types from this > proposal. That is, dir/file distinction might be defined on top of the > new FilePath type. Yes, because the proposal is meant to only make the smallest incremental change needed (i.e. change FilePath datatype, provide conversion functions) to to achieve the primary goals (reduce space/time overhead & make it a distinct type from String) in a way suitable for a future Haskell Report, while trying to stay close enough that you can still write code that works with both the H2010 and a AFPP definition of `FilePath` Trying to redesign the FilePath type to also include dir/file distinction seemed too daunting, as there's quite some additional design-space area to explore (do drive-letters deserve a separate type? do we use DataKinds? What invariants can/shall be represented at the type-level? what errors are caught at the type-level, which are caught at runtime? etc...), parts of which may require type-system extensions, while just having a KISS-style opaque FilePath evades this. From hvr at gnu.org Sat Jun 27 07:54:30 2015 From: hvr at gnu.org (Herbert Valerio Riedel) Date: Sat, 27 Jun 2015 09:54:30 +0200 Subject: Abstract FilePath Proposal In-Reply-To: (Bardur Arantsson's message of "Sat, 27 Jun 2015 03:30:56 +0200") References: <874mlu8nae.fsf@gnu.org> Message-ID: <87bng1r3gp.fsf@gnu.org> On 2015-06-27 at 03:30:56 +0200, Bardur Arantsson wrote: [...] > I am *entirely* behind this in priciple and if it doesn't break too much > of Hackage, also in practice, but... > > ... how much of Hackage *does* this break? This won't be for free: I expect most packages which currently do more than just opaquely pass around FilePaths to require fixes. Some examples: - `writeFile "doo/foo.bar" ...` `_ <- readFile ("doo" "foo" <.> "bar")` This will break unless -XOverloadedStrings happens to be enabled - Unless we generalise (++) to (<>), all cases where `FilePath`s are concatenated via (++) will break. - Code that uses Data.List rather than the `filepath` package for FilePath manipulation will need fixups (simplest fix: explicitly convert to/from String for the manipulation) - Some code, like e.g. fnames <- System.Environment.getArgs forM fnames $ \fn -> print =<< readFile fn will inevitably need to insert explicit conversions to/from FilePaths I tried to simulate the effect on Hackage, but this turned out to be more time-demanding than I hoped for and I had to abort. But the above is what I encountered in my attempt. > The reason that I'm in favor in principle is that paths really *are* > opaque things -- platforms have entirely different conventions. AFAICT > the only thing that they seem to agree on is that there is a "hierarchy" > of some sort. (And not much else, including such things as case > (in-)sensivity or character sets.). > For example, in POSIX they're just strings of bytes without any > specified encoding, and I'd love if they could be make to work like > that when dealing with files in Haskell. Yes, if you look e.g. at http://hackage.haskell.org/package/unix you see a lot of API duplication, which wouldn't have been needed if FilePath was an opaque type w/ lossless conversion to/from ByteString. From mail at joachim-breitner.de Sat Jun 27 08:05:02 2015 From: mail at joachim-breitner.de (Joachim Breitner) Date: Sat, 27 Jun 2015 10:05:02 +0200 Subject: Abstract FilePath Proposal In-Reply-To: <874mlu8nae.fsf@gnu.org> References: <874mlu8nae.fsf@gnu.org> Message-ID: <1435392302.1459.9.camel@joachim-breitner.de> Hi, Am Freitag, den 26.06.2015, 18:08 +0200 schrieb Herbert Valerio Riedel: > Why/How/When? > ============= > > For details (including motivation and a suggested transition scheme) > please consult > > https://ghc.haskell.org/trac/ghc/wiki/Proposal/AbstractFilePath > unless proven wrong, I assume that this breaks lots of code. So by default, I am doubtful towards that proposal. Also, the argument about inefficiency does not convince me. In a Prelude where "type String = [Char]", this is ? as bad as it may be ? consistent and expected. Just like you manually have to reach out for dedicated string types if you want efficient Haskell, you can manually reach out for dedicated FilePath libraries. I doubt that it is a good idea to fix the String problem in small, isolated chunks. However, the argument that, depending on the system, "type FilePath = String" is simply wrong (because the semantics of file paths are not unicode points), is one that I buy in. On such systems, the Prelude is, in a moral sense, wrongly typed, and the situation is comparable to a hypothetical "type String = [Word8]" ? which is just wrong in a world of unicode. So for me, the faithful representation of system filepaths makes this proposal interesting. I like it when Haskell ?gets it right?. So if the transition can be made somewhat smooth, I?m leaning towards supporting it. Greetings, Joachim -- Joachim ?nomeata? Breitner mail at joachim-breitner.de ? http://www.joachim-breitner.de/ Jabber: nomeata at joachim-breitner.de ? GPG-Key: 0xF0FBF51F Debian Developer: nomeata at debian.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: This is a digitally signed message part URL: From metaniklas at gmail.com Sat Jun 27 09:33:21 2015 From: metaniklas at gmail.com (Niklas Larsson) Date: Sat, 27 Jun 2015 11:33:21 +0200 Subject: SV: Abstract FilePath Proposal In-Reply-To: <874mlu8nae.fsf@gnu.org> References: <874mlu8nae.fsf@gnu.org> Message-ID: <558e6de1.63a6700a.5f03.2b03@mx.google.com> Hi! Instead of trying to minimally patch the existing API and still breaking loads of code, why not make a new API that doesn't have to compromise and depreciate the old one? Niklas ----- Ursprungligt meddelande ----- Fr?n: "Herbert Valerio Riedel" Skickat: ?2015-?06-?26 18:09 Till: "libraries at haskell.org" ; "ghc-devs at haskell.org" ?mne: Abstract FilePath Proposal -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hello *, What? ===== We (see From: & CC: headers) propose, plain and simple, to turn the currently defined type-synonym type FilePath = String into an abstract/opaque data type instead. Why/How/When? ============= For details (including motivation and a suggested transition scheme) please consult https://ghc.haskell.org/trac/ghc/wiki/Proposal/AbstractFilePath Suggested discussion period: 4 weeks -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAEBAgAGBQJVjXkZAAoJELo8uj/+IrV0WXUP/0romoKazwLbQpaMAKgCNZon BsY8Di44w6rkbdBXoky0xZooII8LJJyQfexH0BLRYEVLZFy0+LB8XzpPt8Ekg526 YlY4x0qFm9oiJbJDMqHUnb6z6Lr2KxzBcV37drTPbltUA+HB49DUVkkPbvHimpL2 28SIyhAr4fN6fLpGcFAkv6Rcs0mkvnTp7vsC0HNyshmGi6qQ+C+eB4mklQzWOPcn koHZ2wtI8AJmyTdHKcXKAIFM0r+xl4MJ5445IvDjvIuGXZCzybXMw9Ss/4wSG3VN qSIJVEDGZXrBCc12fPxPEB0Bqx9MIVytjplXKIo8rFrk93h3at9t9kDM26z+9PZ5 KYnEdjRKF4KL4j+3xqJDOEJT15GVRbGRRzb9A8xH0YIQ0S3Q3pt1PAfla1Hss75+ NRQgfowZYryL9dfCkAj2XNfdQ+pUk25N3bNig11se+zjk2JO77QRM0u3GOYZ9+CU tSlwhtIMF32xnjgQyWE5yBBiEg3/Y+S+809tVaPseUEzkQJXMGq5TFxBrN6bj1Vm awr6QghThKjeoRwky5bmFn/gept/lbYN6VV5B6gNznGP5xgFrmvVtmjbQJBRMYCv aEUnrYqxkkbIddJjD5gl771/LWH4M2F1yBgJjfiZw2paEVAXKxEr327LsbOQaPdb HjIPRrJbVK9AABo4AZ/Y =lg0o -----END PGP SIGNATURE----- _______________________________________________ ghc-devs mailing list ghc-devs at haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs -------------- next part -------------- An HTML attachment was scrubbed... URL: From k-bx at k-bx.com Sat Jun 27 10:03:33 2015 From: k-bx at k-bx.com (Kostiantyn Rybnikov) Date: Sat, 27 Jun 2015 13:03:33 +0300 Subject: SV: Abstract FilePath Proposal In-Reply-To: <558e6de1.63a6700a.5f03.2b03@mx.google.com> References: <874mlu8nae.fsf@gnu.org> <558e6de1.63a6700a.5f03.2b03@mx.google.com> Message-ID: Because new api already exists in libraries, but FilePath from base is still being used, which makes things worse (now your programs have all those conversions all over). I like the idea with gradual deprecation warning, but it's not clear if it's feasible to implement. 27 ????. 2015 12:33 "Niklas Larsson" ????: > Hi! > > Instead of trying to minimally patch the existing API and still breaking > loads of code, why not make a new API that doesn't have to compromise and > depreciate the old one? > > Niklas > ------------------------------ > Fr?n: Herbert Valerio Riedel > Skickat: ?2015-?06-?26 18:09 > Till: libraries at haskell.org; ghc-devs at haskell.org > ?mne: Abstract FilePath Proposal > > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Hello *, > > What? > ===== > > We (see From: & CC: headers) propose, plain and simple, to turn the > currently defined type-synonym > > type FilePath = String > > into an abstract/opaque data type instead. > > Why/How/When? > ============= > > For details (including motivation and a suggested transition scheme) > please consult > > https://ghc.haskell.org/trac/ghc/wiki/Proposal/AbstractFilePath > > > > Suggested discussion period: 4 weeks > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1 > > iQIcBAEBAgAGBQJVjXkZAAoJELo8uj/+IrV0WXUP/0romoKazwLbQpaMAKgCNZon > BsY8Di44w6rkbdBXoky0xZooII8LJJyQfexH0BLRYEVLZFy0+LB8XzpPt8Ekg526 > YlY4x0qFm9oiJbJDMqHUnb6z6Lr2KxzBcV37drTPbltUA+HB49DUVkkPbvHimpL2 > 28SIyhAr4fN6fLpGcFAkv6Rcs0mkvnTp7vsC0HNyshmGi6qQ+C+eB4mklQzWOPcn > koHZ2wtI8AJmyTdHKcXKAIFM0r+xl4MJ5445IvDjvIuGXZCzybXMw9Ss/4wSG3VN > qSIJVEDGZXrBCc12fPxPEB0Bqx9MIVytjplXKIo8rFrk93h3at9t9kDM26z+9PZ5 > KYnEdjRKF4KL4j+3xqJDOEJT15GVRbGRRzb9A8xH0YIQ0S3Q3pt1PAfla1Hss75+ > NRQgfowZYryL9dfCkAj2XNfdQ+pUk25N3bNig11se+zjk2JO77QRM0u3GOYZ9+CU > tSlwhtIMF32xnjgQyWE5yBBiEg3/Y+S+809tVaPseUEzkQJXMGq5TFxBrN6bj1Vm > awr6QghThKjeoRwky5bmFn/gept/lbYN6VV5B6gNznGP5xgFrmvVtmjbQJBRMYCv > aEUnrYqxkkbIddJjD5gl771/LWH4M2F1yBgJjfiZw2paEVAXKxEr327LsbOQaPdb > HjIPRrJbVK9AABo4AZ/Y > =lg0o > -----END PGP SIGNATURE----- > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ndmitchell at gmail.com Sat Jun 27 10:12:43 2015 From: ndmitchell at gmail.com (Neil Mitchell) Date: Sat, 27 Jun 2015 11:12:43 +0100 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <558e6de1.63a6700a.5f03.2b03@mx.google.com> Message-ID: Hi Niklas, The function writeFile takes a FilePath. We could fork base or tell everyone to use writeFile2, but in practice everyone will keep using writeFile, and this String for FilePath. This approach is the only thing we could figure that made sense. Henning: we do not propose normalisation on initialisation. For ASCII strings fromFilePath . toFilePath will be id. It might also be for unicode on some/all platforms. Of course, you can write your own FilePath creator that does normalisation on construction. Thanks, Neil On Saturday, 27 June 2015, Niklas Larsson > wrote: > Hi! > > Instead of trying to minimally patch the existing API and still breaking > loads of code, why not make a new API that doesn't have to compromise and > depreciate the old one? > > Niklas > ------------------------------ > Fr?n: Herbert Valerio Riedel > Skickat: ?2015-?06-?26 18:09 > Till: libraries at haskell.org; ghc-devs at haskell.org > ?mne: Abstract FilePath Proposal > > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Hello *, > > What? > ===== > > We (see From: & CC: headers) propose, plain and simple, to turn the > currently defined type-synonym > > type FilePath = String > > into an abstract/opaque data type instead. > > Why/How/When? > ============= > > For details (including motivation and a suggested transition scheme) > please consult > > https://ghc.haskell.org/trac/ghc/wiki/Proposal/AbstractFilePath > > > > Suggested discussion period: 4 weeks > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1 > > iQIcBAEBAgAGBQJVjXkZAAoJELo8uj/+IrV0WXUP/0romoKazwLbQpaMAKgCNZon > BsY8Di44w6rkbdBXoky0xZooII8LJJyQfexH0BLRYEVLZFy0+LB8XzpPt8Ekg526 > YlY4x0qFm9oiJbJDMqHUnb6z6Lr2KxzBcV37drTPbltUA+HB49DUVkkPbvHimpL2 > 28SIyhAr4fN6fLpGcFAkv6Rcs0mkvnTp7vsC0HNyshmGi6qQ+C+eB4mklQzWOPcn > koHZ2wtI8AJmyTdHKcXKAIFM0r+xl4MJ5445IvDjvIuGXZCzybXMw9Ss/4wSG3VN > qSIJVEDGZXrBCc12fPxPEB0Bqx9MIVytjplXKIo8rFrk93h3at9t9kDM26z+9PZ5 > KYnEdjRKF4KL4j+3xqJDOEJT15GVRbGRRzb9A8xH0YIQ0S3Q3pt1PAfla1Hss75+ > NRQgfowZYryL9dfCkAj2XNfdQ+pUk25N3bNig11se+zjk2JO77QRM0u3GOYZ9+CU > tSlwhtIMF32xnjgQyWE5yBBiEg3/Y+S+809tVaPseUEzkQJXMGq5TFxBrN6bj1Vm > awr6QghThKjeoRwky5bmFn/gept/lbYN6VV5B6gNznGP5xgFrmvVtmjbQJBRMYCv > aEUnrYqxkkbIddJjD5gl771/LWH4M2F1yBgJjfiZw2paEVAXKxEr327LsbOQaPdb > HjIPRrJbVK9AABo4AZ/Y > =lg0o > -----END PGP SIGNATURE----- > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From spam at scientician.net Sat Jun 27 11:39:21 2015 From: spam at scientician.net (Bardur Arantsson) Date: Sat, 27 Jun 2015 13:39:21 +0200 Subject: Abstract FilePath Proposal In-Reply-To: <87bng1r3gp.fsf@gnu.org> References: <874mlu8nae.fsf@gnu.org> <87bng1r3gp.fsf@gnu.org> Message-ID: On 06/27/2015 09:54 AM, Herbert Valerio Riedel wrote: > This won't be for free: I expect most packages which currently do more > than just opaquely pass around FilePaths to require fixes. > > Some examples: > > - `writeFile "doo/foo.bar" ...` > `_ <- readFile ("doo" "foo" <.> "bar")` > > This will break unless -XOverloadedStrings happens to be enabled > > - Unless we generalise (++) to (<>), all cases where `FilePath`s are > concatenated via (++) will break. > > - Code that uses Data.List rather than the `filepath` package for > FilePath manipulation will need fixups (simplest fix: explicitly > convert to/from String for the manipulation) > > - Some code, like e.g. > > fnames <- System.Environment.getArgs > forM fnames $ \fn -> print =<< readFile fn > > will inevitably need to insert explicit conversions to/from FilePaths > > I tried to simulate the effect on Hackage, but this turned out to be > more time-demanding than I hoped for and I had to abort. But the above > is what I encountered in my attempt. It could, of course, be argued that some of this is "deserved breakage" since blind concatenation (etc.) is probably already wrong in many cases. (If someone is going to help fix up the breakage, then I'm still +1 :)) Regards, From amindfv at gmail.com Sat Jun 27 12:11:52 2015 From: amindfv at gmail.com (amindfv at gmail.com) Date: Sat, 27 Jun 2015 08:11:52 -0400 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <87bng1r3gp.fsf@gnu.org> Message-ID: El Jun 27, 2015, a las 7:39, Bardur Arantsson escribi?: > On 06/27/2015 09:54 AM, Herbert Valerio Riedel wrote: >> This won't be for free: I expect most packages which currently do more >> than just opaquely pass around FilePaths to require fixes. >> >> Some examples: >> >> - `writeFile "doo/foo.bar" ...` >> `_ <- readFile ("doo" "foo" <.> "bar")` >> >> This will break unless -XOverloadedStrings happens to be enabled >> >> - Unless we generalise (++) to (<>), all cases where `FilePath`s are >> concatenated via (++) will break. >> >> - Code that uses Data.List rather than the `filepath` package for >> FilePath manipulation will need fixups (simplest fix: explicitly >> convert to/from String for the manipulation) >> >> - Some code, like e.g. >> >> fnames <- System.Environment.getArgs >> forM fnames $ \fn -> print =<< readFile fn >> >> will inevitably need to insert explicit conversions to/from FilePaths >> >> I tried to simulate the effect on Hackage, but this turned out to be >> more time-demanding than I hoped for and I had to abort. But the above >> is what I encountered in my attempt. > > It could, of course, be argued that some of this is "deserved breakage" > since blind concatenation (etc.) is probably already wrong in many cases. > > (If someone is going to help fix up the breakage, then I'm still +1 :)) Just to be clear, every existing "creation" of a FilePath (without OverloadedStrings) will be broken, right? So e.g. 'writeFile "test.txt" "test"' will be just as broken as 'writeFile ("foo" "test.txt") "test"' (or the '++' version) I'm not +1 or -1 yet, just clarifying. Tom > > Regards, > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From dsf at seereason.com Sat Jun 27 12:56:33 2015 From: dsf at seereason.com (David Fox) Date: Sat, 27 Jun 2015 05:56:33 -0700 Subject: Abstract FilePath Proposal In-Reply-To: <874mlu8nae.fsf@gnu.org> References: <874mlu8nae.fsf@gnu.org> Message-ID: On Fri, Jun 26, 2015 at 9:08 AM, Herbert Valerio Riedel wrote: > > > We (see From: & CC: headers) propose, plain and simple, to turn the > currently defined type-synonym > > type FilePath = String > > into an abstract/opaque data type instead. > > Why/How/When? ?I've had success with a slightly different "How": Phase 1: Replace FilePath with a type class, with instances for the old FilePath (i.e. String) and the new implementation. Phase 2: Wait until a suitable amount of hackage builds without the string instance. Phase 3: Deprecate the String instance - move it to an old-filepath package. Phase 4: Replace the type class with the new implementation ? This way the new implementation is available immediately, packages can begin converting at once, benefits can be assessed. -------------- next part -------------- An HTML attachment was scrubbed... URL: From hvriedel at gmail.com Sat Jun 27 13:37:04 2015 From: hvriedel at gmail.com (Herbert Valerio Riedel) Date: Sat, 27 Jun 2015 15:37:04 +0200 Subject: Abstract FilePath Proposal In-Reply-To: (David Fox's message of "Sat, 27 Jun 2015 05:56:33 -0700") References: <874mlu8nae.fsf@gnu.org> Message-ID: <87h9ptp91b.fsf@gmail.com> On 2015-06-27 at 14:56:33 +0200, David Fox wrote: [...] > ?I've had success with a slightly different "How": What was your concrete use-case btw? > Phase 1: Replace FilePath with a type class, with instances for the old > FilePath (i.e. String) and the new implementation. what would that comprise in the FilePath case? I assume adding a transitional class whose methods are not exposed (and whose typeclass name is exported from some GHC-specific internal-marked module)? i.e. class IsFilePath a where privateToFilePath :: a -> FilePath privateFromFilePath :: FilePath -> a instance IsFilePath FilePath where privateToFilePath = id privateFromFilePath = id instance IsFilePath [Char] where privateToFilePath = System.IO.toFilePath privateFromFilePath = System.IO.fromFilePath ? as well as changing a lot of type-sigs in base & filepath from e.g. writeFile :: FilePath -> String -> IO () openTempFile :: FilePath -> String -> IO (FilePath, Handle) to writeFile :: IsFilePath a => a -> String -> IO () openTempFile :: IsFilePath a => a -> String -> IO (a, Handle) ? > Phase 2: Wait until a suitable amount of hackage builds without the string > instance. I can see Stackage helping with that by using a custom GHC which lacks the legacy `IsFilePath [Char]`-instance. So I'd be optimistic that Phase2 could be accomplished within one year for the Stackage-subset of Hackage. > Phase 3: Deprecate the String instance - move it to an old-filepath package. > > Phase 4: Replace the type class with the new implementation I assume this means getting rid again of the typeclass, and changing the type-sigs back to i.e. writeFile :: FilePath -> String -> IO () openTempFile :: FilePath -> String -> IO (FilePath, Handle) ? (but now with with the new opaque `FilePath`)? > This way the new implementation is available immediately, packages can > begin converting at once, benefits can be assessed. This scheme seems feasible at first glance, as long as the typeclass doesn't start spreading across packages and find its way into type-sigs (in which case it'd become more disruptive to get rid of it again). Otoh, I'm not sure (assuming I understood how your scheme works) it can be avoided to have the typeclass spread, since if not every API that now has `FilePath` arguments in their type-sigs gets generalised to have `IsFilePath a => a` arguments instead, we can't reach the goal of "Phase 2". But I suspect that I didn't fully understand how your proposed transition scheme works exactly... so please correct me where I got it wrong! Cheers, hvr From hvriedel at gmail.com Sat Jun 27 13:42:22 2015 From: hvriedel at gmail.com (Herbert Valerio Riedel) Date: Sat, 27 Jun 2015 15:42:22 +0200 Subject: Abstract FilePath Proposal In-Reply-To: (amindfv@gmail.com's message of "Sat, 27 Jun 2015 08:11:52 -0400") References: <874mlu8nae.fsf@gnu.org> <87bng1r3gp.fsf@gnu.org> Message-ID: <87d20hp8sh.fsf@gmail.com> On 2015-06-27 at 14:11:52 +0200, amindfv at gmail.com wrote: [...] >>> - `writeFile "doo/foo.bar" ...` >>> `_ <- readFile ("doo" "foo" <.> "bar")` >>> >>> This will break unless -XOverloadedStrings happens to be enabled [...] > Just to be clear, every existing "creation" of a FilePath (without > OverloadedStrings) will be broken, right? > > So e.g. 'writeFile "test.txt" "test"' will be just as broken as > 'writeFile ("foo" "test.txt") "test"' (or the '++' version) That's right; w/o OverloadedStrings, you'd have to write e.g. writeFile (toFilePath "test.txt") "test" (which will be possible to write as soon as `filepath` starts exposing the forward-compat `{to,from}FilePath` conversion functions) From dsf at seereason.com Sat Jun 27 14:17:57 2015 From: dsf at seereason.com (David Fox) Date: Sat, 27 Jun 2015 07:17:57 -0700 Subject: Abstract FilePath Proposal In-Reply-To: <87h9ptp91b.fsf@gmail.com> References: <874mlu8nae.fsf@gnu.org> <87h9ptp91b.fsf@gmail.com> Message-ID: On Sat, Jun 27, 2015 at 6:37 AM, Herbert Valerio Riedel wrote: > On 2015-06-27 at 14:56:33 +0200, David Fox wrote: > > [...] > > > ?I've had success with a slightly different "How": > > What was your concrete use-case btw? > > > Phase 1: Replace FilePath with a type class, with instances for the old > > FilePath (i.e. String) and the new implementation. > > what would that comprise in the FilePath case? > > I assume adding a transitional class whose methods are not exposed (and > whose typeclass name is exported from some GHC-specific internal-marked > module)? i.e. > > class IsFilePath a where > privateToFilePath :: a -> FilePath > privateFromFilePath :: FilePath -> a > > instance IsFilePath FilePath where > privateToFilePath = id > privateFromFilePath = id > > instance IsFilePath [Char] where > privateToFilePath = System.IO.toFilePath > privateFromFilePath = System.IO.fromFilePath > > ? > > as well as changing a lot of type-sigs in base & filepath from > e.g. > > writeFile :: FilePath -> String -> IO () > openTempFile :: FilePath -> String -> IO (FilePath, Handle) > > to > > writeFile :: IsFilePath a => a -> String -> IO () > openTempFile :: IsFilePath a => a -> String -> IO (a, Handle) > > > ? > > > Phase 2: Wait until a suitable amount of hackage builds without the > string > > instance. > > I can see Stackage helping with that by using a custom GHC which lacks > the legacy `IsFilePath [Char]`-instance. So I'd be optimistic that Phase2 > could be > accomplished within one year for the Stackage-subset of Hackage. > > > Phase 3: Deprecate the String instance - move it to an old-filepath > package. > > > > Phase 4: Replace the type class with the new implementation > > I assume this means getting rid again of the typeclass, and changing the > type-sigs back to i.e. > > writeFile :: FilePath -> String -> IO () > openTempFile :: FilePath -> String -> IO (FilePath, Handle) > ? > (but now with with the new opaque `FilePath`)? > > > This way the new implementation is available immediately, packages can > > begin converting at once, benefits can be assessed. > > This scheme seems feasible at first glance, as long as the typeclass > doesn't start spreading across packages and find its way into type-sigs > (in which case it'd become more disruptive to get rid of it > again). Otoh, I'm not sure (assuming I understood how your scheme works) > it can be avoided to have the typeclass spread, since if not every API > that now has `FilePath` arguments in their type-sigs gets generalised to > have `IsFilePath a => a` arguments instead, we can't reach the goal of > "Phase 2". > > But I suspect that I didn't fully understand how your proposed > transition scheme works exactly... so please correct me where I got it > wrong! > ?You are right, your approach is more appropriate for use by a community.? I missed some of the problems that would arise. -------------- next part -------------- An HTML attachment was scrubbed... URL: From gale at sefer.org Sat Jun 27 20:50:41 2015 From: gale at sefer.org (Yitzchak Gale) Date: Sat, 27 Jun 2015 20:50:41 +0000 Subject: Abstract FilePath Proposal In-Reply-To: <1435392302.1459.9.camel@joachim-breitner.de> References: <874mlu8nae.fsf@gnu.org> <1435392302.1459.9.camel@joachim-breitner.de> Message-ID: I am strong -1 on this proposal, due to the arguments of Joachim, unless we are getting the semantics right. Are we? By semantics, I mean just the lowest-level definition of what a path is made of. On POSIX, it's a raw string of bytes, with interpretation in any human-readable way delegated to the application. On Mac OS X, it's normalized Unicode. The important point is *normalized* - if you create a FilePath from two different Unicode strings that have the same normalized form, the result FilePaths must be equal on Mac OS X. On Windows, it's UTF-16. Basically, modulo the quirks. Correct semantics means: 1. There are different FilePath types for each platform, because the semantics of a path are vastly different for each. 2. By default, the FilePath for the current platform is used. But the FilePaths for other platforms are also available, and there is a simple API for best-effort conversion between them. Will this proposal provide that? If not, don't do this to us. Please. Joachim Breitner wrote: > unless proven wrong, I assume that this breaks lots of code. So by > default, I am doubtful towards that proposal. > > Also, the argument about inefficiency does not convince me. In a > Prelude where "type String = [Char]", this is ? as bad as it may be ? > consistent and expected. Just like you manually have to reach out for > dedicated string types if you want efficient Haskell, you can manually > reach out for dedicated FilePath libraries. I doubt that it is a good > idea to fix the String problem in small, isolated chunks. > > However, the argument that, depending on the system, "type FilePath = > String" is simply wrong (because the semantics of file paths are not > unicode points), is one that I buy in. On such systems, the Prelude is, > in a moral sense, wrongly typed, and the situation is comparable to a > hypothetical "type String = [Word8]" ? which is just wrong in a world > of unicode. So for me, the faithful representation of system filepaths > makes this proposal interesting. I like it when Haskell ?gets it > right?. > The problem is that I'm not sure this proposal "gets it right". And if not, I agree with your arguments that this proposal would not be worth the pain. -------------- next part -------------- An HTML attachment was scrubbed... URL: From allbery.b at gmail.com Sat Jun 27 21:02:12 2015 From: allbery.b at gmail.com (Brandon Allbery) Date: Sat, 27 Jun 2015 17:02:12 -0400 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <1435392302.1459.9.camel@joachim-breitner.de> Message-ID: On Sat, Jun 27, 2015 at 4:50 PM, Yitzchak Gale wrote: > On Mac OS X, it's normalized Unicode. The important > point is *normalized* - if you create a FilePath from two > different Unicode strings that have the same normalized > form, the result FilePaths must be equal on Mac OS X. > This is only true for higher level OS X APIs. ghc normally operates in the BSD layer, which mostly follows POSIX semantics; in particular, filesystem paths are bytestrings in the BSD layer, and only normalized in Cocoa APIs. (Which, among other things, means you can make a GUI application dump core by trying to use a file dialog in a directory containing a filename created using the BSD API which does not use a UTF8 encoding.) -- brandon s allbery kf8nh sine nomine associates allbery.b at gmail.com ballbery at sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net -------------- next part -------------- An HTML attachment was scrubbed... URL: From dct25-561bs at mythic-beasts.com Sat Jun 27 21:28:24 2015 From: dct25-561bs at mythic-beasts.com (David Turner) Date: Sat, 27 Jun 2015 22:28:24 +0100 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <1435392302.1459.9.camel@joachim-breitner.de> Message-ID: Hi, I'm +1 on the general idea of this proposal. Using String for filenames has caused me all sorts of trouble, particularly when I've had to deal with a bunch of files whose names don't all use the same encoding. However, be careful about the exact semantics of filenames on Windows. Quoting MSDN: There is no need to perform any Unicode normalization on path and file name strings for use by the Windows file I/O API functions because* the file system treats path and file names as an opaque sequence of WCHARs*. Any normalization that your application requires should be performed with this in mind, external of any calls to related Windows file I/O API functions. (from https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx, emphasis mine) Thus FilePath = String (or Text) doesn't really seem correct on Windows either (although it'll be pretty close as long as you stay within the BMP). By my reckoning, when you get down to brass tacks, all filesystems on all platforms name files with sequences of bytes. There are various interesting ways to represent these bytes to human beings as sequences of characters, but aiming for FilePath = ByteString everywhere and dealing with the conversion to characters elsewhere seems more correct. Cheers, David On 27 June 2015 at 22:02, Brandon Allbery wrote: > On Sat, Jun 27, 2015 at 4:50 PM, Yitzchak Gale wrote: >> >> On Mac OS X, it's normalized Unicode. The important >> point is *normalized* - if you create a FilePath from two >> different Unicode strings that have the same normalized >> form, the result FilePaths must be equal on Mac OS X. > > > This is only true for higher level OS X APIs. ghc normally operates in the > BSD layer, which mostly follows POSIX semantics; in particular, filesystem > paths are bytestrings in the BSD layer, and only normalized in Cocoa APIs. > (Which, among other things, means you can make a GUI application dump core > by trying to use a file dialog in a directory containing a filename created > using the BSD API which does not use a UTF8 encoding.) > > -- > brandon s allbery kf8nh sine nomine associates > allbery.b at gmail.com ballbery at sinenomine.net > unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From gale at sefer.org Sun Jun 28 00:41:57 2015 From: gale at sefer.org (Yitzchak Gale) Date: Sun, 28 Jun 2015 00:41:57 +0000 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <1435392302.1459.9.camel@joachim-breitner.de> Message-ID: I wrote: > On Mac OS X, it's normalized Unicode. Brandon Allbery wrote: > This is only true for higher level OS X APIs. ghc normally operates in the > BSD layer, which mostly follows POSIX semantics; in particular, filesystem > paths are bytestrings in the BSD layer, and only normalized in Cocoa APIs. > If I happen to be writing a program that only interacts with the BSD layer, then I can use the POSIX-style FilePath. But as an application writer, most of the time I'll be dealing with Mac OS X paths that need to work correctly with Cocoa. -------------- next part -------------- An HTML attachment was scrubbed... URL: From gale at sefer.org Sun Jun 28 01:02:14 2015 From: gale at sefer.org (Yitzchak Gale) Date: Sun, 28 Jun 2015 01:02:14 +0000 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <1435392302.1459.9.camel@joachim-breitner.de> Message-ID: OK, based on what David and Brandon wrote, I guess that representing paths as bytestrings does make some low-level sense on all platforms. Although for Windows we would still need some way to deal with the requirement that the bytestring have an even length. We will need platform-dependent coercions of paths to and from String/Text. Those might sometimes be partial functions. We need a notion of the coercions for the current platform, and we also need it to be possible to access the coercions for all platforms. On Sun, Jun 28, 2015 at 12:28 AM David Turner wrote: > Hi, > > I'm +1 on the general idea of this proposal. Using String for filenames > has caused me all sorts of trouble, particularly when I've had to deal with > a bunch of files whose names don't all use the same encoding. > > However, be careful about the exact semantics of filenames on Windows. > Quoting MSDN: > > > There is no need to perform any Unicode normalization on path and file > name strings for use by the Windows file I/O API functions because* the > file system treats path and file names as an opaque sequence of WCHARs*. > Any normalization that your application requires should be performed with > this in mind, external of any calls to related Windows file I/O API > functions. > > > (from > https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx, > emphasis mine) > > Thus FilePath = String (or Text) doesn't really seem correct on Windows > either (although it'll be pretty close as long as you stay within the BMP). > > By my reckoning, when you get down to brass tacks, all filesystems on all > platforms name files with sequences of bytes. There are various interesting > ways to represent these bytes to human beings as sequences of characters, > but aiming for FilePath = ByteString everywhere and dealing with the > conversion to characters elsewhere seems more correct. > > Cheers, > > David > > > > On 27 June 2015 at 22:02, Brandon Allbery wrote: > > On Sat, Jun 27, 2015 at 4:50 PM, Yitzchak Gale wrote: > >> > >> On Mac OS X, it's normalized Unicode. The important > >> point is *normalized* - if you create a FilePath from two > >> different Unicode strings that have the same normalized > >> form, the result FilePaths must be equal on Mac OS X. > > > > > > This is only true for higher level OS X APIs. ghc normally operates in > the > > BSD layer, which mostly follows POSIX semantics; in particular, > filesystem > > paths are bytestrings in the BSD layer, and only normalized in Cocoa > APIs. > > (Which, among other things, means you can make a GUI application dump > core > > by trying to use a file dialog in a directory containing a filename > created > > using the BSD API which does not use a UTF8 encoding.) > > > > -- > > brandon s allbery kf8nh sine nomine > associates > > allbery.b at gmail.com > ballbery at sinenomine.net > > unix, openafs, kerberos, infrastructure, xmonad > http://sinenomine.net > > > > _______________________________________________ > > Libraries mailing list > > Libraries at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From dct25-561bs at mythic-beasts.com Sun Jun 28 09:08:29 2015 From: dct25-561bs at mythic-beasts.com (David Turner) Date: Sun, 28 Jun 2015 10:08:29 +0100 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <1435392302.1459.9.camel@joachim-breitner.de> Message-ID: On 28 June 2015 at 02:02, Yitzchak Gale wrote: > OK, based on what David and Brandon wrote, I guess > that representing paths as bytestrings does make > some low-level sense on all platforms. Although > for Windows we would still need some way to deal > with the requirement that the bytestring have an even > length. > I would guess this could just be done by making the type abstract so you can't easily get to the underlying bytes. Windows will only ever give you even-length bytestrings (in directory listings or similar) and all the other ways of synthesizing paths from strings could be set up to preserve the evenness. If you end up passing an odd-length bytestring to Windows as a path then Bad Things could certainly happen, but no worse than mucking around with other unsafe APIs like Data.ByteString.Internal. On 28 June 2015 at 02:02, Yitzchak Gale wrote: > OK, based on what David and Brandon wrote, I guess > that representing paths as bytestrings does make > some low-level sense on all platforms. Although > for Windows we would still need some way to deal > with the requirement that the bytestring have an even > length. > > We will need platform-dependent coercions of > paths to and from String/Text. Those might sometimes > be partial functions. We need a notion of the coercions > for the current platform, and we also need it to be > possible to access the coercions for all platforms. > > > On Sun, Jun 28, 2015 at 12:28 AM David Turner < > dct25-561bs at mythic-beasts.com> wrote: > >> Hi, >> >> I'm +1 on the general idea of this proposal. Using String for filenames >> has caused me all sorts of trouble, particularly when I've had to deal with >> a bunch of files whose names don't all use the same encoding. >> >> However, be careful about the exact semantics of filenames on Windows. >> Quoting MSDN: >> >> >> There is no need to perform any Unicode normalization on path and file >> name strings for use by the Windows file I/O API functions because* the >> file system treats path and file names as an opaque sequence of WCHARs*. >> Any normalization that your application requires should be performed with >> this in mind, external of any calls to related Windows file I/O API >> functions. >> >> >> (from >> https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx, >> emphasis mine) >> >> Thus FilePath = String (or Text) doesn't really seem correct on Windows >> either (although it'll be pretty close as long as you stay within the BMP). >> >> By my reckoning, when you get down to brass tacks, all filesystems on all >> platforms name files with sequences of bytes. There are various interesting >> ways to represent these bytes to human beings as sequences of characters, >> but aiming for FilePath = ByteString everywhere and dealing with the >> conversion to characters elsewhere seems more correct. >> >> Cheers, >> >> David >> >> >> >> On 27 June 2015 at 22:02, Brandon Allbery wrote: >> > On Sat, Jun 27, 2015 at 4:50 PM, Yitzchak Gale wrote: >> >> >> >> On Mac OS X, it's normalized Unicode. The important >> >> point is *normalized* - if you create a FilePath from two >> >> different Unicode strings that have the same normalized >> >> form, the result FilePaths must be equal on Mac OS X. >> > >> > >> > This is only true for higher level OS X APIs. ghc normally operates in >> the >> > BSD layer, which mostly follows POSIX semantics; in particular, >> filesystem >> > paths are bytestrings in the BSD layer, and only normalized in Cocoa >> APIs. >> > (Which, among other things, means you can make a GUI application dump >> core >> > by trying to use a file dialog in a directory containing a filename >> created >> > using the BSD API which does not use a UTF8 encoding.) >> > >> > -- >> > brandon s allbery kf8nh sine nomine >> associates >> > allbery.b at gmail.com >> ballbery at sinenomine.net >> > unix, openafs, kerberos, infrastructure, xmonad >> http://sinenomine.net >> > >> > _______________________________________________ >> > Libraries mailing list >> > Libraries at haskell.org >> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> > >> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From m at tweag.io Sun Jun 28 10:03:59 2015 From: m at tweag.io (Boespflug, Mathieu) Date: Sun, 28 Jun 2015 12:03:59 +0200 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <558e6de1.63a6700a.5f03.2b03@mx.google.com> Message-ID: Hi Neil, why does the proposal *not* include normalization? There are four advantages that I see to making FilePath a datatype: 1. it makes it possible to implement the correct semantics for some systems (including POSIX), 2. it allows for information hiding, which in turn helps modularity, 3. the type is distinct from any other type, hence static checks are stronger, 4. it becomes possible to quotient values over some arbitrary set of identities that makes sense. i.e. in the case of FilePath, arguably "foo/bar//baz" *is* "foo/bar/baz" *is* "foo//bar/baz" for all intents and purposes, so it is not useful to distinguish these three ways of writing down the same path (and in fact in practice distinguishing them leads to subtle bugs). That is, the Eq instance compares FilePath's modulo a few laws. Do you propose to forego (4)? If so why so? If we're going through a deprecation process, could we do so once, by getting the notion of path equality we want right the first time? Contrary to type indexing FilePath, it seems to me that the design space for path identities is much smaller. Essentially, exactly the ones here: https://hackage.haskell.org/package/filepath-1.1.0.2/docs/System-FilePath-Posix.html#v:normalise. Best, Mathieu On 27 June 2015 at 12:12, Neil Mitchell wrote: > Hi Niklas, > > The function writeFile takes a FilePath. We could fork base or tell everyone > to use writeFile2, but in practice everyone will keep using writeFile, and > this String for FilePath. This approach is the only thing we could figure > that made sense. > > Henning: we do not propose normalisation on initialisation. For ASCII > strings fromFilePath . toFilePath will be id. It might also be for unicode > on some/all platforms. Of course, you can write your own FilePath creator > that does normalisation on construction. > > Thanks, Neil > > > On Saturday, 27 June 2015, Niklas Larsson wrote: >> >> Hi! >> >> Instead of trying to minimally patch the existing API and still breaking >> loads of code, why not make a new API that doesn't have to compromise and >> depreciate the old one? >> >> Niklas >> ________________________________ >> Fr?n: Herbert Valerio Riedel >> Skickat: ?2015-?06-?26 18:09 >> Till: libraries at haskell.org; ghc-devs at haskell.org >> ?mne: Abstract FilePath Proposal >> >> -----BEGIN PGP SIGNED MESSAGE----- >> Hash: SHA1 >> >> Hello *, >> >> What? >> ===== >> >> We (see From: & CC: headers) propose, plain and simple, to turn the >> currently defined type-synonym >> >> type FilePath = String >> >> into an abstract/opaque data type instead. >> >> Why/How/When? >> ============= >> >> For details (including motivation and a suggested transition scheme) >> please consult >> >> https://ghc.haskell.org/trac/ghc/wiki/Proposal/AbstractFilePath >> >> >> >> Suggested discussion period: 4 weeks >> -----BEGIN PGP SIGNATURE----- >> Version: GnuPG v1 >> >> iQIcBAEBAgAGBQJVjXkZAAoJELo8uj/+IrV0WXUP/0romoKazwLbQpaMAKgCNZon >> BsY8Di44w6rkbdBXoky0xZooII8LJJyQfexH0BLRYEVLZFy0+LB8XzpPt8Ekg526 >> YlY4x0qFm9oiJbJDMqHUnb6z6Lr2KxzBcV37drTPbltUA+HB49DUVkkPbvHimpL2 >> 28SIyhAr4fN6fLpGcFAkv6Rcs0mkvnTp7vsC0HNyshmGi6qQ+C+eB4mklQzWOPcn >> koHZ2wtI8AJmyTdHKcXKAIFM0r+xl4MJ5445IvDjvIuGXZCzybXMw9Ss/4wSG3VN >> qSIJVEDGZXrBCc12fPxPEB0Bqx9MIVytjplXKIo8rFrk93h3at9t9kDM26z+9PZ5 >> KYnEdjRKF4KL4j+3xqJDOEJT15GVRbGRRzb9A8xH0YIQ0S3Q3pt1PAfla1Hss75+ >> NRQgfowZYryL9dfCkAj2XNfdQ+pUk25N3bNig11se+zjk2JO77QRM0u3GOYZ9+CU >> tSlwhtIMF32xnjgQyWE5yBBiEg3/Y+S+809tVaPseUEzkQJXMGq5TFxBrN6bj1Vm >> awr6QghThKjeoRwky5bmFn/gept/lbYN6VV5B6gNznGP5xgFrmvVtmjbQJBRMYCv >> aEUnrYqxkkbIddJjD5gl771/LWH4M2F1yBgJjfiZw2paEVAXKxEr327LsbOQaPdb >> HjIPRrJbVK9AABo4AZ/Y >> =lg0o >> -----END PGP SIGNATURE----- >> _______________________________________________ >> ghc-devs mailing list >> ghc-devs at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > From dct25-561bs at mythic-beasts.com Sun Jun 28 12:09:10 2015 From: dct25-561bs at mythic-beasts.com (David Turner) Date: Sun, 28 Jun 2015 13:09:10 +0100 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <558e6de1.63a6700a.5f03.2b03@mx.google.com> Message-ID: Hi, I think it'd be more robust to handle normalisation when converting from String/Text to FilePath (and combining things with () and so on) rather than in the underlying representation. It's absolutely crucial that you can ask the OS for a filename (which it gives you as a sequence of bytes) and then pass that exact same sequence of bytes back to the OS without any normalisation or other useful alterations having taken place. You can do some deeply weird stuff in Windows by starting an absolute path with \\?\, including apparently using '.' and '..' as the name of a filesystem component: Because it turns off automatic expansion of the path string, the "\\?\" prefix also allows the use of ".." and "." in the path names, which can be useful if you are attempting to perform operations on a file with these otherwise reserved relative path specifiers as part of the fully qualified path. (from https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx ) I don't fancy shaking all the corner cases out of this. An explicit 'normalise' function seems ok, but baking normalisation into the type itself seems bad. Cheers, David On 28 June 2015 at 11:03, Boespflug, Mathieu wrote: > Hi Neil, > > why does the proposal *not* include normalization? > > There are four advantages that I see to making FilePath a datatype: > > 1. it makes it possible to implement the correct semantics for some > systems (including POSIX), > 2. it allows for information hiding, which in turn helps modularity, > 3. the type is distinct from any other type, hence static checks are > stronger, > 4. it becomes possible to quotient values over some arbitrary set of > identities that makes sense. i.e. in the case of FilePath, arguably > "foo/bar//baz" *is* "foo/bar/baz" *is* "foo//bar/baz" for all intents > and purposes, so it is not useful to distinguish these three ways of > writing down the same path (and in fact in practice distinguishing > them leads to subtle bugs). That is, the Eq instance compares > FilePath's modulo a few laws. > > Do you propose to forego (4)? If so why so? > > If we're going through a deprecation process, could we do so once, by > getting the notion of path equality we want right the first time? > Contrary to type indexing FilePath, it seems to me that the design > space for path identities is much smaller. Essentially, exactly the > ones here: > https://hackage.haskell.org/package/filepath-1.1.0.2/docs/System-FilePath-Posix.html#v:normalise > . > > Best, > > Mathieu > > > On 27 June 2015 at 12:12, Neil Mitchell wrote: > > Hi Niklas, > > > > The function writeFile takes a FilePath. We could fork base or tell > everyone > > to use writeFile2, but in practice everyone will keep using writeFile, > and > > this String for FilePath. This approach is the only thing we could figure > > that made sense. > > > > Henning: we do not propose normalisation on initialisation. For ASCII > > strings fromFilePath . toFilePath will be id. It might also be for > unicode > > on some/all platforms. Of course, you can write your own FilePath creator > > that does normalisation on construction. > > > > Thanks, Neil > > > > > > On Saturday, 27 June 2015, Niklas Larsson wrote: > >> > >> Hi! > >> > >> Instead of trying to minimally patch the existing API and still breaking > >> loads of code, why not make a new API that doesn't have to compromise > and > >> depreciate the old one? > >> > >> Niklas > >> ________________________________ > >> Fr?n: Herbert Valerio Riedel > >> Skickat: ?2015-?06-?26 18:09 > >> Till: libraries at haskell.org; ghc-devs at haskell.org > >> ?mne: Abstract FilePath Proposal > >> > >> -----BEGIN PGP SIGNED MESSAGE----- > >> Hash: SHA1 > >> > >> Hello *, > >> > >> What? > >> ===== > >> > >> We (see From: & CC: headers) propose, plain and simple, to turn the > >> currently defined type-synonym > >> > >> type FilePath = String > >> > >> into an abstract/opaque data type instead. > >> > >> Why/How/When? > >> ============= > >> > >> For details (including motivation and a suggested transition scheme) > >> please consult > >> > >> https://ghc.haskell.org/trac/ghc/wiki/Proposal/AbstractFilePath > >> > >> > >> > >> Suggested discussion period: 4 weeks > >> -----BEGIN PGP SIGNATURE----- > >> Version: GnuPG v1 > >> > >> iQIcBAEBAgAGBQJVjXkZAAoJELo8uj/+IrV0WXUP/0romoKazwLbQpaMAKgCNZon > >> BsY8Di44w6rkbdBXoky0xZooII8LJJyQfexH0BLRYEVLZFy0+LB8XzpPt8Ekg526 > >> YlY4x0qFm9oiJbJDMqHUnb6z6Lr2KxzBcV37drTPbltUA+HB49DUVkkPbvHimpL2 > >> 28SIyhAr4fN6fLpGcFAkv6Rcs0mkvnTp7vsC0HNyshmGi6qQ+C+eB4mklQzWOPcn > >> koHZ2wtI8AJmyTdHKcXKAIFM0r+xl4MJ5445IvDjvIuGXZCzybXMw9Ss/4wSG3VN > >> qSIJVEDGZXrBCc12fPxPEB0Bqx9MIVytjplXKIo8rFrk93h3at9t9kDM26z+9PZ5 > >> KYnEdjRKF4KL4j+3xqJDOEJT15GVRbGRRzb9A8xH0YIQ0S3Q3pt1PAfla1Hss75+ > >> NRQgfowZYryL9dfCkAj2XNfdQ+pUk25N3bNig11se+zjk2JO77QRM0u3GOYZ9+CU > >> tSlwhtIMF32xnjgQyWE5yBBiEg3/Y+S+809tVaPseUEzkQJXMGq5TFxBrN6bj1Vm > >> awr6QghThKjeoRwky5bmFn/gept/lbYN6VV5B6gNznGP5xgFrmvVtmjbQJBRMYCv > >> aEUnrYqxkkbIddJjD5gl771/LWH4M2F1yBgJjfiZw2paEVAXKxEr327LsbOQaPdb > >> HjIPRrJbVK9AABo4AZ/Y > >> =lg0o > >> -----END PGP SIGNATURE----- > >> _______________________________________________ > >> ghc-devs mailing list > >> ghc-devs at haskell.org > >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > > > > > _______________________________________________ > > ghc-devs mailing list > > ghc-devs at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From me at lelf.lu Sun Jun 28 14:36:51 2015 From: me at lelf.lu (Antonio Nikishaev) Date: Sun, 28 Jun 2015 18:36:51 +0400 Subject: Abstract FilePath Proposal References: <874mlu8nae.fsf@gnu.org> <1435392302.1459.9.camel@joachim-breitner.de> Message-ID: Brandon Allbery writes: > On Sat, Jun 27, 2015 at 4:50 PM, Yitzchak Gale wrote: > > On Mac OS X, it's normalized Unicode. The important > > point is *normalized* - if you create a FilePath from two > different Unicode strings that have the same normalized > form, the result FilePaths must be equal on Mac OS X. > > This is only true for higher level OS X APIs. ghc normally operates in > the BSD layer, which mostly follows POSIX semantics; in particular, > filesystem paths are bytestrings in the BSD layer, and only normalized > in Cocoa APIs. Normalization here is a property of the filesystem, not the API. So it will be normalized in the POSIX layer too. From m at tweag.io Sun Jun 28 14:47:59 2015 From: m at tweag.io (Boespflug, Mathieu) Date: Sun, 28 Jun 2015 16:47:59 +0200 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <558e6de1.63a6700a.5f03.2b03@mx.google.com> Message-ID: On 28 June 2015 at 16:34, Sven Panne wrote: > 2015-06-28 12:03 GMT+02:00 Boespflug, Mathieu : >> >> why does the proposal *not* include normalization? [...] > > > I think this is intentional, because otherwise we are in the IO monad for > basically all operations. What's the normalized representation of > "foo/bar/../baz"? Notice that the kind of normalization I'm talking about, specified in the link I provided, does not include this kind of normalization. Because it requires the IO monad to perform correctly, and only on real paths. Here is the link again: https://hackage.haskell.org/package/filepath-1.1.0.2/docs/System-FilePath-Posix.html#v:normalise Full canonicalization of paths, stripping out redundant ".." and whatnot, should certainly be done in a separate function, in IO. From svenpanne at gmail.com Sun Jun 28 16:21:00 2015 From: svenpanne at gmail.com (Sven Panne) Date: Sun, 28 Jun 2015 18:21:00 +0200 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <558e6de1.63a6700a.5f03.2b03@mx.google.com> Message-ID: 2015-06-28 16:47 GMT+02:00 Boespflug, Mathieu : > Notice that the kind of normalization I'm talking about, specified in > the link I provided, does not include this kind of normalization. > Because it requires the IO monad to perform correctly, and only on > real paths. > > Here is the link again: > > > https://hackage.haskell.org/package/filepath-1.1.0.2/docs/System-FilePath-Posix.html#v:normalise > [...] > OK, then I misunderstood what you meant by "normalizing". But a question remains then: What is a use case for having equality modulo "normalise"? It throws together a few more paths which plain equality on strings would consider different, but it is still not semantic equality in the sense of "these 2 paths refer to the same dir/file". So unless there is a compelling use case (which I don't see), I don't see a point in always doing "normalise". Or do I miss something? -------------- next part -------------- An HTML attachment was scrubbed... URL: From amindfv at gmail.com Sun Jun 28 17:05:40 2015 From: amindfv at gmail.com (amindfv at gmail.com) Date: Sun, 28 Jun 2015 13:05:40 -0400 Subject: Abstract FilePath Proposal In-Reply-To: <87fv5dr4ax.fsf@gnu.org> References: <874mlu8nae.fsf@gnu.org> <87fv5dr4ax.fsf@gnu.org> Message-ID: One other point, while still maintaining +0 on the proposal itself: This proposal is likely to break lots and lots of code a la the FTP, and we all remember the unpleasant surprise that the community had with that one. If libraries@ agrees this is a worthwhile change, I think we need to let the community vote on it and its deprecation cycle. Tom El Jun 27, 2015, a las 3:36, Herbert Valerio Riedel escribi?: > On 2015-06-26 at 18:22:16 +0200, Henning Thielemann wrote: > [...] >>>> type FilePath = String >>>> >>>> into an abstract/opaque data type instead. >>> >>> Has someone else tried the pathtype package? >>> http://hackage.haskell.org/package/pathtype >> >> Hm, your last point "Decisions assumed by this Proposal" seems to >> mean, that you want to leave out more specialised types from this >> proposal. That is, dir/file distinction might be defined on top of the >> new FilePath type. > > Yes, because the proposal is meant to only make the smallest incremental > change needed (i.e. change FilePath datatype, provide conversion > functions) to to achieve the primary goals (reduce space/time overhead & > make it a distinct type from String) in a way suitable for a future > Haskell Report, while trying to stay close enough that you can still > write code that works with both the H2010 and a AFPP definition of > `FilePath` > > Trying to redesign the FilePath type to also include dir/file > distinction seemed too daunting, as there's quite some additional > design-space area to explore (do drive-letters deserve a separate type? > do we use DataKinds? What invariants can/shall be represented at the > type-level? what errors are caught at the type-level, which are caught > at runtime? etc...), parts of which may require type-system extensions, > while just having a KISS-style opaque FilePath evades this. > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From bart.massey at gmail.com Sun Jun 28 17:37:51 2015 From: bart.massey at gmail.com (Bart Massey) Date: Sun, 28 Jun 2015 17:37:51 +0000 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <87fv5dr4ax.fsf@gnu.org> Message-ID: -1 on this proposal in all its variations right now. There seems to be no strong consensus on the positive nature of any of the proposed changes at this point, and folks seem to disagree on the scope and content of the changes. We should leave well enough alone until someone has a proposal most of us can agree is awesome. On Sun, Jun 28, 2015 at 10:05 AM wrote: > One other point, while still maintaining +0 on the proposal itself: > > This proposal is likely to break lots and lots of code a la the FTP, and > we all remember the unpleasant surprise that the community had with that > one. > > If libraries@ agrees this is a worthwhile change, I think we need to let > the community vote on it and its deprecation cycle. > > Tom > > > El Jun 27, 2015, a las 3:36, Herbert Valerio Riedel > escribi?: > > > On 2015-06-26 at 18:22:16 +0200, Henning Thielemann wrote: > > [...] > >>>> type FilePath = String > >>>> > >>>> into an abstract/opaque data type instead. > >>> > >>> Has someone else tried the pathtype package? > >>> http://hackage.haskell.org/package/pathtype > >> > >> Hm, your last point "Decisions assumed by this Proposal" seems to > >> mean, that you want to leave out more specialised types from this > >> proposal. That is, dir/file distinction might be defined on top of the > >> new FilePath type. > > > > Yes, because the proposal is meant to only make the smallest incremental > > change needed (i.e. change FilePath datatype, provide conversion > > functions) to to achieve the primary goals (reduce space/time overhead & > > make it a distinct type from String) in a way suitable for a future > > Haskell Report, while trying to stay close enough that you can still > > write code that works with both the H2010 and a AFPP definition of > > `FilePath` > > > > Trying to redesign the FilePath type to also include dir/file > > distinction seemed too daunting, as there's quite some additional > > design-space area to explore (do drive-letters deserve a separate type? > > do we use DataKinds? What invariants can/shall be represented at the > > type-level? what errors are caught at the type-level, which are caught > > at runtime? etc...), parts of which may require type-system extensions, > > while just having a KISS-style opaque FilePath evades this. > > > > _______________________________________________ > > Libraries mailing list > > Libraries at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From gershomb at gmail.com Sun Jun 28 17:51:46 2015 From: gershomb at gmail.com (Gershom B) Date: Sun, 28 Jun 2015 19:51:46 +0200 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <87fv5dr4ax.fsf@gnu.org> Message-ID: +1 on the original proposal, sans variations. The advantage is that it provides a very clear and smooth upgrade path, that with correct signaling can be nearly seamless. As argued, it isn?t about enforcing the ?right? semantics, which can be overlaid with further proposals or even in userland libraries ? it is that the current datatype is just plain wrong for capturing the various weird things that filepaths can really be in practice, so to even have the possibility of putting in place semantics that are ?more correct? we need to have the right sort of opaque type to begin with. Since this proposal is designed to be the smoothest way to get us over that hump, I support it. ?gershom On June 28, 2015 at 7:38:06 PM, Bart Massey (bart.massey at gmail.com) wrote: > -1 on this proposal in all its variations right now. There seems to be no > strong consensus on the positive nature of any of the proposed changes at > this point, and folks seem to disagree on the scope and content of the > changes. We should leave well enough alone until someone has a proposal > most of us can agree is awesome. > > On Sun, Jun 28, 2015 at 10:05 AM wrote: > > > One other point, while still maintaining +0 on the proposal itself: > > > > This proposal is likely to break lots and lots of code a la the FTP, and > > we all remember the unpleasant surprise that the community had with that > > one. > > > > If libraries@ agrees this is a worthwhile change, I think we need to let > > the community vote on it and its deprecation cycle. > > > > Tom > > > > > > El Jun 27, 2015, a las 3:36, Herbert Valerio Riedel > > escribi?: > > > > > On 2015-06-26 at 18:22:16 +0200, Henning Thielemann wrote: > > > [...] > > >>>> type FilePath = String > > >>>> > > >>>> into an abstract/opaque data type instead. > > >>> > > >>> Has someone else tried the pathtype package? > > >>> http://hackage.haskell.org/package/pathtype > > >> > > >> Hm, your last point "Decisions assumed by this Proposal" seems to > > >> mean, that you want to leave out more specialised types from this > > >> proposal. That is, dir/file distinction might be defined on top of the > > >> new FilePath type. > > > > > > Yes, because the proposal is meant to only make the smallest incremental > > > change needed (i.e. change FilePath datatype, provide conversion > > > functions) to to achieve the primary goals (reduce space/time overhead & > > > make it a distinct type from String) in a way suitable for a future > > > Haskell Report, while trying to stay close enough that you can still > > > write code that works with both the H2010 and a AFPP definition of > > > `FilePath` > > > > > > Trying to redesign the FilePath type to also include dir/file > > > distinction seemed too daunting, as there's quite some additional > > > design-space area to explore (do drive-letters deserve a separate type? > > > do we use DataKinds? What invariants can/shall be represented at the > > > type-level? what errors are caught at the type-level, which are caught > > > at runtime? etc...), parts of which may require type-system extensions, > > > while just having a KISS-style opaque FilePath evades this. > > > > > > _______________________________________________ > > > Libraries mailing list > > > Libraries at haskell.org > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > _______________________________________________ > > Libraries mailing list > > Libraries at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > From ekmett at gmail.com Sun Jun 28 19:05:05 2015 From: ekmett at gmail.com (Edward Kmett) Date: Sun, 28 Jun 2015 15:05:05 -0400 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <558e6de1.63a6700a.5f03.2b03@mx.google.com> Message-ID: Worse there are situations where you absolutely _have_ to be able to use \\?\ encoding of a path on Windows to read, modify or delete files with "impossible names" that were created by other means. e.g. Filenames like AUX, that had traditional roles under DOS cause weird interactions, or that were created with "impossibly long names" -- which can happen in the wild when you move directories around, etc. I'm weakly in favor of the proposal precisely because it is the first version of this concept that I've seen that DOESN'T try to get too clever with regards to adding all sorts of normalization and this proposal seems to be the simplest move that would enable us to do something correctly in the future, regardless of what that correct thing winds up being. -Edward On Sun, Jun 28, 2015 at 8:09 AM, David Turner wrote: > Hi, > > I think it'd be more robust to handle normalisation when converting from > String/Text to FilePath (and combining things with () and so on) rather > than in the underlying representation. > > It's absolutely crucial that you can ask the OS for a filename (which it > gives you as a sequence of bytes) and then pass that exact same sequence of > bytes back to the OS without any normalisation or other useful alterations > having taken place. > > You can do some deeply weird stuff in Windows by starting an absolute path > with \\?\, including apparently using '.' and '..' as the name of a > filesystem component: > > Because it turns off automatic expansion of the path string, the "\\?\" > prefix also allows the use of ".." and "." in the path names, which can be > useful if you are attempting to perform operations on a file with these > otherwise reserved relative path specifiers as part of the fully qualified > path. > > > (from > https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx > ) > > I don't fancy shaking all the corner cases out of this. An explicit > 'normalise' function seems ok, but baking normalisation into the type > itself seems bad. > > Cheers, > > David > > > On 28 June 2015 at 11:03, Boespflug, Mathieu wrote: > >> Hi Neil, >> >> why does the proposal *not* include normalization? >> >> There are four advantages that I see to making FilePath a datatype: >> >> 1. it makes it possible to implement the correct semantics for some >> systems (including POSIX), >> 2. it allows for information hiding, which in turn helps modularity, >> 3. the type is distinct from any other type, hence static checks are >> stronger, >> 4. it becomes possible to quotient values over some arbitrary set of >> identities that makes sense. i.e. in the case of FilePath, arguably >> "foo/bar//baz" *is* "foo/bar/baz" *is* "foo//bar/baz" for all intents >> and purposes, so it is not useful to distinguish these three ways of >> writing down the same path (and in fact in practice distinguishing >> them leads to subtle bugs). That is, the Eq instance compares >> FilePath's modulo a few laws. >> >> Do you propose to forego (4)? If so why so? >> >> If we're going through a deprecation process, could we do so once, by >> getting the notion of path equality we want right the first time? >> Contrary to type indexing FilePath, it seems to me that the design >> space for path identities is much smaller. Essentially, exactly the >> ones here: >> https://hackage.haskell.org/package/filepath-1.1.0.2/docs/System-FilePath-Posix.html#v:normalise >> . >> >> Best, >> >> Mathieu >> >> >> On 27 June 2015 at 12:12, Neil Mitchell wrote: >> > Hi Niklas, >> > >> > The function writeFile takes a FilePath. We could fork base or tell >> everyone >> > to use writeFile2, but in practice everyone will keep using writeFile, >> and >> > this String for FilePath. This approach is the only thing we could >> figure >> > that made sense. >> > >> > Henning: we do not propose normalisation on initialisation. For ASCII >> > strings fromFilePath . toFilePath will be id. It might also be for >> unicode >> > on some/all platforms. Of course, you can write your own FilePath >> creator >> > that does normalisation on construction. >> > >> > Thanks, Neil >> > >> > >> > On Saturday, 27 June 2015, Niklas Larsson wrote: >> >> >> >> Hi! >> >> >> >> Instead of trying to minimally patch the existing API and still >> breaking >> >> loads of code, why not make a new API that doesn't have to compromise >> and >> >> depreciate the old one? >> >> >> >> Niklas >> >> ________________________________ >> >> Fr?n: Herbert Valerio Riedel >> >> Skickat: ?2015-?06-?26 18:09 >> >> Till: libraries at haskell.org; ghc-devs at haskell.org >> >> ?mne: Abstract FilePath Proposal >> >> >> >> -----BEGIN PGP SIGNED MESSAGE----- >> >> Hash: SHA1 >> >> >> >> Hello *, >> >> >> >> What? >> >> ===== >> >> >> >> We (see From: & CC: headers) propose, plain and simple, to turn the >> >> currently defined type-synonym >> >> >> >> type FilePath = String >> >> >> >> into an abstract/opaque data type instead. >> >> >> >> Why/How/When? >> >> ============= >> >> >> >> For details (including motivation and a suggested transition scheme) >> >> please consult >> >> >> >> https://ghc.haskell.org/trac/ghc/wiki/Proposal/AbstractFilePath >> >> >> >> >> >> >> >> Suggested discussion period: 4 weeks >> >> -----BEGIN PGP SIGNATURE----- >> >> Version: GnuPG v1 >> >> >> >> iQIcBAEBAgAGBQJVjXkZAAoJELo8uj/+IrV0WXUP/0romoKazwLbQpaMAKgCNZon >> >> BsY8Di44w6rkbdBXoky0xZooII8LJJyQfexH0BLRYEVLZFy0+LB8XzpPt8Ekg526 >> >> YlY4x0qFm9oiJbJDMqHUnb6z6Lr2KxzBcV37drTPbltUA+HB49DUVkkPbvHimpL2 >> >> 28SIyhAr4fN6fLpGcFAkv6Rcs0mkvnTp7vsC0HNyshmGi6qQ+C+eB4mklQzWOPcn >> >> koHZ2wtI8AJmyTdHKcXKAIFM0r+xl4MJ5445IvDjvIuGXZCzybXMw9Ss/4wSG3VN >> >> qSIJVEDGZXrBCc12fPxPEB0Bqx9MIVytjplXKIo8rFrk93h3at9t9kDM26z+9PZ5 >> >> KYnEdjRKF4KL4j+3xqJDOEJT15GVRbGRRzb9A8xH0YIQ0S3Q3pt1PAfla1Hss75+ >> >> NRQgfowZYryL9dfCkAj2XNfdQ+pUk25N3bNig11se+zjk2JO77QRM0u3GOYZ9+CU >> >> tSlwhtIMF32xnjgQyWE5yBBiEg3/Y+S+809tVaPseUEzkQJXMGq5TFxBrN6bj1Vm >> >> awr6QghThKjeoRwky5bmFn/gept/lbYN6VV5B6gNznGP5xgFrmvVtmjbQJBRMYCv >> >> aEUnrYqxkkbIddJjD5gl771/LWH4M2F1yBgJjfiZw2paEVAXKxEr327LsbOQaPdb >> >> HjIPRrJbVK9AABo4AZ/Y >> >> =lg0o >> >> -----END PGP SIGNATURE----- >> >> _______________________________________________ >> >> ghc-devs mailing list >> >> ghc-devs at haskell.org >> >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> > >> > >> > _______________________________________________ >> > ghc-devs mailing list >> > ghc-devs at haskell.org >> > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> > >> _______________________________________________ >> ghc-devs mailing list >> ghc-devs at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ndmitchell at gmail.com Sun Jun 28 21:09:41 2015 From: ndmitchell at gmail.com (Neil Mitchell) Date: Sun, 28 Jun 2015 22:09:41 +0100 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <558e6de1.63a6700a.5f03.2b03@mx.google.com> Message-ID: When talking about "filepath" specifically as something you prod at a specific file system, you can think about normalisation, provided you have a specific drive in mind. However, if you're going to do that, on Linux it's almost better to use an inode number. I have two specific problems with normalisation: * You might hope for the property that after normalisation equality of file locations is equality of FilePath values. That's not true. On Linux you have symlinks. On Windows you have case sensitivity, which is a property of the filesystem, not the OS. You might be able to assume a == b ==> same a b, but you can never assume a /= b ==> not (same a b), so normalisation doesn't really change the guarantee. * I believe some Emacs user once told me that a//b is not the same as a/b in some circumstances. On Windows, there are lots of programs that require / or \. Some programs require ./foo and some require foo. The exact path you pass to some programs gets baked into their output, which is visible in the final release. While paths might be equal for the purpose of asking a file system to get some bytes back, they are often different for the other things people want to do with them, like pass them to other programs that use the paths. On Sun, Jun 28, 2015 at 3:47 PM, Boespflug, Mathieu wrote: > On 28 June 2015 at 16:34, Sven Panne wrote: >> 2015-06-28 12:03 GMT+02:00 Boespflug, Mathieu : >>> >>> why does the proposal *not* include normalization? [...] >> >> >> I think this is intentional, because otherwise we are in the IO monad for >> basically all operations. What's the normalized representation of >> "foo/bar/../baz"? > > Notice that the kind of normalization I'm talking about, specified in > the link I provided, does not include this kind of normalization. > Because it requires the IO monad to perform correctly, and only on > real paths. > > Here is the link again: > > https://hackage.haskell.org/package/filepath-1.1.0.2/docs/System-FilePath-Posix.html#v:normalise > > Full canonicalization of paths, stripping out redundant ".." and > whatnot, should certainly be done in a separate function, in IO. > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From bob at redivi.com Sun Jun 28 21:09:53 2015 From: bob at redivi.com (Bob Ippolito) Date: Sun, 28 Jun 2015 14:09:53 -0700 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <558e6de1.63a6700a.5f03.2b03@mx.google.com> Message-ID: Normalization is a very hairy issue, which is not just platform specific but also filesystem specific. Mac OS X is probably the worst of all words in that respect, where HFS+ will do NFD normalization and may or may not have case sensitivity depending on how that partition was formatted. Network file shares and disk images may or may not have case sensitivity and can use either NFD or NFC normalization based on mount options. Contrary to statements earlier in the thread, NFD normalization happens on HFS+ filesystems (the default) regardless of whether you're using POSIX APIs or not. It's easy to prove this to yourself by creating a file with U+00c9 (LATIN SMALL LETTER E WITH ACUTE) in the name (from any of the APIs) and you'll see it come back out (e.g. from readdir) as two code points: 'e' and then U+0301 (COMBINING ACUTE ACCENT). It'll also do some weird transformations to file names that contain byte sequences that are not valid UTF-8. On Sun, Jun 28, 2015 at 12:05 PM, Edward Kmett wrote: > Worse there are situations where you absolutely _have_ to be able to use > \\?\ encoding of a path on Windows to read, modify or delete files with > "impossible names" that were created by other means. > > e.g. Filenames like AUX, that had traditional roles under DOS cause weird > interactions, or that were created with "impossibly long names" -- which > can happen in the wild when you move directories around, etc. > > I'm weakly in favor of the proposal precisely because it is the first > version of this concept that I've seen that DOESN'T try to get too clever > with regards to adding all sorts of normalization and this proposal seems > to be the simplest move that would enable us to do something correctly in > the future, regardless of what that correct thing winds up being. > > -Edward > > On Sun, Jun 28, 2015 at 8:09 AM, David Turner < > dct25-561bs at mythic-beasts.com> wrote: > >> Hi, >> >> I think it'd be more robust to handle normalisation when converting from >> String/Text to FilePath (and combining things with () and so on) rather >> than in the underlying representation. >> >> It's absolutely crucial that you can ask the OS for a filename (which it >> gives you as a sequence of bytes) and then pass that exact same sequence of >> bytes back to the OS without any normalisation or other useful alterations >> having taken place. >> >> You can do some deeply weird stuff in Windows by starting an absolute >> path with \\?\, including apparently using '.' and '..' as the name of a >> filesystem component: >> >> Because it turns off automatic expansion of the path string, the "\\?\" >> prefix also allows the use of ".." and "." in the path names, which can be >> useful if you are attempting to perform operations on a file with these >> otherwise reserved relative path specifiers as part of the fully qualified >> path. >> >> >> (from >> https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx >> ) >> >> I don't fancy shaking all the corner cases out of this. An explicit >> 'normalise' function seems ok, but baking normalisation into the type >> itself seems bad. >> >> Cheers, >> >> David >> >> >> On 28 June 2015 at 11:03, Boespflug, Mathieu wrote: >> >>> Hi Neil, >>> >>> why does the proposal *not* include normalization? >>> >>> There are four advantages that I see to making FilePath a datatype: >>> >>> 1. it makes it possible to implement the correct semantics for some >>> systems (including POSIX), >>> 2. it allows for information hiding, which in turn helps modularity, >>> 3. the type is distinct from any other type, hence static checks are >>> stronger, >>> 4. it becomes possible to quotient values over some arbitrary set of >>> identities that makes sense. i.e. in the case of FilePath, arguably >>> "foo/bar//baz" *is* "foo/bar/baz" *is* "foo//bar/baz" for all intents >>> and purposes, so it is not useful to distinguish these three ways of >>> writing down the same path (and in fact in practice distinguishing >>> them leads to subtle bugs). That is, the Eq instance compares >>> FilePath's modulo a few laws. >>> >>> Do you propose to forego (4)? If so why so? >>> >>> If we're going through a deprecation process, could we do so once, by >>> getting the notion of path equality we want right the first time? >>> Contrary to type indexing FilePath, it seems to me that the design >>> space for path identities is much smaller. Essentially, exactly the >>> ones here: >>> https://hackage.haskell.org/package/filepath-1.1.0.2/docs/System-FilePath-Posix.html#v:normalise >>> . >>> >>> Best, >>> >>> Mathieu >>> >>> >>> On 27 June 2015 at 12:12, Neil Mitchell wrote: >>> > Hi Niklas, >>> > >>> > The function writeFile takes a FilePath. We could fork base or tell >>> everyone >>> > to use writeFile2, but in practice everyone will keep using writeFile, >>> and >>> > this String for FilePath. This approach is the only thing we could >>> figure >>> > that made sense. >>> > >>> > Henning: we do not propose normalisation on initialisation. For ASCII >>> > strings fromFilePath . toFilePath will be id. It might also be for >>> unicode >>> > on some/all platforms. Of course, you can write your own FilePath >>> creator >>> > that does normalisation on construction. >>> > >>> > Thanks, Neil >>> > >>> > >>> > On Saturday, 27 June 2015, Niklas Larsson >>> wrote: >>> >> >>> >> Hi! >>> >> >>> >> Instead of trying to minimally patch the existing API and still >>> breaking >>> >> loads of code, why not make a new API that doesn't have to compromise >>> and >>> >> depreciate the old one? >>> >> >>> >> Niklas >>> >> ________________________________ >>> >> Fr?n: Herbert Valerio Riedel >>> >> Skickat: ?2015-?06-?26 18:09 >>> >> Till: libraries at haskell.org; ghc-devs at haskell.org >>> >> ?mne: Abstract FilePath Proposal >>> >> >>> >> -----BEGIN PGP SIGNED MESSAGE----- >>> >> Hash: SHA1 >>> >> >>> >> Hello *, >>> >> >>> >> What? >>> >> ===== >>> >> >>> >> We (see From: & CC: headers) propose, plain and simple, to turn the >>> >> currently defined type-synonym >>> >> >>> >> type FilePath = String >>> >> >>> >> into an abstract/opaque data type instead. >>> >> >>> >> Why/How/When? >>> >> ============= >>> >> >>> >> For details (including motivation and a suggested transition scheme) >>> >> please consult >>> >> >>> >> https://ghc.haskell.org/trac/ghc/wiki/Proposal/AbstractFilePath >>> >> >>> >> >>> >> >>> >> Suggested discussion period: 4 weeks >>> >> -----BEGIN PGP SIGNATURE----- >>> >> Version: GnuPG v1 >>> >> >>> >> iQIcBAEBAgAGBQJVjXkZAAoJELo8uj/+IrV0WXUP/0romoKazwLbQpaMAKgCNZon >>> >> BsY8Di44w6rkbdBXoky0xZooII8LJJyQfexH0BLRYEVLZFy0+LB8XzpPt8Ekg526 >>> >> YlY4x0qFm9oiJbJDMqHUnb6z6Lr2KxzBcV37drTPbltUA+HB49DUVkkPbvHimpL2 >>> >> 28SIyhAr4fN6fLpGcFAkv6Rcs0mkvnTp7vsC0HNyshmGi6qQ+C+eB4mklQzWOPcn >>> >> koHZ2wtI8AJmyTdHKcXKAIFM0r+xl4MJ5445IvDjvIuGXZCzybXMw9Ss/4wSG3VN >>> >> qSIJVEDGZXrBCc12fPxPEB0Bqx9MIVytjplXKIo8rFrk93h3at9t9kDM26z+9PZ5 >>> >> KYnEdjRKF4KL4j+3xqJDOEJT15GVRbGRRzb9A8xH0YIQ0S3Q3pt1PAfla1Hss75+ >>> >> NRQgfowZYryL9dfCkAj2XNfdQ+pUk25N3bNig11se+zjk2JO77QRM0u3GOYZ9+CU >>> >> tSlwhtIMF32xnjgQyWE5yBBiEg3/Y+S+809tVaPseUEzkQJXMGq5TFxBrN6bj1Vm >>> >> awr6QghThKjeoRwky5bmFn/gept/lbYN6VV5B6gNznGP5xgFrmvVtmjbQJBRMYCv >>> >> aEUnrYqxkkbIddJjD5gl771/LWH4M2F1yBgJjfiZw2paEVAXKxEr327LsbOQaPdb >>> >> HjIPRrJbVK9AABo4AZ/Y >>> >> =lg0o >>> >> -----END PGP SIGNATURE----- >>> >> _______________________________________________ >>> >> ghc-devs mailing list >>> >> ghc-devs at haskell.org >>> >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >>> > >>> > >>> > _______________________________________________ >>> > ghc-devs mailing list >>> > ghc-devs at haskell.org >>> > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >>> > >>> _______________________________________________ >>> ghc-devs mailing list >>> ghc-devs at haskell.org >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >>> >> >> >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> >> > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From allbery.b at gmail.com Sun Jun 28 21:11:42 2015 From: allbery.b at gmail.com (Brandon Allbery) Date: Sun, 28 Jun 2015 17:11:42 -0400 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <558e6de1.63a6700a.5f03.2b03@mx.google.com> Message-ID: On Sun, Jun 28, 2015 at 5:09 PM, Neil Mitchell wrote: > * I believe some Emacs user once told me that a//b is not the same as > a/b in some circumstances. > Only when typing to an interactive path prompt; it lets you reset to / without erasing the existing path prefix. This should never happen in elisp, for example. -- brandon s allbery kf8nh sine nomine associates allbery.b at gmail.com ballbery at sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net -------------- next part -------------- An HTML attachment was scrubbed... URL: From blamario at ciktel.net Mon Jun 29 02:24:01 2015 From: blamario at ciktel.net (=?UTF-8?B?TWFyaW8gQmxhxb5ldmnEhw==?=) Date: Sun, 28 Jun 2015 22:24:01 -0400 Subject: Abstract FilePath Proposal In-Reply-To: <87h9ptp91b.fsf@gmail.com> References: <874mlu8nae.fsf@gnu.org> <87h9ptp91b.fsf@gmail.com> Message-ID: <5590AC41.4030907@ciktel.net> On 06/27/2015 09:37 AM, Herbert Valerio Riedel wrote: > On 2015-06-27 at 14:56:33 +0200, David Fox wrote: > > [...] > >> ?I've had success with a slightly different "How": > What was your concrete use-case btw? > >> Phase 1: Replace FilePath with a type class, with instances for the old >> FilePath (i.e. String) and the new implementation. > what would that comprise in the FilePath case? > > I assume adding a transitional class whose methods are not exposed (and > whose typeclass name is exported from some GHC-specific internal-marked > module)? i.e. > > class IsFilePath a where > privateToFilePath :: a -> FilePath > privateFromFilePath :: FilePath -> a > > instance IsFilePath FilePath where > privateToFilePath = id > privateFromFilePath = id > > instance IsFilePath [Char] where > privateToFilePath = System.IO.toFilePath > privateFromFilePath = System.IO.fromFilePath It's probably better to not export the class at all, only its two instances and its methods. See below. > as well as changing a lot of type-sigs in base & filepath from > e.g. > > writeFile :: FilePath -> String -> IO () > openTempFile :: FilePath -> String -> IO (FilePath, Handle) > > to > > writeFile :: IsFilePath a => a -> String -> IO () > openTempFile :: IsFilePath a => a -> String -> IO (a, Handle) > > > ? > >> Phase 2: Wait until a suitable amount of hackage builds without the string >> instance. > I can see Stackage helping with that by using a custom GHC which lacks > the legacy `IsFilePath [Char]`-instance. So I'd be optimistic that Phase2 could be > accomplished within one year for the Stackage-subset of Hackage. > >> Phase 3: Deprecate the String instance - move it to an old-filepath package. >> >> Phase 4: Replace the type class with the new implementation > I assume this means getting rid again of the typeclass, and changing the > type-sigs back to i.e. > > writeFile :: FilePath -> String -> IO () > openTempFile :: FilePath -> String -> IO (FilePath, Handle) > ? > (but now with with the new opaque `FilePath`)? > >> This way the new implementation is available immediately, packages can >> begin converting at once, benefits can be assessed. > This scheme seems feasible at first glance, as long as the typeclass > doesn't start spreading across packages and find its way into type-sigs > (in which case it'd become more disruptive to get rid of it > again). Otoh, I'm not sure (assuming I understood how your scheme works) > it can be avoided to have the typeclass spread, since if not every API > that now has `FilePath` arguments in their type-sigs gets generalised to > have `IsFilePath a => a` arguments instead, we can't reach the goal of > "Phase 2". As long as the typeclass itself is not exported, this is not a big problem. Every *explicit* type signature would have to contain either a String or a FilePath. Yes, the transition to the FilePath-only state would probably be slower, but that is the intended feature, not a bug. GHC could do more to help with the transition if it allowed the DEPRECATED pragma on class instances: instance IsFilePath String {-# DEPRECATED "Use the FilePath type instead" #-} where ... The warning would be reported wherever the compiler can statically determine that the deprecated instance is used. From fumiexcel at gmail.com Mon Jun 29 06:56:40 2015 From: fumiexcel at gmail.com (Fumiaki Kinoshita) Date: Mon, 29 Jun 2015 15:56:40 +0900 Subject: Missing instance declarations in base Message-ID: I found some missing instances in the base package. The instances below are almost unique by parametricity. Data.Complex: instance Functor Complex instance Applicative Complex instance Foldable Complex -- real first instance Traversable Complex Data.Functor.Identity: instance Monoid a => Monoid (Identity a) Control.Applicative: instance Foldable ZipList instance Traversable ZipList I'm going to write a patch if there is no issue with them. Also, I wonder if () could be Storable: instance Storable () where sizeOf _ = 0 alignment _ = 1 peek _ = return () poke _ _ = return () -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Mon Jun 29 07:11:47 2015 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Mon, 29 Jun 2015 09:11:47 +0200 (CEST) Subject: Missing instance declarations in base In-Reply-To: References: Message-ID: On Mon, 29 Jun 2015, Fumiaki Kinoshita wrote: > I found some missing instances in the base package. The instances below are almost unique by parametricity. > > Data.Complex: > ? instance Functor Complex > ? instance Applicative Complex > ? instance Foldable Complex -- real first > ? instance Traversable Complex They were certainly omitted earlier because of the RealFloat constraint of the (:+) constructor. > Also, I wonder if () could be Storable: > > instance Storable () where > ? sizeOf _ = 0 > ? alignment _ = 1 > ? peek _ = return () > ? poke _ _ = return () This would allow me to remove the orphan instance from: https://hackage.haskell.org/package/storable-tuple From m at tweag.io Mon Jun 29 07:47:38 2015 From: m at tweag.io (Boespflug, Mathieu) Date: Mon, 29 Jun 2015 09:47:38 +0200 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> <558e6de1.63a6700a.5f03.2b03@mx.google.com> Message-ID: Right - given that filepath is a path manipulation library, not tied to any particular filesystem, and indeed one in which arbitrary imaginary paths can be manipulated, any normalization under consideration can only be that which is independent of global system state. What does happen in practice is that people compare paths without taking into account that a user might have written "a//b" where you have an entry for say "a/b" in your database. Normalization avoids these errors, but I can see the appeal of not interpreting the byte sequences at all, and the kind of normalization that can be done without appeal to global system state ends up being smaller than expected anyways. So +1 for the proposal as-is. On 28 June 2015 at 23:09, Neil Mitchell wrote: > When talking about "filepath" specifically as something you prod at a > specific file system, you can think about normalisation, provided you > have a specific drive in mind. However, if you're going to do that, on > Linux it's almost better to use an inode number. I have two specific > problems with normalisation: > > * You might hope for the property that after normalisation equality of > file locations is equality of FilePath values. That's not true. On > Linux you have symlinks. On Windows you have case sensitivity, which > is a property of the filesystem, not the OS. You might be able to > assume a == b ==> same a b, but you can never assume a /= b ==> not > (same a b), so normalisation doesn't really change the guarantee. > > * I believe some Emacs user once told me that a//b is not the same as > a/b in some circumstances. On Windows, there are lots of programs that > require / or \. Some programs require ./foo and some require foo. The > exact path you pass to some programs gets baked into their output, > which is visible in the final release. While paths might be equal for > the purpose of asking a file system to get some bytes back, they are > often different for the other things people want to do with them, like > pass them to other programs that use the paths. > > > > On Sun, Jun 28, 2015 at 3:47 PM, Boespflug, Mathieu wrote: >> On 28 June 2015 at 16:34, Sven Panne wrote: >>> 2015-06-28 12:03 GMT+02:00 Boespflug, Mathieu : >>>> >>>> why does the proposal *not* include normalization? [...] >>> >>> >>> I think this is intentional, because otherwise we are in the IO monad for >>> basically all operations. What's the normalized representation of >>> "foo/bar/../baz"? >> >> Notice that the kind of normalization I'm talking about, specified in >> the link I provided, does not include this kind of normalization. >> Because it requires the IO monad to perform correctly, and only on >> real paths. >> >> Here is the link again: >> >> https://hackage.haskell.org/package/filepath-1.1.0.2/docs/System-FilePath-Posix.html#v:normalise >> >> Full canonicalization of paths, stripping out redundant ".." and >> whatnot, should certainly be done in a separate function, in IO. >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From hesselink at gmail.com Mon Jun 29 08:38:51 2015 From: hesselink at gmail.com (Erik Hesselink) Date: Mon, 29 Jun 2015 10:38:51 +0200 Subject: Abstract FilePath Proposal In-Reply-To: <874mlu8nae.fsf@gnu.org> References: <874mlu8nae.fsf@gnu.org> Message-ID: I think this proposal is currently underspecified. For example, it's not clear to me what the semantics of a FilePath are. I have the feeling that `toFilePah` should return a Maybe, for example, but it's hard to say without knowing what it's converting to, exactly. I also worry about the immense breakage this will cause. This is not just an issue of causing a lot of work for maintainers, but also of lots of unmaintained libraries, printed code etc breaking. I feel that there is not enough gain in this proposal relative to the amount of breakage. Has any thought been given to introduce new modules for this type, and leave the old ones in place? Erik On Fri, Jun 26, 2015 at 6:08 PM, Herbert Valerio Riedel wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Hello *, > > What? > ===== > > We (see From: & CC: headers) propose, plain and simple, to turn the > currently defined type-synonym > > type FilePath = String > > into an abstract/opaque data type instead. > > Why/How/When? > ============= > > For details (including motivation and a suggested transition scheme) > please consult > > https://ghc.haskell.org/trac/ghc/wiki/Proposal/AbstractFilePath > > > > Suggested discussion period: 4 weeks > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1 > > iQIcBAEBAgAGBQJVjXkZAAoJELo8uj/+IrV0WXUP/0romoKazwLbQpaMAKgCNZon > BsY8Di44w6rkbdBXoky0xZooII8LJJyQfexH0BLRYEVLZFy0+LB8XzpPt8Ekg526 > YlY4x0qFm9oiJbJDMqHUnb6z6Lr2KxzBcV37drTPbltUA+HB49DUVkkPbvHimpL2 > 28SIyhAr4fN6fLpGcFAkv6Rcs0mkvnTp7vsC0HNyshmGi6qQ+C+eB4mklQzWOPcn > koHZ2wtI8AJmyTdHKcXKAIFM0r+xl4MJ5445IvDjvIuGXZCzybXMw9Ss/4wSG3VN > qSIJVEDGZXrBCc12fPxPEB0Bqx9MIVytjplXKIo8rFrk93h3at9t9kDM26z+9PZ5 > KYnEdjRKF4KL4j+3xqJDOEJT15GVRbGRRzb9A8xH0YIQ0S3Q3pt1PAfla1Hss75+ > NRQgfowZYryL9dfCkAj2XNfdQ+pUk25N3bNig11se+zjk2JO77QRM0u3GOYZ9+CU > tSlwhtIMF32xnjgQyWE5yBBiEg3/Y+S+809tVaPseUEzkQJXMGq5TFxBrN6bj1Vm > awr6QghThKjeoRwky5bmFn/gept/lbYN6VV5B6gNznGP5xgFrmvVtmjbQJBRMYCv > aEUnrYqxkkbIddJjD5gl771/LWH4M2F1yBgJjfiZw2paEVAXKxEr327LsbOQaPdb > HjIPRrJbVK9AABo4AZ/Y > =lg0o > -----END PGP SIGNATURE----- > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs From michael at snoyman.com Mon Jun 29 08:46:08 2015 From: michael at snoyman.com (Michael Snoyman) Date: Mon, 29 Jun 2015 08:46:08 +0000 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> Message-ID: Regarding underspecified: I think that's appropriate at this phase. The main proposal is: maybe FilePath an abstract type. It will take multiple GHC releases before we switch over fully, with plenty of time to hash out details of how the filepath package should work, and the opportunity to experiment with different wrappers around a core abstract type. Having used an alternate FilePath type for a while (via system-filepath), I can say that it doesn't give the same benefit of just fixing the central FilePath type. Having to convert between types all over the place is tedious, defeats a lot of the performance benefits we're going for, and hurts type safety. As someone who typically is very much opposed to breaking changes in core libraries: I think this one is well worth it. On Mon, Jun 29, 2015 at 11:39 AM Erik Hesselink wrote: > I think this proposal is currently underspecified. For example, it's > not clear to me what the semantics of a FilePath are. I have the > feeling that `toFilePah` should return a Maybe, for example, but it's > hard to say without knowing what it's converting to, exactly. > > I also worry about the immense breakage this will cause. This is not > just an issue of causing a lot of work for maintainers, but also of > lots of unmaintained libraries, printed code etc breaking. I feel that > there is not enough gain in this proposal relative to the amount of > breakage. > > Has any thought been given to introduce new modules for this type, and > leave the old ones in place? > > Erik > > On Fri, Jun 26, 2015 at 6:08 PM, Herbert Valerio Riedel > wrote: > > -----BEGIN PGP SIGNED MESSAGE----- > > Hash: SHA1 > > > > Hello *, > > > > What? > > ===== > > > > We (see From: & CC: headers) propose, plain and simple, to turn the > > currently defined type-synonym > > > > type FilePath = String > > > > into an abstract/opaque data type instead. > > > > Why/How/When? > > ============= > > > > For details (including motivation and a suggested transition scheme) > > please consult > > > > https://ghc.haskell.org/trac/ghc/wiki/Proposal/AbstractFilePath > > > > > > > > Suggested discussion period: 4 weeks > > -----BEGIN PGP SIGNATURE----- > > Version: GnuPG v1 > > > > iQIcBAEBAgAGBQJVjXkZAAoJELo8uj/+IrV0WXUP/0romoKazwLbQpaMAKgCNZon > > BsY8Di44w6rkbdBXoky0xZooII8LJJyQfexH0BLRYEVLZFy0+LB8XzpPt8Ekg526 > > YlY4x0qFm9oiJbJDMqHUnb6z6Lr2KxzBcV37drTPbltUA+HB49DUVkkPbvHimpL2 > > 28SIyhAr4fN6fLpGcFAkv6Rcs0mkvnTp7vsC0HNyshmGi6qQ+C+eB4mklQzWOPcn > > koHZ2wtI8AJmyTdHKcXKAIFM0r+xl4MJ5445IvDjvIuGXZCzybXMw9Ss/4wSG3VN > > qSIJVEDGZXrBCc12fPxPEB0Bqx9MIVytjplXKIo8rFrk93h3at9t9kDM26z+9PZ5 > > KYnEdjRKF4KL4j+3xqJDOEJT15GVRbGRRzb9A8xH0YIQ0S3Q3pt1PAfla1Hss75+ > > NRQgfowZYryL9dfCkAj2XNfdQ+pUk25N3bNig11se+zjk2JO77QRM0u3GOYZ9+CU > > tSlwhtIMF32xnjgQyWE5yBBiEg3/Y+S+809tVaPseUEzkQJXMGq5TFxBrN6bj1Vm > > awr6QghThKjeoRwky5bmFn/gept/lbYN6VV5B6gNznGP5xgFrmvVtmjbQJBRMYCv > > aEUnrYqxkkbIddJjD5gl771/LWH4M2F1yBgJjfiZw2paEVAXKxEr327LsbOQaPdb > > HjIPRrJbVK9AABo4AZ/Y > > =lg0o > > -----END PGP SIGNATURE----- > > _______________________________________________ > > ghc-devs mailing list > > ghc-devs at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hesselink at gmail.com Mon Jun 29 09:07:36 2015 From: hesselink at gmail.com (Erik Hesselink) Date: Mon, 29 Jun 2015 11:07:36 +0200 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> Message-ID: On Mon, Jun 29, 2015 at 10:46 AM, Michael Snoyman wrote: > Regarding underspecified: I think that's appropriate at this phase. The main > proposal is: maybe FilePath an abstract type. It will take multiple GHC > releases before we switch over fully, with plenty of time to hash out > details of how the filepath package should work, and the opportunity to > experiment with different wrappers around a core abstract type. But changing the semantics of an established newtype is very tricky business, since the resulting breakage won't be indicated by the types! > Having used an alternate FilePath type for a while (via system-filepath), I > can say that it doesn't give the same benefit of just fixing the central > FilePath type. Having to convert between types all over the place is > tedious, defeats a lot of the performance benefits we're going for, and > hurts type safety. Why would you have to convert 'all over the place'? If the alternative library also provides the basic IO functions, the only places you'd have to convert are interfaces with other libraries, and things from e.g. config file, both of which don't happen a lot. > As someone who typically is very much opposed to breaking changes in core > libraries: I think this one is well worth it. Do you have any insight in the amount of breakage this will cause? I have a gut feeling that it's a lot more than any of the previous changes we've had, and those have already caused a lot of grumbling. But the only way to be sure is to run the builds on hackage (or stackage, but that's a smaller sample size). Erik > On Mon, Jun 29, 2015 at 11:39 AM Erik Hesselink wrote: >> >> I think this proposal is currently underspecified. For example, it's >> not clear to me what the semantics of a FilePath are. I have the >> feeling that `toFilePah` should return a Maybe, for example, but it's >> hard to say without knowing what it's converting to, exactly. >> >> I also worry about the immense breakage this will cause. This is not >> just an issue of causing a lot of work for maintainers, but also of >> lots of unmaintained libraries, printed code etc breaking. I feel that >> there is not enough gain in this proposal relative to the amount of >> breakage. >> >> Has any thought been given to introduce new modules for this type, and >> leave the old ones in place? >> >> Erik >> >> On Fri, Jun 26, 2015 at 6:08 PM, Herbert Valerio Riedel >> wrote: >> > -----BEGIN PGP SIGNED MESSAGE----- >> > Hash: SHA1 >> > >> > Hello *, >> > >> > What? >> > ===== >> > >> > We (see From: & CC: headers) propose, plain and simple, to turn the >> > currently defined type-synonym >> > >> > type FilePath = String >> > >> > into an abstract/opaque data type instead. >> > >> > Why/How/When? >> > ============= >> > >> > For details (including motivation and a suggested transition scheme) >> > please consult >> > >> > https://ghc.haskell.org/trac/ghc/wiki/Proposal/AbstractFilePath >> > >> > >> > >> > Suggested discussion period: 4 weeks >> > -----BEGIN PGP SIGNATURE----- >> > Version: GnuPG v1 >> > >> > iQIcBAEBAgAGBQJVjXkZAAoJELo8uj/+IrV0WXUP/0romoKazwLbQpaMAKgCNZon >> > BsY8Di44w6rkbdBXoky0xZooII8LJJyQfexH0BLRYEVLZFy0+LB8XzpPt8Ekg526 >> > YlY4x0qFm9oiJbJDMqHUnb6z6Lr2KxzBcV37drTPbltUA+HB49DUVkkPbvHimpL2 >> > 28SIyhAr4fN6fLpGcFAkv6Rcs0mkvnTp7vsC0HNyshmGi6qQ+C+eB4mklQzWOPcn >> > koHZ2wtI8AJmyTdHKcXKAIFM0r+xl4MJ5445IvDjvIuGXZCzybXMw9Ss/4wSG3VN >> > qSIJVEDGZXrBCc12fPxPEB0Bqx9MIVytjplXKIo8rFrk93h3at9t9kDM26z+9PZ5 >> > KYnEdjRKF4KL4j+3xqJDOEJT15GVRbGRRzb9A8xH0YIQ0S3Q3pt1PAfla1Hss75+ >> > NRQgfowZYryL9dfCkAj2XNfdQ+pUk25N3bNig11se+zjk2JO77QRM0u3GOYZ9+CU >> > tSlwhtIMF32xnjgQyWE5yBBiEg3/Y+S+809tVaPseUEzkQJXMGq5TFxBrN6bj1Vm >> > awr6QghThKjeoRwky5bmFn/gept/lbYN6VV5B6gNznGP5xgFrmvVtmjbQJBRMYCv >> > aEUnrYqxkkbIddJjD5gl771/LWH4M2F1yBgJjfiZw2paEVAXKxEr327LsbOQaPdb >> > HjIPRrJbVK9AABo4AZ/Y >> > =lg0o >> > -----END PGP SIGNATURE----- >> > _______________________________________________ >> > ghc-devs mailing list >> > ghc-devs at haskell.org >> > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> _______________________________________________ >> ghc-devs mailing list >> ghc-devs at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs From michael at snoyman.com Mon Jun 29 09:22:49 2015 From: michael at snoyman.com (Michael Snoyman) Date: Mon, 29 Jun 2015 09:22:49 +0000 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> Message-ID: On Mon, Jun 29, 2015 at 12:07 PM Erik Hesselink wrote: > On Mon, Jun 29, 2015 at 10:46 AM, Michael Snoyman > wrote: > > Regarding underspecified: I think that's appropriate at this phase. The > main > > proposal is: maybe FilePath an abstract type. It will take multiple GHC > > releases before we switch over fully, with plenty of time to hash out > > details of how the filepath package should work, and the opportunity to > > experiment with different wrappers around a core abstract type. > > But changing the semantics of an established newtype is very tricky > business, since the resulting breakage won't be indicated by the > types! > > My suggestion isn't to roll out one breaking change and then another silent semantics change later. Rather, my point is: getting FilePath to be an abstract type is the meat of the proposal, and what we need to agree on. Working out the exact semantics of how the filepath package interacts with that is important, but not urgent. Let's get to an agreement that an abstract type is an improvement, and then we can figure out exactly how it should behave. After all, we'll have about 2 years to figure that out. > > Having used an alternate FilePath type for a while (via > system-filepath), I > > can say that it doesn't give the same benefit of just fixing the central > > FilePath type. Having to convert between types all over the place is > > tedious, defeats a lot of the performance benefits we're going for, and > > hurts type safety. > > Why would you have to convert 'all over the place'? If the alternative > library also provides the basic IO functions, the only places you'd > have to convert are interfaces with other libraries, and things from > e.g. config file, both of which don't happen a lot. > > By having two different types, we know that not everyone will convert over. In fact, the very argument for having two types is so that not everyone will need to convert. Especially if Prelude continues to export the current `type FilePath = [Char]`, it will be difficult to get all libraries to use the new type. > > As someone who typically is very much opposed to breaking changes in core > > libraries: I think this one is well worth it. > > Do you have any insight in the amount of breakage this will cause? I > have a gut feeling that it's a lot more than any of the previous > changes we've had, and those have already caused a lot of grumbling. > But the only way to be sure is to run the builds on hackage (or > stackage, but that's a smaller sample size). > > I agree, this is going to be a big one. It does not lend itself to elegant migrations like FTP did, for instance. But the scope of the current problem is also large, which is why I believe this breakage is warranted. Doing it gradually with a deprecation plan will hopefully make it possible for us to make it as easy as possible. > Erik > > > On Mon, Jun 29, 2015 at 11:39 AM Erik Hesselink > wrote: > >> > >> I think this proposal is currently underspecified. For example, it's > >> not clear to me what the semantics of a FilePath are. I have the > >> feeling that `toFilePah` should return a Maybe, for example, but it's > >> hard to say without knowing what it's converting to, exactly. > >> > >> I also worry about the immense breakage this will cause. This is not > >> just an issue of causing a lot of work for maintainers, but also of > >> lots of unmaintained libraries, printed code etc breaking. I feel that > >> there is not enough gain in this proposal relative to the amount of > >> breakage. > >> > >> Has any thought been given to introduce new modules for this type, and > >> leave the old ones in place? > >> > >> Erik > >> > >> On Fri, Jun 26, 2015 at 6:08 PM, Herbert Valerio Riedel > >> wrote: > >> > -----BEGIN PGP SIGNED MESSAGE----- > >> > Hash: SHA1 > >> > > >> > Hello *, > >> > > >> > What? > >> > ===== > >> > > >> > We (see From: & CC: headers) propose, plain and simple, to turn the > >> > currently defined type-synonym > >> > > >> > type FilePath = String > >> > > >> > into an abstract/opaque data type instead. > >> > > >> > Why/How/When? > >> > ============= > >> > > >> > For details (including motivation and a suggested transition scheme) > >> > please consult > >> > > >> > https://ghc.haskell.org/trac/ghc/wiki/Proposal/AbstractFilePath > >> > > >> > > >> > > >> > Suggested discussion period: 4 weeks > >> > -----BEGIN PGP SIGNATURE----- > >> > Version: GnuPG v1 > >> > > >> > iQIcBAEBAgAGBQJVjXkZAAoJELo8uj/+IrV0WXUP/0romoKazwLbQpaMAKgCNZon > >> > BsY8Di44w6rkbdBXoky0xZooII8LJJyQfexH0BLRYEVLZFy0+LB8XzpPt8Ekg526 > >> > YlY4x0qFm9oiJbJDMqHUnb6z6Lr2KxzBcV37drTPbltUA+HB49DUVkkPbvHimpL2 > >> > 28SIyhAr4fN6fLpGcFAkv6Rcs0mkvnTp7vsC0HNyshmGi6qQ+C+eB4mklQzWOPcn > >> > koHZ2wtI8AJmyTdHKcXKAIFM0r+xl4MJ5445IvDjvIuGXZCzybXMw9Ss/4wSG3VN > >> > qSIJVEDGZXrBCc12fPxPEB0Bqx9MIVytjplXKIo8rFrk93h3at9t9kDM26z+9PZ5 > >> > KYnEdjRKF4KL4j+3xqJDOEJT15GVRbGRRzb9A8xH0YIQ0S3Q3pt1PAfla1Hss75+ > >> > NRQgfowZYryL9dfCkAj2XNfdQ+pUk25N3bNig11se+zjk2JO77QRM0u3GOYZ9+CU > >> > tSlwhtIMF32xnjgQyWE5yBBiEg3/Y+S+809tVaPseUEzkQJXMGq5TFxBrN6bj1Vm > >> > awr6QghThKjeoRwky5bmFn/gept/lbYN6VV5B6gNznGP5xgFrmvVtmjbQJBRMYCv > >> > aEUnrYqxkkbIddJjD5gl771/LWH4M2F1yBgJjfiZw2paEVAXKxEr327LsbOQaPdb > >> > HjIPRrJbVK9AABo4AZ/Y > >> > =lg0o > >> > -----END PGP SIGNATURE----- > >> > _______________________________________________ > >> > ghc-devs mailing list > >> > ghc-devs at haskell.org > >> > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > >> _______________________________________________ > >> ghc-devs mailing list > >> ghc-devs at haskell.org > >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From dct25-561bs at mythic-beasts.com Mon Jun 29 09:27:24 2015 From: dct25-561bs at mythic-beasts.com (David Turner) Date: Mon, 29 Jun 2015 10:27:24 +0100 Subject: Abstract FilePath Proposal In-Reply-To: <874mlu8nae.fsf@gnu.org> References: <874mlu8nae.fsf@gnu.org> Message-ID: One tiny amendment to a comment(!) in the non-normative(!) code in Phase 3: data WindowsFilePath = WFP ByteArray# -- UTF16 data If a Windows file path is valid UTF-16 then it is displayed as such in the GUI, but if not it's still a legal file path. It really is just wchar_t[] data: data WindowsFilePath = WFP ByteArray# -- wchar_t[] data as passed to syscalls This seems to be the source of some confusion. Cheers, David On 26 June 2015 at 17:08, Herbert Valerio Riedel wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Hello *, > > What? > ===== > > We (see From: & CC: headers) propose, plain and simple, to turn the > currently defined type-synonym > > type FilePath = String > > into an abstract/opaque data type instead. > > Why/How/When? > ============= > > For details (including motivation and a suggested transition scheme) > please consult > > https://ghc.haskell.org/trac/ghc/wiki/Proposal/AbstractFilePath > > > > Suggested discussion period: 4 weeks > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1 > > iQIcBAEBAgAGBQJVjXkZAAoJELo8uj/+IrV0WXUP/0romoKazwLbQpaMAKgCNZon > BsY8Di44w6rkbdBXoky0xZooII8LJJyQfexH0BLRYEVLZFy0+LB8XzpPt8Ekg526 > YlY4x0qFm9oiJbJDMqHUnb6z6Lr2KxzBcV37drTPbltUA+HB49DUVkkPbvHimpL2 > 28SIyhAr4fN6fLpGcFAkv6Rcs0mkvnTp7vsC0HNyshmGi6qQ+C+eB4mklQzWOPcn > koHZ2wtI8AJmyTdHKcXKAIFM0r+xl4MJ5445IvDjvIuGXZCzybXMw9Ss/4wSG3VN > qSIJVEDGZXrBCc12fPxPEB0Bqx9MIVytjplXKIo8rFrk93h3at9t9kDM26z+9PZ5 > KYnEdjRKF4KL4j+3xqJDOEJT15GVRbGRRzb9A8xH0YIQ0S3Q3pt1PAfla1Hss75+ > NRQgfowZYryL9dfCkAj2XNfdQ+pUk25N3bNig11se+zjk2JO77QRM0u3GOYZ9+CU > tSlwhtIMF32xnjgQyWE5yBBiEg3/Y+S+809tVaPseUEzkQJXMGq5TFxBrN6bj1Vm > awr6QghThKjeoRwky5bmFn/gept/lbYN6VV5B6gNznGP5xgFrmvVtmjbQJBRMYCv > aEUnrYqxkkbIddJjD5gl771/LWH4M2F1yBgJjfiZw2paEVAXKxEr327LsbOQaPdb > HjIPRrJbVK9AABo4AZ/Y > =lg0o > -----END PGP SIGNATURE----- > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From andreas.abel at ifi.lmu.de Mon Jun 29 09:33:35 2015 From: andreas.abel at ifi.lmu.de (Andreas Abel) Date: Mon, 29 Jun 2015 11:33:35 +0200 Subject: Missing instance declarations in base In-Reply-To: References: Message-ID: <559110EF.5000107@ifi.lmu.de> +1. On 29.06.2015 08:56, Fumiaki Kinoshita wrote: > I found some missing instances in the base package. The instances below > are almost unique by parametricity. > > Data.Complex: > instance Functor Complex > instance Applicative Complex > instance Foldable Complex -- real first > instance Traversable Complex > > Data.Functor.Identity: > instance Monoid a => Monoid (Identity a) > > Control.Applicative: > instance Foldable ZipList > instance Traversable ZipList > > I'm going to write a patch if there is no issue with them. > > Also, I wonder if () could be Storable: > > instance Storable () where > sizeOf _ = 0 > alignment _ = 1 > peek _ = return () > poke _ _ = return () > > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -- Andreas Abel <>< Du bist der geliebte Mensch. Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden andreas.abel at gu.se http://www2.tcs.ifi.lmu.de/~abel/ From alois.cochard at gmail.com Mon Jun 29 09:57:46 2015 From: alois.cochard at gmail.com (Alois Cochard) Date: Mon, 29 Jun 2015 11:57:46 +0200 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> Message-ID: +1 for the first two phase of the original proposal. I always wished it was not a type alias. No strong opinion of phase 3, I have propabaly never run into sophisticated enough issues to fully get the picture... but I doubt we'll be able to craft an ideal cross-platform API, I like what is in spirit in the original proposal. On 29 June 2015 at 11:27, David Turner wrote: > One tiny amendment to a comment(!) in the non-normative(!) code in Phase 3: > > data WindowsFilePath = WFP ByteArray# -- UTF16 data > > > If a Windows file path is valid UTF-16 then it is displayed as such in the > GUI, but if not it's still a legal file path. It really is just wchar_t[] > data: > > data WindowsFilePath = WFP ByteArray# -- wchar_t[] data as passed to syscalls > > > This seems to be the source of some confusion. > > > Cheers, > > > David > > > > On 26 June 2015 at 17:08, Herbert Valerio Riedel wrote: > >> -----BEGIN PGP SIGNED MESSAGE----- >> Hash: SHA1 >> >> Hello *, >> >> What? >> ===== >> >> We (see From: & CC: headers) propose, plain and simple, to turn the >> currently defined type-synonym >> >> type FilePath = String >> >> into an abstract/opaque data type instead. >> >> Why/How/When? >> ============= >> >> For details (including motivation and a suggested transition scheme) >> please consult >> >> https://ghc.haskell.org/trac/ghc/wiki/Proposal/AbstractFilePath >> >> >> >> Suggested discussion period: 4 weeks >> -----BEGIN PGP SIGNATURE----- >> Version: GnuPG v1 >> >> iQIcBAEBAgAGBQJVjXkZAAoJELo8uj/+IrV0WXUP/0romoKazwLbQpaMAKgCNZon >> BsY8Di44w6rkbdBXoky0xZooII8LJJyQfexH0BLRYEVLZFy0+LB8XzpPt8Ekg526 >> YlY4x0qFm9oiJbJDMqHUnb6z6Lr2KxzBcV37drTPbltUA+HB49DUVkkPbvHimpL2 >> 28SIyhAr4fN6fLpGcFAkv6Rcs0mkvnTp7vsC0HNyshmGi6qQ+C+eB4mklQzWOPcn >> koHZ2wtI8AJmyTdHKcXKAIFM0r+xl4MJ5445IvDjvIuGXZCzybXMw9Ss/4wSG3VN >> qSIJVEDGZXrBCc12fPxPEB0Bqx9MIVytjplXKIo8rFrk93h3at9t9kDM26z+9PZ5 >> KYnEdjRKF4KL4j+3xqJDOEJT15GVRbGRRzb9A8xH0YIQ0S3Q3pt1PAfla1Hss75+ >> NRQgfowZYryL9dfCkAj2XNfdQ+pUk25N3bNig11se+zjk2JO77QRM0u3GOYZ9+CU >> tSlwhtIMF32xnjgQyWE5yBBiEg3/Y+S+809tVaPseUEzkQJXMGq5TFxBrN6bj1Vm >> awr6QghThKjeoRwky5bmFn/gept/lbYN6VV5B6gNznGP5xgFrmvVtmjbQJBRMYCv >> aEUnrYqxkkbIddJjD5gl771/LWH4M2F1yBgJjfiZw2paEVAXKxEr327LsbOQaPdb >> HjIPRrJbVK9AABo4AZ/Y >> =lg0o >> -----END PGP SIGNATURE----- >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> > > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > -- *?\ois* http://twitter.com/aloiscochard http://github.com/aloiscochard -------------- next part -------------- An HTML attachment was scrubbed... URL: From matthewtpickering at gmail.com Mon Jun 29 12:13:54 2015 From: matthewtpickering at gmail.com (Matthew Pickering) Date: Mon, 29 Jun 2015 13:13:54 +0100 Subject: haskell-src-exts maintenance Message-ID: Dear List, There are a large number of untriaged pull requests and issues currently open on the issue tracker for haskell-src-exts. The tool is widely used by tool writers but the last commit to the project is now over 6 months ago. I think it is important to get this work merged and update the parser to support modern language features introduced in GHC 7.8 and 7.10. I would personally be capable of helping with this effort but before doing so I would appreciate a comment from the current maintainers as to the current status of the project. So, 1. Does anyone know if Niklas or Peter plan to return to the project? 2. Is there anyone else who is interested in updating the HSE parser? Matt From ekmett at gmail.com Mon Jun 29 15:00:35 2015 From: ekmett at gmail.com (Edward Kmett) Date: Mon, 29 Jun 2015 11:00:35 -0400 Subject: Missing instance declarations in base In-Reply-To: References: Message-ID: On Mon, Jun 29, 2015 at 2:56 AM, Fumiaki Kinoshita wrote: > I found some missing instances in the base package. The instances below > are almost unique by parametricity. > > Data.Complex: > instance Functor Complex > instance Applicative Complex > instance Foldable Complex -- real first > instance Traversable Complex > I've had to have orphans for these in order to make linear work for years now. No objection to adding them. They were blocked before by the RealFloat a => data type context. > Data.Functor.Identity: > instance Monoid a => Monoid (Identity a) > > Control.Applicative: > instance Foldable ZipList > instance Traversable ZipList > > I'm going to write a patch if there is no issue with them. > > Also, I wonder if () could be Storable: > > instance Storable () where > sizeOf _ = 0 > alignment _ = 1 > peek _ = return () > poke _ _ = return () > No objection from me to any of them; a very strong +1. -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Mon Jun 29 15:04:52 2015 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Mon, 29 Jun 2015 17:04:52 +0200 (CEST) Subject: Missing instance declarations in base In-Reply-To: References: Message-ID: On Mon, 29 Jun 2015, Edward Kmett wrote: > Also, I wonder if () could be Storable: > > instance Storable () where > ? sizeOf _ = 0 > ? alignment _ = 1 > ? peek _ = return () > ? poke _ _ = return () > > > No objection from me to any of them; a very strong +1. Btw. what about Storable (a,b) and Storable (a,b,c)? From ekmett at gmail.com Mon Jun 29 15:18:20 2015 From: ekmett at gmail.com (Edward Kmett) Date: Mon, 29 Jun 2015 11:18:20 -0400 Subject: Missing instance declarations in base In-Reply-To: References: Message-ID: The main problem with adding those in general is that then we have to get deeper into the business of packing and alignment. You need to add the spacers for when the second structure isn't aligned with the first, and the logic for that isn't cross-platform friendly. -Edward On Mon, Jun 29, 2015 at 11:04 AM, Henning Thielemann < lemming at henning-thielemann.de> wrote: > > On Mon, 29 Jun 2015, Edward Kmett wrote: > > Also, I wonder if () could be Storable: >> >> instance Storable () where >> sizeOf _ = 0 >> alignment _ = 1 >> peek _ = return () >> poke _ _ = return () >> >> >> No objection from me to any of them; a very strong +1. >> > > Btw. what about Storable (a,b) and Storable (a,b,c)? -------------- next part -------------- An HTML attachment was scrubbed... URL: From mike at izbicki.me Mon Jun 29 16:46:39 2015 From: mike at izbicki.me (Mike Izbicki) Date: Mon, 29 Jun 2015 09:46:39 -0700 Subject: Missing instance declarations in base In-Reply-To: References: Message-ID: Are the alignment issues for tuples not something that CPP could fix? On Mon, Jun 29, 2015 at 8:18 AM, Edward Kmett wrote: > The main problem with adding those in general is that then we have to get > deeper into the business of packing and alignment. You need to add the > spacers for when the second structure isn't aligned with the first, and the > logic for that isn't cross-platform friendly. > > -Edward > > > > On Mon, Jun 29, 2015 at 11:04 AM, Henning Thielemann > wrote: >> >> >> On Mon, 29 Jun 2015, Edward Kmett wrote: >> >>> Also, I wonder if () could be Storable: >>> >>> instance Storable () where >>> sizeOf _ = 0 >>> alignment _ = 1 >>> peek _ = return () >>> poke _ _ = return () >>> >>> >>> No objection from me to any of them; a very strong +1. >> >> >> Btw. what about Storable (a,b) and Storable (a,b,c)? > > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > From ekmett at gmail.com Mon Jun 29 20:32:05 2015 From: ekmett at gmail.com (Edward Kmett) Date: Mon, 29 Jun 2015 16:32:05 -0400 Subject: Missing instance declarations in base In-Reply-To: References: Message-ID: It depends. The problem is ultimately that folks use Storable for many things. Sometimes it is native interop, but sometimes it is for serializing out to a known binary file format, etc. In the absence of these extra instances we do not have to choose its "real" role. If we added them then we'd start committing to one of those scenarios. -Edward On Mon, Jun 29, 2015 at 12:46 PM, Mike Izbicki wrote: > Are the alignment issues for tuples not something that CPP could fix? > > On Mon, Jun 29, 2015 at 8:18 AM, Edward Kmett wrote: > > The main problem with adding those in general is that then we have to get > > deeper into the business of packing and alignment. You need to add the > > spacers for when the second structure isn't aligned with the first, and > the > > logic for that isn't cross-platform friendly. > > > > -Edward > > > > > > > > On Mon, Jun 29, 2015 at 11:04 AM, Henning Thielemann > > wrote: > >> > >> > >> On Mon, 29 Jun 2015, Edward Kmett wrote: > >> > >>> Also, I wonder if () could be Storable: > >>> > >>> instance Storable () where > >>> sizeOf _ = 0 > >>> alignment _ = 1 > >>> peek _ = return () > >>> poke _ _ = return () > >>> > >>> > >>> No objection from me to any of them; a very strong +1. > >> > >> > >> Btw. what about Storable (a,b) and Storable (a,b,c)? > > > > > > > > _______________________________________________ > > Libraries mailing list > > Libraries at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Mon Jun 29 20:40:17 2015 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Mon, 29 Jun 2015 22:40:17 +0200 (CEST) Subject: Missing instance declarations in base In-Reply-To: References: Message-ID: On Mon, 29 Jun 2015, Edward Kmett wrote: > It depends. The problem is ultimately that folks use Storable for many > things. Sometimes it is native interop, but sometimes it is for > serializing out to a known binary file format, etc. In the absence of > these extra instances we do not have to choose its "real" role. If we > added them then we'd start committing to one of those scenarios. The Storable class is part of the FFI and thus I think we must comply to the system ABI. From svenpanne at gmail.com Mon Jun 29 20:46:59 2015 From: svenpanne at gmail.com (Sven Panne) Date: Mon, 29 Jun 2015 22:46:59 +0200 Subject: Missing instance declarations in base In-Reply-To: References: Message-ID: 2015-06-29 22:40 GMT+02:00 Henning Thielemann : > > On Mon, 29 Jun 2015, Edward Kmett wrote: > > It depends. The problem is ultimately that folks use Storable for many >> things. Sometimes it is native interop, but sometimes it is for serializing >> out to a known binary file format, etc. In the absence of these extra >> instances we do not have to choose its "real" role. If we added them then >> we'd start committing to one of those scenarios. >> > > The Storable class is part of the FFI and thus I think we must comply to > the system ABI. -1 to obeying the system ABI blindly for tuples: There is the notion of packed structures, not everything using the FFI uses the system ABI (e.g. various OpenGL data structures), etc. Having some kind of support for the system ABI would be nice, but this should not be mixed with the Storable class IMHO. -------------- next part -------------- An HTML attachment was scrubbed... URL: From allbery.b at gmail.com Mon Jun 29 20:48:27 2015 From: allbery.b at gmail.com (Brandon Allbery) Date: Mon, 29 Jun 2015 16:48:27 -0400 Subject: Missing instance declarations in base In-Reply-To: References: Message-ID: On Mon, Jun 29, 2015 at 4:46 PM, Sven Panne wrote: > -1 to obeying the system ABI blindly for tuples: There is the notion of > packed structures, not everything using the FFI uses the system ABI (e.g. > various OpenGL data structures), etc. Having some kind of support for the > system ABI would be nice, but this should not be mixed with the Storable > class IMHO. The FFI being part of the Haskell Report, and Storable being necessary for implementation, I think it's on you to produce a new suitable class instead. -- brandon s allbery kf8nh sine nomine associates allbery.b at gmail.com ballbery at sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Mon Jun 29 20:55:42 2015 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Mon, 29 Jun 2015 22:55:42 +0200 (CEST) Subject: Missing instance declarations in base In-Reply-To: References: Message-ID: On Mon, 29 Jun 2015, Brandon Allbery wrote: > On Mon, Jun 29, 2015 at 4:46 PM, Sven Panne wrote: > -1 to obeying the system ABI blindly for tuples: There is the notion of packed structures, not > everything using the FFI uses the system ABI (e.g. various OpenGL data structures), etc. Having > some kind of support for the system ABI would be nice, but this should not be mixed with the > Storable class IMHO. > > > The FFI being part of the Haskell Report, and Storable being necessary > for implementation, I think it's on you to produce a new suitable class > instead. I think the same. For packed structures you would need a new PackedStorable class. From qdunkan at gmail.com Mon Jun 29 20:57:15 2015 From: qdunkan at gmail.com (Evan Laforge) Date: Mon, 29 Jun 2015 13:57:15 -0700 Subject: Missing instance declarations in base In-Reply-To: References: Message-ID: On Mon, Jun 29, 2015 at 1:40 PM, Henning Thielemann wrote: > The Storable class is part of the FFI and thus I think we must comply to the > system ABI. I think it's actually kind of overloaded, because it has haskell-only types like Char. I actually think it's really dangerous and we should have a separate Storable for each language, which only that language's types (that just C at the moment). I've already done it that way for quite a few years now. So I'm against tuples in Storable because tuples don't exist in C, so you should really be using a record with a corresponding struct. For non-FFI use a tuple makes sense, but aren't there lots of other ways to do that? E.g. I think Data.Vector.Unboxed has special support, and binary serialization has Data.Binary, etc. From lemming at henning-thielemann.de Mon Jun 29 21:05:42 2015 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Mon, 29 Jun 2015 23:05:42 +0200 (CEST) Subject: Missing instance declarations in base In-Reply-To: References: Message-ID: On Mon, 29 Jun 2015, Evan Laforge wrote: > I think it's actually kind of overloaded, because it has haskell-only > types like Char. good point > So I'm against tuples in Storable because tuples don't exist in C, so > you should really be using a record with a corresponding struct. I have used them to call functions compiled by LLVM-JIT. LLVM supports tuple types. I guess that LLVM tuples are just structs without field names. From allbery.b at gmail.com Mon Jun 29 21:09:29 2015 From: allbery.b at gmail.com (Brandon Allbery) Date: Mon, 29 Jun 2015 17:09:29 -0400 Subject: Missing instance declarations in base In-Reply-To: References: Message-ID: On Mon, Jun 29, 2015 at 5:05 PM, Henning Thielemann < lemming at henning-thielemann.de> wrote: > > On Mon, 29 Jun 2015, Evan Laforge wrote: > > I think it's actually kind of overloaded, because it has haskell-only >> types like Char. >> > > good point Hm. If it does so in any way other than specifying how they marshal to C types, that sounds like a problem with the definition of Storable. (Flip side, that marshaling is kinda the point of an FFI.) > So I'm against tuples in Storable because tuples don't exist in C, so >> you should really be using a record with a corresponding struct. >> > > I have used them to call functions compiled by LLVM-JIT. LLVM supports > tuple types. I guess that LLVM tuples are just structs without field names. LLVM does target more than just C (and therefore more than just C types). I think my question here is "is there an agreed-on ABI for these types, beyond LLVM's own?" -- brandon s allbery kf8nh sine nomine associates allbery.b at gmail.com ballbery at sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net -------------- next part -------------- An HTML attachment was scrubbed... URL: From svenpanne at gmail.com Tue Jun 30 08:10:20 2015 From: svenpanne at gmail.com (Sven Panne) Date: Tue, 30 Jun 2015 10:10:20 +0200 Subject: Missing instance declarations in base In-Reply-To: References: Message-ID: 2015-06-29 23:09 GMT+02:00 Brandon Allbery : > On Mon, Jun 29, 2015 at 5:05 PM, Henning Thielemann < > lemming at henning-thielemann.de> wrote: >> >> On Mon, 29 Jun 2015, Evan Laforge wrote: >> >> I think it's actually kind of overloaded, because it has haskell-only >>> types like Char. >>> >> >> good point > > > Hm. If it does so in any way other than specifying how they marshal to C > types, that sounds like a problem with the definition of Storable. (Flip > side, that marshaling is kinda the point of an FFI.) > Actually there is nothing dangerous/overloaded/etc. at all: When we designed the FFI, we had 2 use cases in mind: * Bind some existing C stuff to Haskell. This is what CInt, CFloat, etc. are for. * Extend existing Haskell code with C: This is what HsInt, HsFloat etc. are for. > So I'm against tuples in Storable because tuples don't exist in C, so >>> you should really be using a record with a corresponding struct. >>> >> >> I have used them to call functions compiled by LLVM-JIT. LLVM supports >> tuple types. I guess that LLVM tuples are just structs without field names. > > > LLVM does target more than just C (and therefore more than just C types). > I think my question here is "is there an agreed-on ABI for these types, > beyond LLVM's own?" > We intentionally left out marshaling of compound structures out of the spec, because this would open (as we just see :-) a can of worms, even if we would restrict ourselves to just C. The FFI and the Storable instances in the report are just the necessary building blocks (which can't be expressed otherwise) for higher-level stuff and the intention was to use tools like c2hs etc. for more complicated things. One more argument why Storable instances for tuples are a bad idea: To make this consistent, one would have to align 1-tuples (i.e. normal values like CFloat etc.), too, because most ABIs require this. But this is intentionally not what their instances do. -------------- next part -------------- An HTML attachment was scrubbed... URL: From ndmitchell at gmail.com Tue Jun 30 09:25:02 2015 From: ndmitchell at gmail.com (Neil Mitchell) Date: Tue, 30 Jun 2015 10:25:02 +0100 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> Message-ID: Hi David, > One tiny amendment to a comment(!) in the non-normative(!) code in Phase 3: > > data WindowsFilePath = WFP ByteArray# -- UTF16 data > > If a Windows file path is valid UTF-16 then it is displayed as such in the > GUI, but if not it's still a legal file path. It really is just wchar_t[] > data. Thanks for bringing this up. It's tricky - I think in practice: toFilePath x = WPF (encodeStringAsUTF16 x) But the data in WPF will be treated as UCS2 (aka wchar_t) when passing to the API calls, so it's really both. While on Windows NT it really was UCS2, but Win 7 it's always treated as UTF16 in the GUI, so that seems to be consistent with what people expect and ensures we don't throw away information when converting to/from FilePath. Given it seems you are quite knowledgeable in this area, please shout if that seems misguided! To all the people who are worried about breakage, I can guarantee this will cause breakage. It's a sad fact, and certainly the main negative to this proposal. I was on the fence initially when hvr suggested this change to me, but was convinced by performance and correctness. Whether the Haskell community as a whole thinks that makes it worth it is why it's a proposal. If anything, I'm concerned by the lack of people saying -1, please don't break my code... Thanks, Neil From hesselink at gmail.com Tue Jun 30 09:45:36 2015 From: hesselink at gmail.com (Erik Hesselink) Date: Tue, 30 Jun 2015 11:45:36 +0200 Subject: Abstract FilePath Proposal In-Reply-To: References: <874mlu8nae.fsf@gnu.org> Message-ID: On Tue, Jun 30, 2015 at 11:25 AM, Neil Mitchell wrote: > To all the people who are worried about breakage, I can guarantee this > will cause breakage. It's a sad fact, and certainly the main negative > to this proposal. I was on the fence initially when hvr suggested this > change to me, but was convinced by performance and correctness. > Whether the Haskell community as a whole thinks that makes it worth it > is why it's a proposal. If anything, I'm concerned by the lack of > people saying -1, please don't break my code... I'm not convinced by the performance argument. Most people don't need performance from the small amount of FilePath usage they have. Those who do can switch to a different package. Now correctness would be a good argument, but this proposal doesn't really add that much in that respect, it seems. I'm still on the fence, but leaning towards -1, but I'm not saying please don't break my code. My code will be fine, I'm around to fix it. I'm more worried about other people's code (that I might rely on), maintainers that have left, or aren't that responsive, newcomers reading old tutorials, people getting angry about needing more CPP/fixing more code on new GHC releases, etc. We're still breaking code on every new GHC release, and it seems the amount of breakage is only increasing. Erik