[Haskell-beginners] Natural functions versus existential types
Darren Grant
therealkludgy at gmail.com
Mon Jan 14 02:34:18 CET 2013
On Wed, Jan 9, 2013 at 1:45 PM, Aleksandar Dimitrov <
aleks.dimitrov at gmail.com> wrote:
> On Sun, Jan 06, 2013 at 11:22:51PM -0800, Darren Grant wrote:
> > I've seen some cases where Haskell examples dive into existential types
> > instead of using natural higher order functions. For instance, the
> > "Existential type" wiki page [1] section 2.2 proposes existentials as the
> > solution to a heterogeneous list problem where a ray-tracer must
> evaluate a
> > trace function for different types of objects. Is there a good reason for
> > this, or is it just a case of prior language assumptions leading to
> > unnatural code? Why could I not just make the list homogeneous by
> supplying
> > a list of partially evaluated trace functions instead?
>
> I have never written a ray-tracer, so I don't know about the exact
> requirements,
> but depending on the code in question, partial evaluation might not be
> possible.
>
> Parametric types can only be instantiated with *one* specific type. A list
> [a]
> can only be either [Int] or [Bool], but not [Int,Bool] or so. [1]
>
> So whenever you'd like to have a collection of things that won't have the
> same
> type, but have a certain operation defined on them, existential types come
> in
> handy. A partial application only makes sense when you have a function of
> higher
> arity, but `hits` in the example on the Wiki has only one argument, namely
> the
> list. At some point, a *collection* of Renderables needs to pass by the
> function
> `hit`. This collection probably needs to be stored somewhere, presumably a
> list,
> that is then fed to `hits`.
>
> Of course, you might set up your types differently, so that everything
> that will
> need to pass by the function `hits` would also be of one certain type. You
> could, for example, instead of storing the heterogeneous Renderables in a
> list,
> just reduce the different shapes to a Renderable data type that contains
> the
> important fields. Then, whenever a geometric object gets created, a
> Rendereable
> also gets created, then stored in that list. But how *viable* that is, I
> don't
> know. My gut feeling says that it won't be viable at all.
Consider the following:
If I have a traceable data type like data Sphere, I can define it and a
trace function as follows:
data Sphere = Sphere { spherepos :: (Double,Double,Double), sphereradius
:: Double }
traceSphere :: Sphere -> Ray -> [Hit]
Where Ray is self-explanatory and [Hit] is a resulting list of hits where
ray intersects sphere. I can then define a list of traceable objects thus,
[Ray -> [Hit]]
Which can also be thought of as,
type Trace = Ray -> [Hit]
[Trace]
Now I am able to define a homogeneous list [Trace] of partially applied
functions like so,
[traceSphere $ Sphere (0,0,0) 20,
traceSphere $ Sphere (10,20,30) 40,
traceBox $ Box (0,0,0) (10,10,10) -- where traceBox is also
partially applied
]
You see what I mean? This is very natural in Haskell. I'm sure there must
be counter-examples, but I haven't the comprehension for these.
What do you think?
> Sometimes I read an argument that existentials are required due to unknown
> constraints at compile time, but do not have an intuition for this
> > situation yet. For instance, I read that IO requires existentials. Still
> > working on that one. :)
>
> Where did you read that? The *definition* of the IO type does not use
> existentials [2]. But I'm not very familiar with the internals.
You're right! I'm not sure what I saw, but I would guess that I conflated
some application of IO with the definition.
Cheers,
Darren
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/beginners/attachments/20130113/dfbef124/attachment.htm>
More information about the Beginners
mailing list