POV-Ray : Newsgroups : povray.off-topic : More Haskell fanning : Re: More Haskell fanning Server Time
30 Jul 2024 02:26:57 EDT (-0400)
  Re: More Haskell fanning  
From: Invisible
Date: 17 May 2011 04:07:38
Message: <4dd22cca$1@news.povray.org>
On 16/05/2011 20:18, Darren New wrote:
> On 5/16/2011 1:06, Invisible wrote:
>> Well, no. See, if you call a Win32 function, it just works. If you call a
>> function that you wrote yourself, you have to tell the linker to link the
>> corresponding object code.
>
> Unless you register it, I expect.

Well, no, what I'm saying is that if you call a function that's defined 
in (say) windows.h, the linker somehow "finds" it. But if you wrote some 
C source code of your own, you have to tell the linker to link in the 
object code or it complains it can't find it.

It makes sense that you have to tell the linker where to find your own 
code. What I can't figure out is how it somehow "knows" when a function 
is from the Win32 API and magically finds it.

(The answer is probably something like "GHC automatically includes the 
Win32 files at link time".)

>> As I understand it, calling Win32 works by calling a C stub function
>> which
>> does the necessary machine code magic to actually invoke the Windows
>> kernel,
>> whatever that may be. But I don't see anywhere where this gets linked
>> in...
>
> It's entirely possible the declaration itself generates that code, isn't
> it? I'm pretty sure that's how it works in C#: you say "C# XYZ(i) calls
> C-languge PDQ with a (short) parameter" and the compiler generates an
> XYZ function that casts its argument to a short and jumps to the PDQ
> function, basically.

If I do a "foreign import", the Haskell compiler generates a Haskell 
function which calls the corresponding C function. Which is fine if 
you're statically linking the C code into your binary. But you don't 
link the Windows kernel into your application, do you? It does some 
weird magic with processor rings and code gates to enter kernel mode to 
run the code.

I'm no expert, but as I say, I was under the impression that the usual 
way to access a DLL is to link in a small C stub which defines the code 
necessary to dynamically find and execute the exported functions from 
the DLL.

>> Which is a bit like developing software for Linux and insisting that
>> everybody should avoid using Bash.
>
> Yep. More like developing distributed programs for Linux and deciding
> that sockets are too hard to use.

LOL! Yeah...

Seriously. Everybody talks about "hey, it's cool. Oh, except on Windows, 
where we have to solve DLL Hell. But hey, who actually uses Windows?"

Personally, I thought "DLL hell" went away about 10 years ago...

>>>> I'm not seeing why you would need to do this with cold code update
>>>> either.
>>>> You only need to shut down the processes related to the thing you're
>>>> actually changing.
>>>
>>> Then you have a bunch of different processes on the same machine
>>> fighting over resources. Sending messages between them means you now
>>> have a bunch of context switches, etc.
>>
>> I don't follow.
>
> It's less efficient to have the kernel scheduler scheduling the
> different processes than to have the Erlang-specific scheduler doing it.
> That's why people make 100,000 erlang tasks in one process and doing the
> same in Linux will bring the kernel to its knees, if not run you out of
> memory.

Right. So all you're saying is that OS processes are heavier than Erlang 
processes.

One thing Erlang can do (and Haskell can't, easily) is that because 
Erlang is a VM, you can have several unrelated Erlang applications 
running on the same VM. But to run multiple Haskell applications, you 
would have to have multiple copies of the Haskell runtime in action. 
Which, as you say, isn't something you want to do too much of.

>>> Yep. And that's why building a big system like this with static
>>> type-erased data is more difficult than dynamic tagged data.
>>
>> ...which is why the Haskell implementation is using dynamic tagged data.
>
> Yep. And that loses a lot of the benefits of the static typing right there.

*sigh* This old argument again.

Yes, the entire program is statically typed, but this one tiny part 
where you have to do a simple runtime type check automatically 
COMPLETELY DESTROYS EVERY SINGLE ADVANTAGE OF STATIC TYPING!

>> Can't handle it _yet_. They have concrete plans for how they would
>> implement it, they just haven't yet.
>
> Fair enough. I look forward to seeing what they come up with.

I look forward to seeing whether they ever finish it.

(I lose count of how many projects targeting Haskell at the GPU have 
been started. The number of them which produced a production-grade end 
product is zero.)

>> 1. Make no attempt to verify whether data structures match at all.
>
> Right.
>
> Actually, even worse, in Erlang, the likelihood is that you just leave
> the mismatched message in the buffer, which then grows until it crashes
> the whole machine with no obvious reason. One of the poorly thought-out
> designs there, methinks.

I'll say!

Basically you need to manually make sure you send a version number at 
the start of your message exchange, or something like that, and make 
sure that all servers and clients you write can handle all versions of 
the protocol.

Or design the protocol so that it never needs to change. (Which is not 
infeasible if you can send code as part of the protocol I suppose...)

>> (By contrast, Haskell might potentially be able to distinguish the old
>> type
>> and the new type at the type level, if the structure of the type has
>> actually changed, and issue a compile-time warning.)
>
> This assumes you know at compile time what types the other side is
> using, which also isn't always true. :-)

Not really. When you compile v1, you assume that the other side will be 
v1 as well. When you compile v2, the compiler checks what you changed, 
and warns you if you don't explicitly handle the v1 data (unless it's 
identical).

>> 2. I have literally no idea how Erlang sends functions over the wire.
>
> It's out in the erldocs somewhere, but I can't find it after five
> minutes of looking around. They specify the wire format of everything,
> including that.

Yeah, I figured.

The Haskell implementation has a potential advantage in that you can 
specify precisely how to serialise stuff if you want to. (Usually to 
send a more compact representation by leaving off data which can be 
recomputed at the other side, making use of the special structure of the 
data to skip parts of it, etc.) Of course, the bit that tells the other 
side who the message is for and what type it contains isn't open to 
negotiation. ;-)

>> assumed it just sends the VM executable code over the wire.
>
> Given that I can write a function on an x86 machine and ship it over to
> a program running on a Sparc that has been running since before I bought
> the x86 machine, yah, I'd say there's some sort of virtual code being
> transfered. :-)

And yet, that would seem rather heavy compared to just sending a 
function name (or rather, a *unique* function identifier), so perhaps 
Erlang actually does it that way like Haskell is doing. Or maybe it only 
sends the code if the other side doesn't already have it or something.

Come to think of it, I'm still figuring out how it manages to send atoms...

>> In both cases, it looks like you need a name plus some kind of version
>> number, or maybe a hash of a description or something, to distinguish
>> things
>> that the programmer has assigned identical names to...
>
> It depends on whether you're sending a function or the name of the
> function, really.

Well, we're sending type names too, which give you the same problem. 
(And sending a type definition doesn't help, because we still need to 
figure out whether they're *meant* to be the same type or not.)


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.