transformers 0.4: change in accessor function exports?

One of the changes[1] in transformers 0.4 is as follows: 0.3: newtype Identity a = Identity { runIdentity :: a } 0.4: newtype Identity a = Identity a runIdentity (Identity x) = x While this may seem benign, I've already seen three cases where this caused breakage[2][3][4]. Is there a reason for this change in 0.4? If not, I'd like to request moving back to the previous formulation to avoid unnecessary breakage. Michael [1] http://hdiff.luite.com/cgit/transformers/commit/Data/Functor/Identity.hs?id=cabf26451206cf1e223970b2df846132300c04d9&ss=1 [2] https://github.com/fpco/streaming-commons/pull/5 [3] https://github.com/ekmett/exceptions/pull/29 [4] https://github.com/ekmett/mtl/commit/d1a6253886a99215d5ff6afe3632b27e696d40b...

On Tue, May 06, 2014 at 07:16:40PM +0300, Michael Snoyman wrote:
One of the changes[1] in transformers 0.4 is as follows:
0.3:
newtype Identity a = Identity { runIdentity :: a }
0.4:
newtype Identity a = Identity a runIdentity (Identity x) = x
While this may seem benign, I've already seen three cases where this caused breakage[2][3][4].
Is there a reason for this change in 0.4? If not, I'd like to request moving back to the previous formulation to avoid unnecessary breakage.
Read and Show instances were introduced in 0.4. With the record form, the default instances for those classes would be very cumbersome. The alternative of defining custom instances that differ from the default ones would make the interface more confusing.

It may make the code in transformers a bit more confusing for a handful of
instances, but this is breaking almost every user I've talked to.
This is proving to be a major breaking change as users commonly import
StateT(..) and go off and use runStateT, etc.
I wrote the imports in mtl 2.2 in such a way that if you recanted and chose
to switch back to the old style, it'd still work.
I just know that I personally have 200+ modules to change as a result, for
no better experience as a user.
-Edward
On Wed, May 7, 2014 at 3:18 AM, Ross Paterson
On Tue, May 06, 2014 at 07:16:40PM +0300, Michael Snoyman wrote:
One of the changes[1] in transformers 0.4 is as follows:
0.3:
newtype Identity a = Identity { runIdentity :: a }
0.4:
newtype Identity a = Identity a runIdentity (Identity x) = x
While this may seem benign, I've already seen three cases where this caused breakage[2][3][4].
Is there a reason for this change in 0.4? If not, I'd like to request moving back to the previous formulation to avoid unnecessary breakage.
Read and Show instances were introduced in 0.4. With the record form, the default instances for those classes would be very cumbersome. The alternative of defining custom instances that differ from the default ones would make the interface more confusing. _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Wouldn't it be simpler/less breaking to keep "newtype Identity a = Identity { runIdentity :: a }" and simply hand write Show/Read instances that function asif it was "newtype Identity a = Identity a", giving us best of both worlds? Cheers, Merijn On May 6, 2014, at 23:30 , Edward Kmett wrote:
It may make the code in transformers a bit more confusing for a handful of instances, but this is breaking almost every user I've talked to.
This is proving to be a major breaking change as users commonly import StateT(..) and go off and use runStateT, etc.
I wrote the imports in mtl 2.2 in such a way that if you recanted and chose to switch back to the old style, it'd still work.
I just know that I personally have 200+ modules to change as a result, for no better experience as a user.
-Edward
On Wed, May 7, 2014 at 3:18 AM, Ross Paterson
wrote: On Tue, May 06, 2014 at 07:16:40PM +0300, Michael Snoyman wrote: One of the changes[1] in transformers 0.4 is as follows:
0.3:
newtype Identity a = Identity { runIdentity :: a }
0.4:
newtype Identity a = Identity a runIdentity (Identity x) = x
While this may seem benign, I've already seen three cases where this caused breakage[2][3][4].
Is there a reason for this change in 0.4? If not, I'd like to request moving back to the previous formulation to avoid unnecessary breakage.
Read and Show instances were introduced in 0.4. With the record form, the default instances for those classes would be very cumbersome. The alternative of defining custom instances that differ from the default ones would make the interface more confusing. _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

