On 27/04/2011, at 20:38 , Erik de Castro Lopo wrote:
>> e "a", which could be anything.
> 
> In fact it can't even figure out if the object actually contains a
> DataRS or whether its something else

That information isn't visible in the type, but the function itself could 
examine the header field of the object...


>> They can't. At some point in the implementation you just have to
>> trust that the code is correct.
> 
> True, but you don't give regular scissors to child, you give them
> safety scissors so they are less likely to do themselves damage.
> Similarly if you are designing a high level language, I don't see
> any reason why the language should provide the programmer with
> features that can so easily be abused to create unsafe programs.

Yeah, but we're already giving them unsafeCoercePtr. 


> I also think its possible to remove potentially unsafe language
> features and still produce a high level language capable of
> replacing C for systems programming. In some cases this may mean
> moving things from the library to the compiler.

Yes, but the code still has to exist somewhere. When we bootstrap DDC, both 
versions would be written in the same language, and both would be linked into 
the user programs. The line between "compiler" and "base library" isn't always 
a strong one.  I think it's ok to use unsafe ops internally in the base 
library, provided they're not exported to the modules that import it.


> This is very much applying Yaron Minsky's "Make illegal states
> unrepresentable" idea to language design.

I totally agree for regular programming. But once you add unsafeCoercePtr to 
the programming model you've already let the bears in. You've got to break the 
abstraction at some point. If you break it in the base library then it's easier 
to change the underlying object representation as you don't have to recompile 
the compiler.


>> There is work on type preserving compilation that maintains type
>> information all the way to the assembly level, but that's another
>> life's work. Simon Winwood did his thesis on this stuff.
> 
> Yes, but with LLVM we are already quite a long way there. LLVM
> allows some kinds of casts, but is very much more strict with
> types than the average C compiler.

I meant representing *all* of the type information at assembly level. The LLVM 
type system knows what's a pointer and what's not, but it doesn't know that the 
Haskell/Disciple List type is polymorphic and has two constructors.


>> If you implement a function like boxPrim, you should give it a
>> type class constraint that requires the argument to actually be
>> a primitive unboxed type.
>> 
>> class Boxable a b where
>> box    :: a -> b
>> unbox  :: b -> a 
>> 
>> You'd then bake the valid instances into the compiler, but allow
>> users to define their own if they want.
>> 
>> instance Boxable Int32# Int32 where
>>  box   = ...
>>  unbox = ... 
>> 
>> or something.
> 
> Again, thats an idea I really like. Nice!
> 
> At this stage I think I should drop my original idea and look into
> 
>  0) Fixing peekDataRS_payload so it has signature of
>        :: forall a. a -> Addr#

Yeah, I'd do that first. You'll need to add the primitives to coerce between 
Addr# and types like Ptr# Int32#. Add them in the Data.Addr module.


>  1) Look at doing one or more of these two:
> 
>        a) data Int32 = Int { unboxed :: Int32# }
> 
>        b) class Boxable


The first would be more general as you could support an arbitrary number of 
fields with arbitrary types.

The second would probably be easier to implement. 


Ben.


-- 
Disciple-Cafe mailing list
http://groups.google.com/group/disciple-cafe

Reply via email to