Proposal: Move primitive-Data.Primitive.Addr API into base

Carter Schonwald carter.schonwald at gmail.com
Mon Oct 29 23:30:53 UTC 2018


the parametricity isn't for when you know things, its for saying "these are
possibly different or possibly the same, dont let me mix them up though,
cause I dont know yet"


On Mon, Oct 29, 2018 at 7:03 PM Daniel Cartwright <chessai1996 at gmail.com>
wrote:

> I'm not sure that argument applies at all, when talking about _incorrect_
> usages of Ptr. Sure, Addr probably shouldn't be used when there is
> meaningful type information/value to recover, but neither should Ptr be
> used when there is none.
>
> The argument being made is not to make 'better', per se, and there
> definitely won't be a 'mathematical statement' about this, but it certainly
> may be made clearer - in my opinion, the usages of 'Ptr' that i've already
> brought up are inherently unclear because of the bogus phantom type
> associated with 'Ptr'. The illustration of this begs no code that doesn't
> already exist in corelibs.
>
>
> On Mon, Oct 29, 2018 at 6:19 PM Carter Schonwald <
> carter.schonwald at gmail.com> wrote:
>
>> to zoom out: what code is improved? what code is made better/clearer? No
>> one has articulated this clearly.
>>
>> The one example of Addr being used in Vector.Storable.Mutable is not an
>> argument in favor of using Addr. Its an argument against it existing.
>>
>> i'm looking for evidence, in the form of code i can look at then say
>> "yes, this is better code" when comparing the two. Or a mathematical
>> statement of "what is made better"
>>
>> @David Feuer <david.feuer at gmail.com> , @Daniel , do you have one?
>>
>> when i'm writing complicated code, MORE polymorphism helps me usually.
>>
>> I can write some code like the following and even though I'm using it
>> with Int at argument,
>> I *Know* that i'm not mixing up arguments/values that i write as
>> different types. I cannot do this with Address!
>> (the type / function below can be found at
>> https://github.com/wellposed/numerical/blob/3a0bbf50bc6ce0b710aee755f5a4bfce08af4201/src/Numerical/Array/Layout/Builder.hs#L294
>> )
>>
>> {-# SPECIALIZE INLINE computeStarts :: [(Int,Int)]->Int->Int
>> ->[(Int,Int)] #-}
>> computeStarts:: (Enum a, Ord a, Num b )=>[(a,b)]-> a -> a -> [(a,b)]
>>
>> parametricity (even when constrained by type classes) is a powerful and
>> foundational tool for good programming in haskell and similar languages
>>
>> there has been nothing stated here that successfully articulates a good
>> reason to forgo/discourage parametricity as an engineering tool. for thats
>> what Addr is.
>> A datatype thats never safe in isolation, and discourages using
>> parametricity to write correct software.
>>
>> a very strong case is needed to forgo parametricity.
>>
>>
>>
>>
>> On Mon, Oct 29, 2018 at 5:33 PM David Feuer <david.feuer at gmail.com>
>> wrote:
>>
>>> Good point! Call it nominal then.
>>>
>>> On Mon, Oct 29, 2018, 5:24 PM Carter Schonwald <
>>> carter.schonwald at gmail.com> wrote:
>>>
>>>> absolutely false, represeentational equality of the  type a in `Ptr a`
>>>> does not mean the memory representation at the corresponding address is the
>>>> same.
>>>> (it sometimes is true, but memory packing/alignment details in structs
>>>> in C  for otherwise equivlanet structs should rule this out)
>>>>
>>>> aka, `a` being representationally equal to `b` via haskell newtypes
>>>> does not mean the memory representation at `Ptr a`, and `Ptr b` are the
>>>> same. a trivial example is when
>>>> host and network byte order aren't the same (eg big vs little endian
>>>> memory encodings)
>>>>
>>>> On Mon, Oct 29, 2018 at 12:28 PM David Feuer <david.feuer at gmail.com>
>>>> wrote:
>>>>
>>>>> What? Of course you can dereference it. You dereference it, getting a
>>>>> value of type `Void`,
>>>>> and apply absurd to get whatever you want in the world. This, of
>>>>> course, is utter nonsense,
>>>>> unless *having* the Ptr Void means that something has already gone
>>>>> wrong. It's pretty
>>>>> hard for me to imagine a situation where this is actually what you
>>>>> want. A Ptr () isn't nonsense.
>>>>> It is not terrible to use Ptr () to represent an Addr, but I wonder if
>>>>> it sends the wrong message.
>>>>> By the way: there's another argument for having Addr in base for now.
>>>>> We would really
>>>>> *like* for Ptr's parameter to have a *representational* role, but we
>>>>> *don't* want to require
>>>>> unsafeCoerce to cast Ptrs. The solution to that in the current role
>>>>> system:
>>>>>
>>>>>     data Addr = Addr Addr#
>>>>>
>>>>>     newtype Ptr a = Ptr_ Addr
>>>>>     type role Ptr representational
>>>>>
>>>>>     pattern Ptr :: Addr# -> Ptr a
>>>>>     pattern Ptr addr# = Ptr_ (Addr addr#)
>>>>>
>>>>>     -- Allow users to reveal coercibility of pointer types locally
>>>>>     ptrCoercion :: Coercion (Ptr a) (Ptr b)
>>>>>     ptrCoercion = Coercion
>>>>>
>>>>>     castPtr :: Ptr a -> Ptr b
>>>>>     castPtr = coerceWith ptrCoercion -- (or the now-free unwrap-rewrap
>>>>> definition)
>>>>>
>>>>>
>>>>> So even if we don't *expose* Addr in base, we should almost certainly
>>>>> *define*
>>>>> it there.
>>>>> On Mon, Oct 29, 2018 at 12:11 PM Carter Schonwald
>>>>> <carter.schonwald at gmail.com> wrote:
>>>>> >
>>>>> > The point , hahah, of a Ptr void is that you can’t dereference it.
>>>>> But you certainly can cast it and do address arithmetic on it!!
>>>>> >
>>>>> >
>>>>> >
>>>>> > On Mon, Oct 29, 2018 at 10:10 AM David Feuer <david.feuer at gmail.com>
>>>>> wrote:
>>>>> >>
>>>>> >> On Mon, Oct 29, 2018, 10:05 AM Sven Panne <svenpanne at gmail.com>
>>>>> wrote:
>>>>> >>>
>>>>> >>> Am Mo., 29. Okt. 2018 um 14:27 Uhr schrieb Daniel Cartwright <
>>>>> chessai1996 at gmail.com>:
>>>>> >>>>
>>>>> >>>> 'Ptr Void' is not a pointer to a value of type 'Void'; there are
>>>>> no values of type 'Void': this type is nonsensical.
>>>>> >>>
>>>>> >>>
>>>>> >>> That's the whole point, and it actually makes sense: If you see
>>>>> "Ptr Void", you can't do much with it, apart from passing it around or
>>>>> using castPtr on it. This is exactly what should be achieved by using "Ptr
>>>>> Void" in an API. This is basically the same as "void *" in C/C++.
>>>>> >>
>>>>> >>
>>>>> >> No, it does not make sense. The approximate equivalent of C's void*
>>>>> is Ptr Any. Ptr Void promises to give you anything you want on dereference,
>>>>> which is nonsense.
>>>>> >>
>>>>> >>>
>>>>> >>> You can't store or read "()", so the same holds as for Void (which
>>>>> didn't exist when the FFI was created IIRC).
>>>>> >>
>>>>> >>
>>>>> >> Sure you can. Storing () does nothing and reading it gives (). Our
>>>>> () is somewhat similar to C's void return type.
>>>>> >> _______________________________________________
>>>>> >> Libraries mailing list
>>>>> >> Libraries at haskell.org
>>>>> >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>>>>>
>>>> _______________________________________________
>> Libraries mailing list
>> Libraries at haskell.org
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/libraries/attachments/20181029/15cc0989/attachment.html>


More information about the Libraries mailing list