agree with merjin and edward...
On Tue, May 6, 2014 at 5:54 PM, Merijn Verstraaten
Wouldn't it be simpler/less breaking to keep "newtype Identity a = Identity { runIdentity :: a }" and simply hand write Show/Read instances that function asif it was "newtype Identity a = Identity a", giving us best of both worlds?
Cheers, Merijn
On May 6, 2014, at 23:30 , Edward Kmett wrote:
It may make the code in transformers a bit more confusing for a handful of instances, but this is breaking almost every user I've talked to.
This is proving to be a major breaking change as users commonly import StateT(..) and go off and use runStateT, etc.
I wrote the imports in mtl 2.2 in such a way that if you recanted and chose to switch back to the old style, it'd still work.
I just know that I personally have 200+ modules to change as a result, for no better experience as a user.
-Edward
On Wed, May 7, 2014 at 3:18 AM, Ross Paterson
wrote: On Tue, May 06, 2014 at 07:16:40PM +0300, Michael Snoyman wrote:
One of the changes[1] in transformers 0.4 is as follows:
0.3:
newtype Identity a = Identity { runIdentity :: a }
0.4:
newtype Identity a = Identity a runIdentity (Identity x) = x
While this may seem benign, I've already seen three cases where this caused breakage[2][3][4].
Is there a reason for this change in 0.4? If not, I'd like to request moving back to the previous formulation to avoid unnecessary breakage.
Read and Show instances were introduced in 0.4. With the record form, the default instances for those classes would be very cumbersome. The alternative of defining custom instances that differ from the default ones would make the interface more confusing. _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

That is the suggestion we are putting forth. =)
-Edward
On Wed, May 7, 2014 at 7:54 AM, Merijn Verstraaten
Wouldn't it be simpler/less breaking to keep "newtype Identity a = Identity { runIdentity :: a }" and simply hand write Show/Read instances that function asif it was "newtype Identity a = Identity a", giving us best of both worlds?
Cheers, Merijn
On May 6, 2014, at 23:30 , Edward Kmett wrote:
It may make the code in transformers a bit more confusing for a handful of instances, but this is breaking almost every user I've talked to.
This is proving to be a major breaking change as users commonly import StateT(..) and go off and use runStateT, etc.
I wrote the imports in mtl 2.2 in such a way that if you recanted and chose to switch back to the old style, it'd still work.
I just know that I personally have 200+ modules to change as a result, for no better experience as a user.
-Edward
On Wed, May 7, 2014 at 3:18 AM, Ross Paterson
wrote: On Tue, May 06, 2014 at 07:16:40PM +0300, Michael Snoyman wrote:
One of the changes[1] in transformers 0.4 is as follows:
0.3:
newtype Identity a = Identity { runIdentity :: a }
0.4:
newtype Identity a = Identity a runIdentity (Identity x) = x
While this may seem benign, I've already seen three cases where this caused breakage[2][3][4].
Is there a reason for this change in 0.4? If not, I'd like to request moving back to the previous formulation to avoid unnecessary breakage.
Read and Show instances were introduced in 0.4. With the record form, the default instances for those classes would be very cumbersome. The alternative of defining custom instances that differ from the default ones would make the interface more confusing. _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

