You'd still need several versions of the code for a polymorphic function, one for pointer values, one for 4-byte non-pointers, one for 8-byte non-pointers etc.
That's what .net does, I believe, but via runtime code generation.
| -----Original Message-----
| From: [hidden email] [mailto:[hidden email]] On Behalf Of Ashley Yakeley
| Sent: 29 December 2005 17:56
| To: [hidden email] | Subject: [Haskell] Re: Boxing (Day) Question
| In article
| <[hidden email] | ft.com>,
| "Simon Peyton-Jones" <[hidden email]> wrote:
| > The .NET CLR lifts the restriction by specialising code, so that it can
| > adapt to whether it is moving Int# or Double# values around. In
| > Haskell, though, it's not possible to statically generate all the
| > instances you need, so you'd need run-time code generation to do this.
| > It's a real restriction, and sometimes very tiresome, but I'm not
| > planning to fix it soon, unless I have a brilliant idea for how to do it
| > easily.
| So you don't think having a different kind for each kind of storage
| (e.g. #4 for 4-byte values, etc.) would help you here?
| Ashley Yakeley, Seattle WA
| Haskell mailing list
| [hidden email] | http://www.haskell.org/mailman/listinfo/haskell _______________________________________________
Haskell-Cafe mailing list
[hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe
| > You'd still need several versions of the code for a polymorphic
| > for pointer values, one for 4-byte non-pointers, one for 8-byte
| > etc.
| Yes, but that's up to the user. A type variable always has a
| kind, so for instance one might want an array over any 4-byte
| non-pointer value:
| data Array4 (a :: #4)
| Functions on Array4 only need one version of code. This makes
| polymorphism less useful, of course, but the goal here is to be closer
| to the machine.
Ah, now I see what you mean. I had not thought of doing that, but it'd
make sense, esp if there were lots of 4-byte-non-pointer types. But
there are only a couple (Int# and Word32#) so I'm not sure it's worth
the effort. But (without thinking about it too hard) it looks like a
very sensible idea. The trickiness is in the fact that some type
constructors (notably (->)) are somewhat kind-polymorphic, which gives
rise to some awkwardness in the type checker. So the details might not
be entirely straightforward.
On Wed, Jan 04, 2006 at 09:48:05AM -0000, Simon Peyton-Jones wrote:
> Ah, now I see what you mean. I had not thought of doing that, but it'd
> make sense, esp if there were lots of 4-byte-non-pointer types. But
> there are only a couple (Int# and Word32#) so I'm not sure it's worth
> the effort. But (without thinking about it too hard) it looks like a
> very sensible idea. The trickiness is in the fact that some type
> constructors (notably (->)) are somewhat kind-polymorphic, which gives
> rise to some awkwardness in the type checker. So the details might not
> be entirely straightforward.
perhaps some sort of post-kind-inference can be done. so the only _user
visible_ unboxed kind would be # (not counting unboxed tuples) and then
after everything is typechecked in terms of that, a separate inference
pass figures out the sizes #4, #8, etc. then a specialized version of
each polymorphic routine is created for each kind it is called at. This
is opposed to full expansion where polymoprhic routines are specialized
at each type rather than each kind. This would solve the exponential
code growth problem since there are only a finite number of kinds (up to
isomorphism if user defined kinds are allowed) in any implementation.
One can do separate compilation by ouputing the functions with the
special tag saying the linker should combine identical names, so the
same function might get outputted a few times, but only a single copy
will end up in the final executable. alternatively, a version for each
kind can be generated up front and then the linker can clean up the ones
that arn't used.