In Data.Dynamic, Dynamic is defined as data Dynamic = Dynamic TypeRep Any Does this have any advantage over a safer data Dynamic = forall a. Typeable a => Dynamic a ? Roman
Ok, one reason is that the TypeRep won't be cached in the Dynamic value. Even in GHC 7.8 Typeable is defined as class Typeable a where typeRep# :: Proxy# a -> TypeRep instead of class Typeable a where typeRep :: Tagged a TypeRep Why? Is this an oversight? * Roman Cheplyaka <roma@ro-che.info> [2014-03-10 12:11:27+0200]
In Data.Dynamic, Dynamic is defined as
data Dynamic = Dynamic TypeRep Any
Does this have any advantage over a safer
data Dynamic = forall a. Typeable a => Dynamic a
?
Roman
Dear Core Libraries committee I think Roman is right here. Moreover we have known this for at least I think seven years http://comments.gmane.org/gmane.comp.lang.haskell.cafe/20097, where I wrote: | Yes, Dynamic preceded the Typeable class, I think. | Were we to do it today, I think we'd have | | data Dynamic = forall a . (Typeable a) => Dynamic a | | Whether it's worth changing, I'm not sure. It's a library so, | if a change desirable, anyone could take a lead. The new representation for Dynamic would be good because it's less insecure than all this "Obj" nonsense, instead relying on Typeable, which is pretty good these days. Pedro is the most recent visitor to this territory and may have views. Roman's point about the method for the Typeable class is a good one too, and not one I've seen discussed. Over to you Simon | -----Original Message----- | From: Libraries [mailto:libraries-bounces@haskell.org] On Behalf Of | Roman Cheplyaka | Sent: 10 March 2014 10:35 | To: libraries@haskell.org | Subject: Re: Data.Dynamic: Any vs existential | | Ok, one reason is that the TypeRep won't be cached in the Dynamic value. | Even in GHC 7.8 Typeable is defined as | | class Typeable a where | typeRep# :: Proxy# a -> TypeRep | | instead of | | class Typeable a where | typeRep :: Tagged a TypeRep | | Why? Is this an oversight? | | * Roman Cheplyaka <roma@ro-che.info> [2014-03-10 12:11:27+0200] | > In Data.Dynamic, Dynamic is defined as | > | > data Dynamic = Dynamic TypeRep Any | > | > Does this have any advantage over a safer | > | > data Dynamic = forall a. Typeable a => Dynamic a | > | > ? | > | > Roman
What about the memory footprint? I recall making measurements using "ghc-datasize" package and the existential appeared to occupy much more space. 2014-03-10 15:26 GMT+04:00 Simon Peyton Jones <simonpj@microsoft.com>:
Dear Core Libraries committee
I think Roman is right here. Moreover we have known this for at least I think seven years http://comments.gmane.org/gmane.comp.lang.haskell.cafe/20097, where I wrote:
| Yes, Dynamic preceded the Typeable class, I think. | Were we to do it today, I think we'd have | | data Dynamic = forall a . (Typeable a) => Dynamic a | | Whether it's worth changing, I'm not sure. It's a library so, | if a change desirable, anyone could take a lead.
The new representation for Dynamic would be good because it's less insecure than all this "Obj" nonsense, instead relying on Typeable, which is pretty good these days.
Pedro is the most recent visitor to this territory and may have views.
Roman's point about the method for the Typeable class is a good one too, and not one I've seen discussed.
Over to you
Simon
| -----Original Message----- | From: Libraries [mailto:libraries-bounces@haskell.org] On Behalf Of | Roman Cheplyaka | Sent: 10 March 2014 10:35 | To: libraries@haskell.org | Subject: Re: Data.Dynamic: Any vs existential | | Ok, one reason is that the TypeRep won't be cached in the Dynamic value. | Even in GHC 7.8 Typeable is defined as | | class Typeable a where | typeRep# :: Proxy# a -> TypeRep | | instead of | | class Typeable a where | typeRep :: Tagged a TypeRep | | Why? Is this an oversight? | | * Roman Cheplyaka <roma@ro-che.info> [2014-03-10 12:11:27+0200] | > In Data.Dynamic, Dynamic is defined as | > | > data Dynamic = Dynamic TypeRep Any | > | > Does this have any advantage over a safer | > | > data Dynamic = forall a. Typeable a => Dynamic a | > | > ? | > | > Roman _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
On Mon, Mar 10, 2014 at 7:26 AM, Simon Peyton Jones <simonpj@microsoft.com>wrote:
Dear Core Libraries committee
I think Roman is right here. Moreover we have known this for at least I think seven years http://comments.gmane.org/gmane.comp.lang.haskell.cafe/20097, where I wrote:
| Yes, Dynamic preceded the Typeable class, I think. | Were we to do it today, I think we'd have | | data Dynamic = forall a . (Typeable a) => Dynamic a | | Whether it's worth changing, I'm not sure. It's a library so, | if a change desirable, anyone could take a lead.
The new representation for Dynamic would be good because it's less insecure than all this "Obj" nonsense, instead relying on Typeable, which is pretty good these days.
Pedro is the most recent visitor to this territory and may have views.
Roman's point about the method for the Typeable class is a good one too, and not one I've seen discussed.
Over to you
I, at least, am in favor of this. I've thought for a while that the ideal form of all this is something like: data TypeRep a -- indexed by a class Typeable a where typeRep :: TypeRep a data Dynamic = forall a. Dynamic (TypeRep a) a Where, ideally, TypeRep is an indexed type, and you can match on it to refine its argument. Then Typeable just becomes the implicit version of this evidence, for convenience. TypeRep versions of cast would also have to be primitive probably (since one can not, a priori, enumerate the diagonal of all possible monotypes, now and in the future). Anyhow, I don't know if this entire interface is or will be implementable in GHC (the idea comes from a document about JHC way back, although I don't know if even it implements this), but using Typeable in an existential captures the Dynamic part of it, at least. Also, I hadn't seen the Tagged version of Typeable before (and hadn't thought of it myself). I expect it's an oversight that this wasn't the form chosen, as it seems superior to me. In fact, it seems like every situation where the 0-width Proxy# could be used, Tagged could also be used instead, and is automatically 0-width, and has better sharing behavior? Unless you explicitly don't want sharing, that is. It seems like any relative inconvenience could probably be alleviated by the proxy function in tagged, while keeping the nicer behavior. -- Dan
+++++1000 to dan doels strawman suggestion. I'm a huge fan of indexed types style apis like that one. On Mon, Mar 10, 2014 at 11:54 AM, Dan Doel <dan.doel@gmail.com> wrote:
On Mon, Mar 10, 2014 at 7:26 AM, Simon Peyton Jones <simonpj@microsoft.com
wrote:
Dear Core Libraries committee
I think Roman is right here. Moreover we have known this for at least I think seven years http://comments.gmane.org/gmane.comp.lang.haskell.cafe/20097, where I wrote:
| Yes, Dynamic preceded the Typeable class, I think. | Were we to do it today, I think we'd have | | data Dynamic = forall a . (Typeable a) => Dynamic a | | Whether it's worth changing, I'm not sure. It's a library so, | if a change desirable, anyone could take a lead.
The new representation for Dynamic would be good because it's less insecure than all this "Obj" nonsense, instead relying on Typeable, which is pretty good these days.
Pedro is the most recent visitor to this territory and may have views.
Roman's point about the method for the Typeable class is a good one too, and not one I've seen discussed.
Over to you
I, at least, am in favor of this. I've thought for a while that the ideal form of all this is something like:
data TypeRep a -- indexed by a
class Typeable a where typeRep :: TypeRep a
data Dynamic = forall a. Dynamic (TypeRep a) a
Where, ideally, TypeRep is an indexed type, and you can match on it to refine its argument. Then Typeable just becomes the implicit version of this evidence, for convenience. TypeRep versions of cast would also have to be primitive probably (since one can not, a priori, enumerate the diagonal of all possible monotypes, now and in the future).
Anyhow, I don't know if this entire interface is or will be implementable in GHC (the idea comes from a document about JHC way back, although I don't know if even it implements this), but using Typeable in an existential captures the Dynamic part of it, at least.
Also, I hadn't seen the Tagged version of Typeable before (and hadn't thought of it myself). I expect it's an oversight that this wasn't the form chosen, as it seems superior to me. In fact, it seems like every situation where the 0-width Proxy# could be used, Tagged could also be used instead, and is automatically 0-width, and has better sharing behavior? Unless you explicitly don't want sharing, that is.
It seems like any relative inconvenience could probably be alleviated by the proxy function in tagged, while keeping the nicer behavior.
-- Dan
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
Adding a phantom type to TypeRep itself will break a lot of code (the untyped TypeRep is used quite a bit) without any real benefit (it's essentially the same as Tagged a TypeRep). * Carter Schonwald <carter.schonwald@gmail.com> [2014-03-10 13:44:13-0400]
+++++1000 to dan doels strawman suggestion.
I'm a huge fan of indexed types style apis like that one.
On Mon, Mar 10, 2014 at 11:54 AM, Dan Doel <dan.doel@gmail.com> wrote:
On Mon, Mar 10, 2014 at 7:26 AM, Simon Peyton Jones <simonpj@microsoft.com
wrote:
Dear Core Libraries committee
I think Roman is right here. Moreover we have known this for at least I think seven years http://comments.gmane.org/gmane.comp.lang.haskell.cafe/20097, where I wrote:
| Yes, Dynamic preceded the Typeable class, I think. | Were we to do it today, I think we'd have | | data Dynamic = forall a . (Typeable a) => Dynamic a | | Whether it's worth changing, I'm not sure. It's a library so, | if a change desirable, anyone could take a lead.
The new representation for Dynamic would be good because it's less insecure than all this "Obj" nonsense, instead relying on Typeable, which is pretty good these days.
Pedro is the most recent visitor to this territory and may have views.
Roman's point about the method for the Typeable class is a good one too, and not one I've seen discussed.
Over to you
I, at least, am in favor of this. I've thought for a while that the ideal form of all this is something like:
data TypeRep a -- indexed by a
class Typeable a where typeRep :: TypeRep a
data Dynamic = forall a. Dynamic (TypeRep a) a
Where, ideally, TypeRep is an indexed type, and you can match on it to refine its argument. Then Typeable just becomes the implicit version of this evidence, for convenience. TypeRep versions of cast would also have to be primitive probably (since one can not, a priori, enumerate the diagonal of all possible monotypes, now and in the future).
Anyhow, I don't know if this entire interface is or will be implementable in GHC (the idea comes from a document about JHC way back, although I don't know if even it implements this), but using Typeable in an existential captures the Dynamic part of it, at least.
Also, I hadn't seen the Tagged version of Typeable before (and hadn't thought of it myself). I expect it's an oversight that this wasn't the form chosen, as it seems superior to me. In fact, it seems like every situation where the 0-width Proxy# could be used, Tagged could also be used instead, and is automatically 0-width, and has better sharing behavior? Unless you explicitly don't want sharing, that is.
It seems like any relative inconvenience could probably be alleviated by the proxy function in tagged, while keeping the nicer behavior.
-- Dan
_______________________________________________ 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
isn't it a GADT/singleton/data family more than a phantom? On Mon, Mar 10, 2014 at 2:09 PM, Roman Cheplyaka <roma@ro-che.info> wrote:
Adding a phantom type to TypeRep itself will break a lot of code (the untyped TypeRep is used quite a bit) without any real benefit (it's essentially the same as Tagged a TypeRep).
* Carter Schonwald <carter.schonwald@gmail.com> [2014-03-10 13:44:13-0400]
+++++1000 to dan doels strawman suggestion.
I'm a huge fan of indexed types style apis like that one.
On Mon, Mar 10, 2014 at 11:54 AM, Dan Doel <dan.doel@gmail.com> wrote:
On Mon, Mar 10, 2014 at 7:26 AM, Simon Peyton Jones < simonpj@microsoft.com
wrote:
Dear Core Libraries committee
I think Roman is right here. Moreover we have known this for at least I think seven years http://comments.gmane.org/gmane.comp.lang.haskell.cafe/20097, where I wrote:
| Yes, Dynamic preceded the Typeable class, I think. | Were we to do it today, I think we'd have | | data Dynamic = forall a . (Typeable a) => Dynamic a | | Whether it's worth changing, I'm not sure. It's a library so, | if a change desirable, anyone could take a lead.
The new representation for Dynamic would be good because it's less insecure than all this "Obj" nonsense, instead relying on Typeable, which is pretty good these days.
Pedro is the most recent visitor to this territory and may have views.
Roman's point about the method for the Typeable class is a good one too, and not one I've seen discussed.
Over to you
I, at least, am in favor of this. I've thought for a while that the ideal form of all this is something like:
data TypeRep a -- indexed by a
class Typeable a where typeRep :: TypeRep a
data Dynamic = forall a. Dynamic (TypeRep a) a
Where, ideally, TypeRep is an indexed type, and you can match on it to refine its argument. Then Typeable just becomes the implicit version of this evidence, for convenience. TypeRep versions of cast would also have to be primitive probably (since one can not, a priori, enumerate the diagonal of all possible monotypes, now and in the future).
Anyhow, I don't know if this entire interface is or will be implementable in GHC (the idea comes from a document about JHC way back, although I don't know if even it implements this), but using Typeable in an existential captures the Dynamic part of it, at least.
Also, I hadn't seen the Tagged version of Typeable before (and hadn't thought of it myself). I expect it's an oversight that this wasn't the form chosen, as it seems superior to me. In fact, it seems like every situation where the 0-width Proxy# could be used, Tagged could also be used instead, and is automatically 0-width, and has better sharing behavior? Unless you explicitly don't want sharing, that is.
It seems like any relative inconvenience could probably be alleviated by the proxy function in tagged, while keeping the nicer behavior.
-- Dan
_______________________________________________ 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
Right — I misunderstood what Dan meant on the first reading. Then it's an even more drastic change to Typeable. And it's not clear (to me, at least) how it should work. * Carter Schonwald <carter.schonwald@gmail.com> [2014-03-10 16:04:21-0400]
isn't it a GADT/singleton/data family more than a phantom?
On Mon, Mar 10, 2014 at 2:09 PM, Roman Cheplyaka <roma@ro-che.info> wrote:
Adding a phantom type to TypeRep itself will break a lot of code (the untyped TypeRep is used quite a bit) without any real benefit (it's essentially the same as Tagged a TypeRep).
* Carter Schonwald <carter.schonwald@gmail.com> [2014-03-10 13:44:13-0400]
+++++1000 to dan doels strawman suggestion.
I'm a huge fan of indexed types style apis like that one.
On Mon, Mar 10, 2014 at 11:54 AM, Dan Doel <dan.doel@gmail.com> wrote:
On Mon, Mar 10, 2014 at 7:26 AM, Simon Peyton Jones < simonpj@microsoft.com
wrote:
Dear Core Libraries committee
I think Roman is right here. Moreover we have known this for at least I think seven years http://comments.gmane.org/gmane.comp.lang.haskell.cafe/20097, where I wrote:
| Yes, Dynamic preceded the Typeable class, I think. | Were we to do it today, I think we'd have | | data Dynamic = forall a . (Typeable a) => Dynamic a | | Whether it's worth changing, I'm not sure. It's a library so, | if a change desirable, anyone could take a lead.
The new representation for Dynamic would be good because it's less insecure than all this "Obj" nonsense, instead relying on Typeable, which is pretty good these days.
Pedro is the most recent visitor to this territory and may have views.
Roman's point about the method for the Typeable class is a good one too, and not one I've seen discussed.
Over to you
I, at least, am in favor of this. I've thought for a while that the ideal form of all this is something like:
data TypeRep a -- indexed by a
class Typeable a where typeRep :: TypeRep a
data Dynamic = forall a. Dynamic (TypeRep a) a
Where, ideally, TypeRep is an indexed type, and you can match on it to refine its argument. Then Typeable just becomes the implicit version of this evidence, for convenience. TypeRep versions of cast would also have to be primitive probably (since one can not, a priori, enumerate the diagonal of all possible monotypes, now and in the future).
Anyhow, I don't know if this entire interface is or will be implementable in GHC (the idea comes from a document about JHC way back, although I don't know if even it implements this), but using Typeable in an existential captures the Dynamic part of it, at least.
Also, I hadn't seen the Tagged version of Typeable before (and hadn't thought of it myself). I expect it's an oversight that this wasn't the form chosen, as it seems superior to me. In fact, it seems like every situation where the 0-width Proxy# could be used, Tagged could also be used instead, and is automatically 0-width, and has better sharing behavior? Unless you explicitly don't want sharing, that is.
It seems like any relative inconvenience could probably be alleviated by the proxy function in tagged, while keeping the nicer behavior.
-- Dan
_______________________________________________ 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
Note, I'm not proposing that we change Typeable to match my vision. I just think that it is (closer to) an ideal formulation, and the existential Dynamic is closer to it, and thus good. :) Changing the definition of Dynamic should have about 0 cost API-wise, which makes it a no brainer. The same can't be said for the rest of my ideal Typeable, though, which probably rules it out. On Mon, Mar 10, 2014 at 4:25 PM, Roman Cheplyaka <roma@ro-che.info> wrote:
Right -- I misunderstood what Dan meant on the first reading.
Then it's an even more drastic change to Typeable. And it's not clear (to me, at least) how it should work.
* Carter Schonwald <carter.schonwald@gmail.com> [2014-03-10 16:04:21-0400]
isn't it a GADT/singleton/data family more than a phantom?
On Mon, Mar 10, 2014 at 2:09 PM, Roman Cheplyaka <roma@ro-che.info> wrote:
Adding a phantom type to TypeRep itself will break a lot of code (the untyped TypeRep is used quite a bit) without any real benefit (it's essentially the same as Tagged a TypeRep).
* Carter Schonwald <carter.schonwald@gmail.com> [2014-03-10 13:44:13-0400]
+++++1000 to dan doels strawman suggestion.
I'm a huge fan of indexed types style apis like that one.
On Mon, Mar 10, 2014 at 11:54 AM, Dan Doel <dan.doel@gmail.com> wrote:
On Mon, Mar 10, 2014 at 7:26 AM, Simon Peyton Jones < simonpj@microsoft.com
wrote:
Dear Core Libraries committee
I think Roman is right here. Moreover we have known this for at least I think seven years http://comments.gmane.org/gmane.comp.lang.haskell.cafe/20097, where I wrote:
| Yes, Dynamic preceded the Typeable class, I think. | Were we to do it today, I think we'd have | | data Dynamic = forall a . (Typeable a) => Dynamic a | | Whether it's worth changing, I'm not sure. It's a library so, | if a change desirable, anyone could take a lead.
The new representation for Dynamic would be good because it's less insecure than all this "Obj" nonsense, instead relying on Typeable, which is pretty good these days.
Pedro is the most recent visitor to this territory and may have views.
Roman's point about the method for the Typeable class is a good one too, and not one I've seen discussed.
Over to you
I, at least, am in favor of this. I've thought for a while that the ideal form of all this is something like:
data TypeRep a -- indexed by a
class Typeable a where typeRep :: TypeRep a
data Dynamic = forall a. Dynamic (TypeRep a) a
Where, ideally, TypeRep is an indexed type, and you can match on it to refine its argument. Then Typeable just becomes the implicit version of this evidence, for convenience. TypeRep versions of cast would also have to be primitive probably (since one can not, a priori, enumerate the diagonal of all possible monotypes, now and in the future).
Anyhow, I don't know if this entire interface is or will be implementable in GHC (the idea comes from a document about JHC way back, although I don't know if even it implements this), but using Typeable in an existential captures the Dynamic part of it, at least.
Also, I hadn't seen the Tagged version of Typeable before (and hadn't thought of it myself). I expect it's an oversight that this wasn't the form chosen, as it seems superior to me. In fact, it seems like every situation where the 0-width Proxy# could be used, Tagged could also be used instead, and is automatically 0-width, and has better sharing behavior? Unless you explicitly don't want sharing, that is.
It seems like any relative inconvenience could probably be alleviated by the proxy function in tagged, while keeping the nicer behavior.
-- Dan
_______________________________________________ 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 Mon, Mar 10, 2014 at 6:35 AM, Roman Cheplyaka <roma@ro-che.info> wrote:
Ok, one reason is that the TypeRep won't be cached in the Dynamic value. Even in GHC 7.8 Typeable is defined as
class Typeable a where typeRep# :: Proxy# a -> TypeRep
instead of
class Typeable a where typeRep :: Tagged a TypeRep
Why? Is this an oversight?
I talked with Ed about this, and he noted that this might be a false problem. Certainly, the Proxy# is never actually used, so as long as the generated instances are of the form: typeRep# = let tr = ... in \_ -> tr the TypeReps are shared, and are at most a bit of indirection away. Also, how different are (Tagged tr :: Tagged a TypeRep) and ((\_ -> tr) :: Proxy# a -> TypeRep) at a low level? I know the constructor of the former disappears in core, but don't know what specifically happens with 0-width fields like Proxy#. Is the latter slightly less efficient? If so, can the optimizer eliminate the difference for cases like this? -- Dan
It's certainly true that, with the current setup, a monomorphic instance will look like instance Typeable Foo where typeRep# = \_ -> (...something...) :: TypeRep and the optimiser will float the (...something...) to top level. But this is an optimisation, not true by construction. For example, a non-top-level instance might look like instance (Typeable a, Typeable b) => Typeable (a b) where typeRep# = \_ -> mkAppTy (typeRep# (undefined::Proxy a)) (typeRep# (undefined :: Proxy b)) And that in turn will become $dfTyApp = /\a b. \(d1::Typeable a) (d2::Typeable b). \_ -> mkAppTy (d1 a) (d2 b) (I'm missing out some newtypes etc.) Now, will the (d1 a) and (d2 b) be floated outside the \_? Not so certain. It depends on the let-floater. The good thing about the Tagged stuff is that there is no lambda in the first place, so the issue doesn't arise. It's ok if the programming interface is less easy to use; Data.Typeable.typeOf is already a function, not a method. The method is called typeRep#, and is internal. So I think you can go ahead and improve the design. But it's clearly a library-committee decision; I'll just do what you say. Simon From: Libraries [mailto:libraries-bounces@haskell.org] On Behalf Of Dan Doel Sent: 10 March 2014 18:02 To: Roman Cheplyaka Cc: Haskell Libraries Subject: Re: Data.Dynamic: Any vs existential On Mon, Mar 10, 2014 at 6:35 AM, Roman Cheplyaka <roma@ro-che.info<mailto:roma@ro-che.info>> wrote: Ok, one reason is that the TypeRep won't be cached in the Dynamic value. Even in GHC 7.8 Typeable is defined as class Typeable a where typeRep# :: Proxy# a -> TypeRep instead of class Typeable a where typeRep :: Tagged a TypeRep Why? Is this an oversight? I talked with Ed about this, and he noted that this might be a false problem. Certainly, the Proxy# is never actually used, so as long as the generated instances are of the form: typeRep# = let tr = ... in \_ -> tr the TypeReps are shared, and are at most a bit of indirection away. Also, how different are (Tagged tr :: Tagged a TypeRep) and ((\_ -> tr) :: Proxy# a -> TypeRep) at a low level? I know the constructor of the former disappears in core, but don't know what specifically happens with 0-width fields like Proxy#. Is the latter slightly less efficient? If so, can the optimizer eliminate the difference for cases like this? -- Dan
I'm open to moving Tagged into base with 7.10. Since it'll make the resultant code less likely to break for artificial reasons involving lifting, etc. and as it is mostly an internal API anyways, I don't have much I can say against it. Though that said, my poor tagged package will have had its innards slurped out one module at time over the course of years. ;) -Edward On Mon, Mar 10, 2014 at 4:49 PM, Simon Peyton Jones <simonpj@microsoft.com>wrote:
It’s certainly true that, with the current setup, a monomorphic instance will look like
instance Typeable Foo where
typeRep# = \_ -> (...something...) :: TypeRep
and the optimiser will float the (...something...) to top level. But this is an optimisation, not true by construction. For example, a non-top-level instance might look like
instance (Typeable a, Typeable b) => Typeable (a b) where
typeRep# = \_ -> mkAppTy (typeRep# (undefined::Proxy a))
(typeRep# (undefined :: Proxy b))
And that in turn will become
$dfTyApp = /\a b. \(d1::Typeable a) (d2::Typeable b).
\_ -> mkAppTy (d1 a) (d2 b)
(I’m missing out some newtypes etc.) Now, will the (d1 a) and (d2 b) be floated outside the \_? Not so certain. It depends on the let-floater.
The good thing about the Tagged stuff is that there is no lambda in the first place, so the issue doesn’t arise.
It’s ok if the programming interface is less easy to use; Data.Typeable.typeOf is already a function, not a method. The method is called typeRep#, and is internal.
So I think you can go ahead and improve the design. But it’s clearly a library-committee decision; I’ll just do what you say.
Simon
*From:* Libraries [mailto:libraries-bounces@haskell.org] *On Behalf Of *Dan Doel *Sent:* 10 March 2014 18:02 *To:* Roman Cheplyaka *Cc:* Haskell Libraries
*Subject:* Re: Data.Dynamic: Any vs existential
On Mon, Mar 10, 2014 at 6:35 AM, Roman Cheplyaka <roma@ro-che.info> wrote:
Ok, one reason is that the TypeRep won't be cached in the Dynamic value. Even in GHC 7.8 Typeable is defined as
class Typeable a where typeRep# :: Proxy# a -> TypeRep
instead of
class Typeable a where typeRep :: Tagged a TypeRep
Why? Is this an oversight?
I talked with Ed about this, and he noted that this might be a false problem. Certainly, the Proxy# is never actually used, so as long as the generated instances are of the form:
typeRep# = let tr = ... in \_ -> tr
the TypeReps are shared, and are at most a bit of indirection away. Also, how different are (Tagged tr :: Tagged a TypeRep) and ((\_ -> tr) :: Proxy# a -> TypeRep) at a low level? I know the constructor of the former disappears in core, but don't know what specifically happens with 0-width fields like Proxy#. Is the latter slightly less efficient? If so, can the optimizer eliminate the difference for cases like this?
-- Dan
-- You received this message because you are subscribed to the Google Groups "haskell-core-libraries" group. To unsubscribe from this group and stop receiving emails from it, send an email to haskell-core-libraries+unsubscribe@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
One reason for favoring the Proxy# a style over the Tagged style is almost any manipulation of the Tagged variant requires ScopedTypeVariables and a very awkward programming style, while a 0-width proxy can be passed around like an explicit type application. Otherwise they are largely equivalent if you're careful about how the low level definitions work. As the original author of both, I'm not personally wedded to either the Tagged or the Proxy style, but I find in practice the Proxy version leads to much prettier code that is easier to follow. -Edward On Mon, Mar 10, 2014 at 6:35 AM, Roman Cheplyaka <roma@ro-che.info> wrote:
Ok, one reason is that the TypeRep won't be cached in the Dynamic value. Even in GHC 7.8 Typeable is defined as
class Typeable a where typeRep# :: Proxy# a -> TypeRep
instead of
class Typeable a where typeRep :: Tagged a TypeRep
Why? Is this an oversight?
* Roman Cheplyaka <roma@ro-che.info> [2014-03-10 12:11:27+0200]
In Data.Dynamic, Dynamic is defined as
data Dynamic = Dynamic TypeRep Any
Does this have any advantage over a safer
data Dynamic = forall a. Typeable a => Dynamic a
?
Roman
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
participants (6)
-
Carter Schonwald -
Dan Doel -
Edward Kmett -
Nikita Volkov -
Roman Cheplyaka -
Simon Peyton Jones