should the 0.4 release be temporarily marked deprecated so that breakages
stop for a wee bit?
On Tue, May 6, 2014 at 6:30 PM, Edward Kmett
That is the suggestion we are putting forth. =)
-Edward
On Wed, May 7, 2014 at 7:54 AM, Merijn Verstraaten
wrote:
Wouldn't it be simpler/less breaking to keep "newtype Identity a = Identity { runIdentity :: a }" and simply hand write Show/Read instances that function asif it was "newtype Identity a = Identity a", giving us best of both worlds?
Cheers, Merijn
On May 6, 2014, at 23:30 , Edward Kmett wrote:
It may make the code in transformers a bit more confusing for a handful of instances, but this is breaking almost every user I've talked to.
This is proving to be a major breaking change as users commonly import StateT(..) and go off and use runStateT, etc.
I wrote the imports in mtl 2.2 in such a way that if you recanted and chose to switch back to the old style, it'd still work.
I just know that I personally have 200+ modules to change as a result, for no better experience as a user.
-Edward
On Wed, May 7, 2014 at 3:18 AM, Ross Paterson
wrote: On Tue, May 06, 2014 at 07:16:40PM +0300, Michael Snoyman wrote:
One of the changes[1] in transformers 0.4 is as follows:
0.3:
newtype Identity a = Identity { runIdentity :: a }
0.4:
newtype Identity a = Identity a runIdentity (Identity x) = x
While this may seem benign, I've already seen three cases where this caused breakage[2][3][4].
Is there a reason for this change in 0.4? If not, I'd like to request moving back to the previous formulation to avoid unnecessary breakage.
Read and Show instances were introduced in 0.4. With the record form, the default instances for those classes would be very cumbersome. The alternative of defining custom instances that differ from the default ones would make the interface more confusing. _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Carter,
You don't deprecate versions in hackage, you deprecate whole packages.
Slow down and let's let the man reply. ;)
-Edward
On Wed, May 7, 2014 at 8:32 AM, Carter Schonwald wrote: should the 0.4 release be temporarily marked deprecated so that breakages
stop for a wee bit? On Tue, May 6, 2014 at 6:30 PM, Edward Kmett That is the suggestion we are putting forth. =) -Edward On Wed, May 7, 2014 at 7:54 AM, Merijn Verstraaten <
merijn@inconsistent.nl> wrote: Wouldn't it be simpler/less breaking to keep "newtype Identity a =
Identity { runIdentity :: a }" and simply hand write Show/Read instances
that function asif it was "newtype Identity a = Identity a", giving us best
of both worlds? Cheers,
Merijn On May 6, 2014, at 23:30 , Edward Kmett wrote: It may make the code in transformers a bit more confusing for a handful
of instances, but this is breaking almost every user I've talked to. This is proving to be a major breaking change as users commonly import
StateT(..) and go off and use runStateT, etc. I wrote the imports in mtl 2.2 in such a way that if you recanted and
chose to switch back to the old style, it'd still work. I just know that I personally have 200+ modules to change as a result,
for no better experience as a user. -Edward On Wed, May 7, 2014 at 3:18 AM, Ross Paterson On Tue, May 06, 2014 at 07:16:40PM +0300, Michael Snoyman wrote: One of the changes[1] in transformers 0.4 is as follows: 0.3: newtype Identity a = Identity { runIdentity :: a } 0.4: newtype Identity a = Identity a
runIdentity (Identity x) = x While this may seem benign, I've already seen three cases where this
caused
breakage[2][3][4]. Is there a reason for this change in 0.4? If not, I'd like to request
moving
back to the previous formulation to avoid unnecessary breakage. Read and Show instances were introduced in 0.4. With the record form,
the default instances for those classes would be very cumbersome.
The alternative of defining custom instances that differ from the
default
ones would make the interface more confusing.
_______________________________________________
Libraries mailing list
Libraries@haskell.org
http://www.haskell.org/mailman/listinfo/libraries _______________________________________________
Libraries mailing list
Libraries@haskell.org
http://www.haskell.org/mailman/listinfo/libraries _______________________________________________
Libraries mailing list
Libraries@haskell.org
http://www.haskell.org/mailman/listinfo/libraries _______________________________________________
Libraries mailing list
Libraries@haskell.org
http://www.haskell.org/mailman/listinfo/libraries

On Wed, May 07, 2014 at 08:34:38AM +1000, Edward Kmett wrote:
You don't deprecate versions in hackage, you deprecate whole packages.
Not sure if I missed the point, but you can deprecate versions: http://hackage.haskell.org/packages/preferred

On Wed, May 7, 2014 at 12:31 PM, Tom Ellis < tom-lists-haskell-cafe-2013@jaguarpaw.co.uk> wrote:
On Wed, May 07, 2014 at 08:34:38AM +1000, Edward Kmett wrote:
You don't deprecate versions in hackage, you deprecate whole packages.
Not sure if I missed the point, but you can deprecate versions:
You can, and it's a good practice, but unfortunately it won't really change cabal's build plan generation: https://github.com/haskell/cabal/issues/1792 Michael

Actually you do. On the new hackage, you can deprecate single
versions, though these are not hard constraints to cabal IIRC, so
their use is limited. For transformers, this could be done at [0].
This would probably be a good idea, if only to show people which
version they should support. I'm guessing it's 0.3.* or 0.4.1, since
that last one was done without a major version bump, implying that the
changes in 0.4.0 'never happened'?
Erik
[0] http://hackage.haskell.org/package/transformers/preferred/edit
On Wed, May 7, 2014 at 12:34 AM, Edward Kmett
Carter,
You don't deprecate versions in hackage, you deprecate whole packages.
Slow down and let's let the man reply. ;)
-Edward
On Wed, May 7, 2014 at 8:32 AM, Carter Schonwald
wrote: should the 0.4 release be temporarily marked deprecated so that breakages stop for a wee bit?
On Tue, May 6, 2014 at 6:30 PM, Edward Kmett
wrote: That is the suggestion we are putting forth. =)
-Edward
On Wed, May 7, 2014 at 7:54 AM, Merijn Verstraaten
wrote: Wouldn't it be simpler/less breaking to keep "newtype Identity a = Identity { runIdentity :: a }" and simply hand write Show/Read instances that function asif it was "newtype Identity a = Identity a", giving us best of both worlds?
Cheers, Merijn
On May 6, 2014, at 23:30 , Edward Kmett wrote:
It may make the code in transformers a bit more confusing for a handful of instances, but this is breaking almost every user I've talked to.
This is proving to be a major breaking change as users commonly import StateT(..) and go off and use runStateT, etc.
I wrote the imports in mtl 2.2 in such a way that if you recanted and chose to switch back to the old style, it'd still work.
I just know that I personally have 200+ modules to change as a result, for no better experience as a user.
-Edward
On Wed, May 7, 2014 at 3:18 AM, Ross Paterson
wrote: On Tue, May 06, 2014 at 07:16:40PM +0300, Michael Snoyman wrote:
One of the changes[1] in transformers 0.4 is as follows:
0.3:
newtype Identity a = Identity { runIdentity :: a }
0.4:
newtype Identity a = Identity a runIdentity (Identity x) = x
While this may seem benign, I've already seen three cases where this caused breakage[2][3][4].
Is there a reason for this change in 0.4? If not, I'd like to request moving back to the previous formulation to avoid unnecessary breakage.
Read and Show instances were introduced in 0.4. With the record form, the default instances for those classes would be very cumbersome. The alternative of defining custom instances that differ from the default ones would make the interface more confusing. _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On 2014-05-07 at 00:32:33 +0200, Carter Schonwald wrote:
should the 0.4 release be temporarily marked deprecated so that breakages stop for a wee bit?
I know, some of you may not want to hear this, but this will only bite packages not following the PVP (i.e. those that didn't have upper bounds)... transformers-0.4 was a major version bump after all, so it *is* allowed to break the API (whether that was a good design decision is a different discussion though)

On Wed, May 7, 2014 at 12:40 PM, Herbert Valerio Riedel
On 2014-05-07 at 00:32:33 +0200, Carter Schonwald wrote:
should the 0.4 release be temporarily marked deprecated so that breakages stop for a wee bit?
I know, some of you may not want to hear this, but this will only bite packages not following the PVP (i.e. those that didn't have upper bounds)... transformers-0.4 was a major version bump after all, so it *is* allowed to break the API (whether that was a good design decision is a different discussion though)
Actually, in this case, I've seen some packages that *were* following the PVP get broken by this change, since authors didn't realize this would be a breaking change before releasing a new version of their package with a relaxed upper bound. You can argue about good practices in release procedures, but I just want to make it clear that, in this case, an immediate release of transformers 0.4.1 was incredibly helpful with stropping wider-spread breakage. I'd still like to come back to the question Felipe asked: why is the change from field labels to explicit functions considered an improvement? Michael

On Wed, May 7, 2014 at 5:47 AM, Michael Snoyman
On Wed, May 7, 2014 at 12:40 PM, Herbert Valerio Riedel
wrote: I know, some of you may not want to hear this, but this will only bite packages not following the PVP (i.e. those that didn't have upper bounds)... transformers-0.4 was a major version bump after all, so it *is* allowed to break the API (whether that was a good design decision is a different discussion though)
Actually, in this case, I've seen some packages that *were* following the PVP get broken by this change, since authors didn't realize this would be a breaking change before releasing a new version of their package with a relaxed upper bound.
The PVP clearly communicates that if a dependency has a major version bump, then you MUST test your package with the new version to guarantee that your release will build. Those people simply shouldn't have released without testing. Also, people not following the PVP are very simply ALWAYS more prone to the kind of breakage we see here.
I'd still like to come back to the question Felipe asked: why is the change from field labels to explicit functions considered an improvement?
+1 here. I'm definitely curious about the reasoning.

Am 07.05.2014 11:40, schrieb Herbert Valerio Riedel:
On 2014-05-07 at 00:32:33 +0200, Carter Schonwald wrote:
should the 0.4 release be temporarily marked deprecated so that breakages stop for a wee bit?
I know, some of you may not want to hear this, but this will only bite packages not following the PVP (i.e. those that didn't have upper bounds)... transformers-0.4 was a major version bump after all, so it *is* allowed to break the API (whether that was a good design decision is a different discussion though)
However, turning the runIdentity function back into a record field name in 0.4.1.0, was another breaking change that only got a minor version bump. :-(

On 2014-05-07 at 11:47:25 +0200, Henning Thielemann wrote:
Am 07.05.2014 11:40, schrieb Herbert Valerio Riedel:
On 2014-05-07 at 00:32:33 +0200, Carter Schonwald wrote:
should the 0.4 release be temporarily marked deprecated so that breakages stop for a wee bit?
I know, some of you may not want to hear this, but this will only bite packages not following the PVP (i.e. those that didn't have upper bounds)... transformers-0.4 was a major version bump after all, so it *is* allowed to break the API (whether that was a good design decision is a different discussion though)
However, turning the runIdentity function back into a record field name in 0.4.1.0, was another breaking change that only got a minor version bump. :-(
Btw, as I can't think of an example right now, what would be an example for code that works with transformers-0.4.0.0 but wouldn't compile anymore with transformers-0.4.1.0? Cheers, hvr

On Wed, May 07, 2014 at 12:15:58PM +0200, Herbert Valerio Riedel wrote:
On 2014-05-07 at 11:47:25 +0200, Henning Thielemann wrote:
Am 07.05.2014 11:40, schrieb Herbert Valerio Riedel:
On 2014-05-07 at 00:32:33 +0200, Carter Schonwald wrote:
should the 0.4 release be temporarily marked deprecated so that breakages stop for a wee bit?
I know, some of you may not want to hear this, but this will only bite packages not following the PVP (i.e. those that didn't have upper bounds)... transformers-0.4 was a major version bump after all, so it *is* allowed to break the API (whether that was a good design decision is a different discussion though)
However, turning the runIdentity function back into a record field name in 0.4.1.0, was another breaking change that only got a minor version bump. :-(
Btw, as I can't think of an example right now, what would be an example for code that works with transformers-0.4.0.0 but wouldn't compile anymore with transformers-0.4.1.0?
Surely just the reverse of the breaking change? https://github.com/ibotty/streaming-commons/commit/b1137852e4f58520ad65d01b2...

On Wed, May 7, 2014 at 1:34 PM, Tom Ellis < tom-lists-haskell-cafe-2013@jaguarpaw.co.uk> wrote:
On Wed, May 07, 2014 at 12:15:58PM +0200, Herbert Valerio Riedel wrote:
On 2014-05-07 at 11:47:25 +0200, Henning Thielemann wrote:
Am 07.05.2014 11:40, schrieb Herbert Valerio Riedel:
On 2014-05-07 at 00:32:33 +0200, Carter Schonwald wrote:
should the 0.4 release be temporarily marked deprecated so that breakages stop for a wee bit?
I know, some of you may not want to hear this, but this will only bite packages not following the PVP (i.e. those that didn't have upper bounds)... transformers-0.4 was a major version bump after all, so it *is* allowed to break the API (whether that was a good design decision is a different discussion though)
However, turning the runIdentity function back into a record field name in 0.4.1.0, was another breaking change that only got a minor version bump. :-(
Btw, as I can't think of an example right now, what would be an example for code that works with transformers-0.4.0.0 but wouldn't compile anymore with transformers-0.4.1.0?
Surely just the reverse of the breaking change?
https://github.com/ibotty/streaming-commons/commit/b1137852e4f58520ad65d01b2...
No, that code is compatible with transformers 0.3, 0.4, and 0.4.1. With the syntax: import Data.Functor.Constant (Constant (Constant), getConstant) We're importing the data type Constrant, the data construct Constant for that data type, and the function getConstant. It doesn't matter if getConstant is a normal function or a field accessor, it can still be accessed by that syntax. Michael

On Wed, May 07, 2014 at 02:10:42PM +0300, Michael Snoyman wrote:
Btw, as I can't think of an example right now, what would be an example for code that works with transformers-0.4.0.0 but wouldn't compile anymore with transformers-0.4.1.0?
Surely just the reverse of the breaking change?
https://github.com/ibotty/streaming-commons/commit/b1137852e4f58520ad65d01b2...
No, that code is compatible with transformers 0.3, 0.4, and 0.4.1. With the syntax:
import Data.Functor.Constant (Constant (Constant), getConstant)
We're importing the data type Constrant, the data construct Constant for that data type, and the function getConstant. It doesn't matter if getConstant is a normal function or a field accessor, it can still be accessed by that syntax.
Then I don't understand why field accessors are even *allowed* to be imported beneath the type. Surely that's only necessary to disambiguate constructors from types? Tom

On Wed, May 7, 2014 at 2:41 PM, Tom Ellis < tom-lists-haskell-cafe-2013@jaguarpaw.co.uk> wrote:
Btw, as I can't think of an example right now, what would be an example for code that works with transformers-0.4.0.0 but wouldn't compile anymore with transformers-0.4.1.0?
Surely just the reverse of the breaking change?
https://github.com/ibotty/streaming-commons/commit/b1137852e4f58520ad65d01b2...
No, that code is compatible with transformers 0.3, 0.4, and 0.4.1. With
On Wed, May 07, 2014 at 02:10:42PM +0300, Michael Snoyman wrote: the
syntax:
import Data.Functor.Constant (Constant (Constant), getConstant)
We're importing the data type Constrant, the data construct Constant for that data type, and the function getConstant. It doesn't matter if getConstant is a normal function or a field accessor, it can still be accessed by that syntax.
Then I don't understand why field accessors are even *allowed* to be imported beneath the type. Surely that's only necessary to disambiguate constructors from types?
In the case here, the syntax: import Control.Monad.Trans.Reader (ReaderT (..)) is very convenient. But it's true that you don't really gain much from the distinction between these two: import Control.Monad.Trans.Reader (ReaderT (ReaderT, runReaderT)) import Control.Monad.Trans.Reader (ReaderT (ReaderT), runReaderT) Perhaps the latter should be considered a better approach, since it's more resilient to changes in datatypes. Michael

On Wed, 2014-05-07 at 14:43 +0300, Michael Snoyman wrote:
Perhaps the latter should be considered a better approach, since it's more resilient to changes in datatypes.
And (IMHO) it's more in line with expectations. Using `Name(..)` makes sense when the `..` are constructors or 'true' record field names, whilst `runReader` sounds more like an ordinary function (no matter what its actual implementation is). Nicolas

Am 07.05.2014 13:43, schrieb Michael Snoyman:
In the case here, the syntax:
import Control.Monad.Trans.Reader (ReaderT (..))
is very convenient. But it's true that you don't really gain much from the distinction between these two:
import Control.Monad.Trans.Reader (ReaderT (ReaderT, runReaderT)) import Control.Monad.Trans.Reader (ReaderT (ReaderT), runReaderT)
Perhaps the latter should be considered a better approach, since it's more resilient to changes in datatypes.
However, even if imported in the second way, runReaderT identifier can be used in record field update syntax. I guess it would be more consistent to allow only the use as a function when imported like an ordinary function.

On Wed, May 7, 2014 at 4:31 PM, Henning Thielemann < schlepptop@henning-thielemann.de> wrote:
Am 07.05.2014 13:43, schrieb Michael Snoyman:
In the case here, the syntax:
import Control.Monad.Trans.Reader (ReaderT (..))
is very convenient. But it's true that you don't really gain much from the distinction between these two:
import Control.Monad.Trans.Reader (ReaderT (ReaderT, runReaderT)) import Control.Monad.Trans.Reader (ReaderT (ReaderT), runReaderT)
Perhaps the latter should be considered a better approach, since it's more resilient to changes in datatypes.
However, even if imported in the second way, runReaderT identifier can be used in record field update syntax. I guess it would be more consistent to allow only the use as a function when imported like an ordinary function.
If you think *that's* bad, you'll love this: module Person ( Person , name , age , defaultPerson ) where data Person = Person { name :: String, age :: Int} deriving Show defaultPerson = Person "Alice" 25 ---- module Main where import Person main = print defaultPerson { name = "Bob", age = 30 } ---- (Yes, I've been known to abuse this in my libraries, and in 20/20 hindsight, I wish I hadn't.) Michael

* Herbert Valerio Riedel
Btw, as I can't think of an example right now, what would be an example for code that works with transformers-0.4.0.0 but wouldn't compile anymore with transformers-0.4.1.0?
{-# LANGUAGE RecordWildCards #-} import qualified Control.Monad.Trans.Identity as I I.Identity {..} = I.Identity () runIdentity = () (untested, but I think it does the trick) Roman

Am 07.05.2014 12:15, schrieb Herbert Valerio Riedel:
On 2014-05-07 at 11:47:25 +0200, Henning Thielemann wrote:
However, turning the runIdentity function back into a record field name in 0.4.1.0, was another breaking change that only got a minor version bump. :-(
Btw, as I can't think of an example right now, what would be an example for code that works with transformers-0.4.0.0 but wouldn't compile anymore with transformers-0.4.1.0?
E.g. import Data.Functor.Identity (Identity(..)) runIdentity :: Identity a -> a runIdentity (Identity a) = a This would work with transformers-0.4.0.0 but gives a name clash with transformers-0.4.1.0.

On Wed, May 07, 2014 at 07:30:03AM +1000, Edward Kmett wrote:
It may make the code in transformers a bit more confusing for a handful of instances, but this is breaking almost every user I've talked to.
My concern is not the implementation, it's the interface.
This is proving to be a major breaking change as users commonly import StateT (..) and go off and use runStateT, etc.
I wrote the imports in mtl 2.2 in such a way that if you recanted and chose to switch back to the old style, it'd still work.
I just know that I personally have 200+ modules to change as a result, for no better experience as a user.
I'm convinced that this change is the right thing to do, but I haven't managed it at all well. So I'll do a minor release re-instating the fields in short order, but still intend to remove them in the next major release (with more preparation).

Em 06-05-2014 19:57, Ross Paterson escreveu:
On Wed, May 07, 2014 at 07:30:03AM +1000, Edward Kmett wrote:
It may make the code in transformers a bit more confusing for a handful of instances, but this is breaking almost every user I've talked to.
My concern is not the implementation, it's the interface.
This is proving to be a major breaking change as users commonly import StateT (..) and go off and use runStateT, etc.
I wrote the imports in mtl 2.2 in such a way that if you recanted and chose to switch back to the old style, it'd still work.
I just know that I personally have 200+ modules to change as a result, for no better experience as a user.
I'm convinced that this change is the right thing to do, but I haven't managed it at all well. So I'll do a minor release re-instating the fields in short order, but still intend to remove them in the next major release (with more preparation).
I'm sorry, but why are you convinced of this? Cheers, -- Felipe.

I don't really care one way or the other how this is resolved, but does it
strike anyone else that current practices must be remarkably fragile for
such a minor change (which doesn't even change exported names!) to
supposedly cause so much breakage?
John L.
On Tue, May 6, 2014 at 2:30 PM, Edward Kmett
It may make the code in transformers a bit more confusing for a handful of instances, but this is breaking almost every user I've talked to.
This is proving to be a major breaking change as users commonly import StateT(..) and go off and use runStateT, etc.
I wrote the imports in mtl 2.2 in such a way that if you recanted and chose to switch back to the old style, it'd still work.
I just know that I personally have 200+ modules to change as a result, for no better experience as a user.
-Edward
On Wed, May 7, 2014 at 3:18 AM, Ross Paterson
wrote: On Tue, May 06, 2014 at 07:16:40PM +0300, Michael Snoyman wrote:
One of the changes[1] in transformers 0.4 is as follows:
0.3:
newtype Identity a = Identity { runIdentity :: a }
0.4:
newtype Identity a = Identity a runIdentity (Identity x) = x
While this may seem benign, I've already seen three cases where this caused breakage[2][3][4].
Is there a reason for this change in 0.4? If not, I'd like to request moving back to the previous formulation to avoid unnecessary breakage.
Read and Show instances were introduced in 0.4. With the record form, the default instances for those classes would be very cumbersome. The alternative of defining custom instances that differ from the default ones would make the interface more confusing. _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Am 07.05.2014 01:03, schrieb John Lato:
I don't really care one way or the other how this is resolved, but does it strike anyone else that current practices must be remarkably fragile for such a minor change (which doesn't even change exported names!) to supposedly cause so much breakage?
With qualified imports there would be no breakage ... However, names in mtl and thus transformers were not designed for qualified import. :-(

Hi, Am Mittwoch, den 07.05.2014, 08:33 +0200 schrieb Henning Thielemann:
Am 07.05.2014 01:03, schrieb John Lato:
I don't really care one way or the other how this is resolved, but does it strike anyone else that current practices must be remarkably fragile for such a minor change (which doesn't even change exported names!) to supposedly cause so much breakage?
With qualified imports there would be no breakage ...
However, names in mtl and thus transformers were not designed for qualified import. :-(
would it? /tmp $ echo 'module Foo where newtype Foo = Foo {unFoo :: ()}' > Foo.hs /tmp $ echo 'module Bar where import qualified Foo (Foo(..)) ; bar = Foo.unFoo' > Bar.hs /tmp $ ghc -c Foo.hs; ghc -c Bar.hs /tmp $ echo 'module Foo where newtype Foo = Foo (); unFoo (Foo x) = x ' > Foo.hs /tmp $ ghc -c Foo.hs; ghc -c Bar.hs Bar.hs:1:57: Not in scope: `Foo.unFoo' Greetings, Joachim -- Joachim “nomeata” Breitner mail@joachim-breitner.de • http://www.joachim-breitner.de/ Jabber: nomeata@joachim-breitner.de • GPG-Key: 0xF0FBF51F Debian Developer: nomeata@debian.org

Am 07.05.2014 10:49, schrieb Joachim Breitner:
Hi,
Am Mittwoch, den 07.05.2014, 08:33 +0200 schrieb Henning Thielemann:
Am 07.05.2014 01:03, schrieb John Lato:
I don't really care one way or the other how this is resolved, but does it strike anyone else that current practices must be remarkably fragile for such a minor change (which doesn't even change exported names!) to supposedly cause so much breakage?
With qualified imports there would be no breakage ...
However, names in mtl and thus transformers were not designed for qualified import. :-(
would it?
/tmp $ echo 'module Foo where newtype Foo = Foo {unFoo :: ()}' > Foo.hs /tmp $ echo 'module Bar where import qualified Foo (Foo(..)) ; bar = Foo.unFoo' > Bar.hs
With qualified import I mean import qualified Foo as Foo Importing qualified with explicit import list is somehow done twice, because Foo.unFoo cannot clash with other identifiers, unless you use the abbreviation Foo twice.
/tmp $ ghc -c Foo.hs; ghc -c Bar.hs /tmp $ echo 'module Foo where newtype Foo = Foo (); unFoo (Foo x) = x ' > Foo.hs /tmp $ ghc -c Foo.hs; ghc -c Bar.hs
Bar.hs:1:57: Not in scope: `Foo.unFoo'

Hi, Am Mittwoch, den 07.05.2014, 11:11 +0200 schrieb Henning Thielemann:
With qualified import I mean
import qualified Foo as Foo
Importing qualified with explicit import list is somehow done twice, because Foo.unFoo cannot clash with other identifiers, unless you use the abbreviation Foo twice.
quite right; sorry. Greetings, Joachim -- Joachim “nomeata” Breitner mail@joachim-breitner.de • http://www.joachim-breitner.de/ Jabber: nomeata@joachim-breitner.de • GPG-Key: 0xF0FBF51F Debian Developer: nomeata@debian.org
participants (15)
-
Carter Schonwald
-
Edward Kmett
-
Erik Hesselink
-
Felipe Lessa
-
Henning Thielemann
-
Herbert Valerio Riedel
-
Joachim Breitner
-
John Lato
-
Merijn Verstraaten
-
Michael Snoyman
-
MightyByte
-
Nicolas Trangez
-
Roman Cheplyaka
-
Ross Paterson
-
Tom Ellis