Discussion:
Proposal: Move primitive-Data.Primitive.Addr API into base
Add Reply
Daniel Cartwright
2018-10-25 15:24:37 UTC
Reply
Permalink
Motivation: There are a lot of places in base where 'Ptr a' is used in
place of 'Addr', because in base there is no 'Addr', only 'Addr#'. The
problem lies in the fact that many of these uses of 'Ptr a' are lying; the
'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
David Feuer
2018-10-25 15:27:51 UTC
Reply
Permalink
I concur. Addr is the "natural" wrapper for Addr#, and I believe all such
natural wrappers belong in base.
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is used in
place of 'Addr', because in base there is no 'Addr', only 'Addr#'. The
problem lies in the fact that many of these uses of 'Ptr a' are lying; the
'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Andrew Martin
2018-10-25 19:34:09 UTC
Reply
Permalink
I like the idea of moving the type Addr into base. But we cannot move the
entire module since it has functions that talk about PrimMonad, and we
definitely don't want to move that into base.
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is used in
place of 'Addr', because in base there is no 'Addr', only 'Addr#'. The
problem lies in the fact that many of these uses of 'Ptr a' are lying; the
'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
Carter Schonwald
2018-10-25 21:58:35 UTC
Reply
Permalink
Indeed. The monad transformer instances for primmonad need to live in
primmonad OR transformers to avoid orphans.

Either way, unless transformers moves into base (unlikely), no way anything
using prim monad will.
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we cannot move the
entire module since it has functions that talk about PrimMonad, and we
definitely don't want to move that into base.
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is used in
place of 'Addr', because in base there is no 'Addr', only 'Addr#'. The
problem lies in the fact that many of these uses of 'Ptr a' are lying; the
'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
David Feuer
2018-10-25 22:18:55 UTC
Reply
Permalink
We shouldn't really need to move anything into base except Addr and its
base instances.

On Oct 25, 2018 5:59 PM, "Carter Schonwald" <***@gmail.com>
wrote:

Indeed. The monad transformer instances for primmonad need to live in
primmonad OR transformers to avoid orphans.

Either way, unless transformers moves into base (unlikely), no way anything
using prim monad will.
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we cannot move the
entire module since it has functions that talk about PrimMonad, and we
definitely don't want to move that into base.
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is used in
place of 'Addr', because in base there is no 'Addr', only 'Addr#'. The
problem lies in the fact that many of these uses of 'Ptr a' are lying; the
'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-25 22:45:48 UTC
Reply
Permalink
hrmm, what are the pieces of base that are using Ptr when they really
should be using Addr? This would help me understand what would be made
better in base :)
Post by David Feuer
We shouldn't really need to move anything into base except Addr and its
base instances.
Indeed. The monad transformer instances for primmonad need to live in
primmonad OR transformers to avoid orphans.
Either way, unless transformers moves into base (unlikely), no way
anything using prim monad will.
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we cannot move the
entire module since it has functions that talk about PrimMonad, and we
definitely don't want to move that into base.
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is used in
place of 'Addr', because in base there is no 'Addr', only 'Addr#'. The
problem lies in the fact that many of these uses of 'Ptr a' are lying; the
'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Daniel Cartwright
2018-10-26 00:11:40 UTC
Reply
Permalink
yes, only the type and its instances should be moved as far as i'm aware.

Also, it's more than just base.

this Ptr is a lie:
https://hackage.haskell.org/package/ghc-compact-0.1.0.0/docs/GHC-Compact-Serialized.html#t:SerializedCompact
these Ptrs are lies:
https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-IO-Handle.html
in GHC.Stats, the foreign import "getRTSStats" has `Ptr () -> IO ()`, this
Ptr () is also a lie

These are just off the top of my head, there are more
Post by Carter Schonwald
hrmm, what are the pieces of base that are using Ptr when they really
should be using Addr? This would help me understand what would be made
better in base :)
Post by David Feuer
We shouldn't really need to move anything into base except Addr and its
base instances.
Indeed. The monad transformer instances for primmonad need to live in
primmonad OR transformers to avoid orphans.
Either way, unless transformers moves into base (unlikely), no way
anything using prim monad will.
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we cannot move
the entire module since it has functions that talk about PrimMonad, and we
definitely don't want to move that into base.
On Thu, Oct 25, 2018 at 11:25 AM Daniel Cartwright <
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is used in
place of 'Addr', because in base there is no 'Addr', only 'Addr#'. The
problem lies in the fact that many of these uses of 'Ptr a' are lying; the
'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Daniel Cartwright
2018-10-26 00:27:14 UTC
Reply
Permalink
Now, one could argue that `Ptr ()` isn't a lie, it sort of reads like C's
void pointer. But surely something like `Ptr Word8` is a lie, when it is
not actually a Ptr to Word8 values.
Post by Daniel Cartwright
yes, only the type and its instances should be moved as far as i'm aware.
Also, it's more than just base.
https://hackage.haskell.org/package/ghc-compact-0.1.0.0/docs/GHC-Compact-Serialized.html#t:SerializedCompact
https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-IO-Handle.html
in GHC.Stats, the foreign import "getRTSStats" has `Ptr () -> IO ()`, this
Ptr () is also a lie
These are just off the top of my head, there are more
On Thu, Oct 25, 2018 at 6:46 PM Carter Schonwald <
Post by Carter Schonwald
hrmm, what are the pieces of base that are using Ptr when they really
should be using Addr? This would help me understand what would be made
better in base :)
Post by David Feuer
We shouldn't really need to move anything into base except Addr and its
base instances.
Indeed. The monad transformer instances for primmonad need to live in
primmonad OR transformers to avoid orphans.
Either way, unless transformers moves into base (unlikely), no way
anything using prim monad will.
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we cannot move
the entire module since it has functions that talk about PrimMonad, and we
definitely don't want to move that into base.
On Thu, Oct 25, 2018 at 11:25 AM Daniel Cartwright <
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is used in
place of 'Addr', because in base there is no 'Addr', only 'Addr#'. The
problem lies in the fact that many of these uses of 'Ptr a' are lying; the
'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-26 03:22:55 UTC
Reply
Permalink
... when is a valid pointer not going to point at byte addressable memory
on memory architectures ghc can support or target?
Post by Daniel Cartwright
Now, one could argue that `Ptr ()` isn't a lie, it sort of reads like C's
void pointer. But surely something like `Ptr Word8` is a lie, when it is
not actually a Ptr to Word8 values.
Post by Daniel Cartwright
yes, only the type and its instances should be moved as far as i'm aware.
Also, it's more than just base.
https://hackage.haskell.org/package/ghc-compact-0.1.0.0/docs/GHC-Compact-Serialized.html#t:SerializedCompact
https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-IO-Handle.html
in GHC.Stats, the foreign import "getRTSStats" has `Ptr () -> IO ()`,
this Ptr () is also a lie
These are just off the top of my head, there are more
On Thu, Oct 25, 2018 at 6:46 PM Carter Schonwald <
Post by Carter Schonwald
hrmm, what are the pieces of base that are using Ptr when they really
should be using Addr? This would help me understand what would be made
better in base :)
Post by David Feuer
We shouldn't really need to move anything into base except Addr and its
base instances.
Indeed. The monad transformer instances for primmonad need to live in
primmonad OR transformers to avoid orphans.
Either way, unless transformers moves into base (unlikely), no way
anything using prim monad will.
On Thu, Oct 25, 2018 at 3:34 PM Andrew Martin <
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we cannot move
the entire module since it has functions that talk about PrimMonad, and we
definitely don't want to move that into base.
On Thu, Oct 25, 2018 at 11:25 AM Daniel Cartwright <
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is used
in place of 'Addr', because in base there is no 'Addr', only 'Addr#'. The
problem lies in the fact that many of these uses of 'Ptr a' are lying; the
'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-26 03:28:17 UTC
Reply
Permalink
Pretending we’re talking about this with storable as our example semantics
:

Ptr Void
Corresponds to a memory address you don’t want to read or write to.

Ptr () corresponds to a memory location that’s pretty boring to read /
write to


It’s definitely also true that for nontrivial c data structures , storable
isn’t the right model for how to interact with the associated pointers.

On Thu, Oct 25, 2018 at 11:22 PM Carter Schonwald <
Post by Carter Schonwald
... when is a valid pointer not going to point at byte addressable memory
on memory architectures ghc can support or target?
Post by Daniel Cartwright
Now, one could argue that `Ptr ()` isn't a lie, it sort of reads like C's
void pointer. But surely something like `Ptr Word8` is a lie, when it is
not actually a Ptr to Word8 values.
Post by Daniel Cartwright
yes, only the type and its instances should be moved as far as i'm aware.
Also, it's more than just base.
https://hackage.haskell.org/package/ghc-compact-0.1.0.0/docs/GHC-Compact-Serialized.html#t:SerializedCompact
https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-IO-Handle.html
in GHC.Stats, the foreign import "getRTSStats" has `Ptr () -> IO ()`,
this Ptr () is also a lie
These are just off the top of my head, there are more
On Thu, Oct 25, 2018 at 6:46 PM Carter Schonwald <
Post by Carter Schonwald
hrmm, what are the pieces of base that are using Ptr when they really
should be using Addr? This would help me understand what would be made
better in base :)
Post by David Feuer
We shouldn't really need to move anything into base except Addr and
its base instances.
On Oct 25, 2018 5:59 PM, "Carter Schonwald" <
Indeed. The monad transformer instances for primmonad need to live in
primmonad OR transformers to avoid orphans.
Either way, unless transformers moves into base (unlikely), no way
anything using prim monad will.
On Thu, Oct 25, 2018 at 3:34 PM Andrew Martin <
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we cannot move
the entire module since it has functions that talk about PrimMonad, and we
definitely don't want to move that into base.
On Thu, Oct 25, 2018 at 11:25 AM Daniel Cartwright <
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is used
in place of 'Addr', because in base there is no 'Addr', only 'Addr#'. The
problem lies in the fact that many of these uses of 'Ptr a' are lying; the
'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
David Feuer
2018-10-26 03:33:36 UTC
Reply
Permalink
Post by Carter Schonwald
Pretending we’re talking about this with storable as our example semantics
Ptr Void
Corresponds to a memory address you don’t want to read or write to.
This is not so easy to think about (there's not much utility in such a
type). Perhaps Ptr Void is a reasonable type for pointers known to be null
or outside the address space, but I'm not sure.
Post by Carter Schonwald
Ptr () corresponds to a memory location that’s pretty boring to read /
write to
Yes! In other words, it's *not* what people should be using for a pointer
to an arbitrary non-Haskell address. That's precisely what Addr is for.
Post by Carter Schonwald
On Thu, Oct 25, 2018 at 11:22 PM Carter Schonwald <
Post by Carter Schonwald
... when is a valid pointer not going to point at byte addressable memory
on memory architectures ghc can support or target?
Post by Daniel Cartwright
Now, one could argue that `Ptr ()` isn't a lie, it sort of reads like
C's void pointer. But surely something like `Ptr Word8` is a lie, when it
is not actually a Ptr to Word8 values.
Post by Daniel Cartwright
yes, only the type and its instances should be moved as far as i'm aware.
Also, it's more than just base.
https://hackage.haskell.org/package/ghc-compact-0.1.0.0/docs/GHC-Compact-Serialized.html#t:SerializedCompact
https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-IO-Handle.html
in GHC.Stats, the foreign import "getRTSStats" has `Ptr () -> IO ()`,
this Ptr () is also a lie
These are just off the top of my head, there are more
On Thu, Oct 25, 2018 at 6:46 PM Carter Schonwald <
Post by Carter Schonwald
hrmm, what are the pieces of base that are using Ptr when they really
should be using Addr? This would help me understand what would be made
better in base :)
Post by David Feuer
We shouldn't really need to move anything into base except Addr and
its base instances.
On Oct 25, 2018 5:59 PM, "Carter Schonwald" <
Indeed. The monad transformer instances for primmonad need to live
in primmonad OR transformers to avoid orphans.
Either way, unless transformers moves into base (unlikely), no way
anything using prim monad will.
On Thu, Oct 25, 2018 at 3:34 PM Andrew Martin <
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we cannot
move the entire module since it has functions that talk about PrimMonad,
and we definitely don't want to move that into base.
On Thu, Oct 25, 2018 at 11:25 AM Daniel Cartwright <
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is used
in place of 'Addr', because in base there is no 'Addr', only 'Addr#'. The
problem lies in the fact that many of these uses of 'Ptr a' are lying; the
'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-26 04:04:46 UTC
Reply
Permalink
Cool. What apis in base should move to use Addr from fake pointer ? Cause
just adding it in isolation seems lame!

I guess I’m just trying to say “what would the impact on base, if every
fake Ptr was moved to be Addr?” Because it’s not something which should be
done by halves.

1) what apis would be changed?

2) what internal things would be changed albeit not Api visible

3). Address arithmetic for Addr is very different from addres arithmetic on
larger than word8 size storable values, is there anything which would move
representations where the change to byte indexed would change the
calculations ?


If we can layout what the impact / scope of changes needed for these and
other considerations, I guess I’d be all for it. Assuming there’s the
corresponding interest in executing changes. (I just have this worry in my
head that it might be one of those icebergs.. like the split base effort )
On Thu, Oct 25, 2018, 11:28 PM Carter Schonwald <
Post by Carter Schonwald
Pretending we’re talking about this with storable as our example
Ptr Void
Corresponds to a memory address you don’t want to read or write to.
This is not so easy to think about (there's not much utility in such a
type). Perhaps Ptr Void is a reasonable type for pointers known to be null
or outside the address space, but I'm not sure.
Post by Carter Schonwald
Ptr () corresponds to a memory location that’s pretty boring to read /
write to
Yes! In other words, it's *not* what people should be using for a pointer
to an arbitrary non-Haskell address. That's precisely what Addr is for.
Post by Carter Schonwald
On Thu, Oct 25, 2018 at 11:22 PM Carter Schonwald <
Post by Carter Schonwald
... when is a valid pointer not going to point at byte addressable
memory on memory architectures ghc can support or target?
Post by Daniel Cartwright
Now, one could argue that `Ptr ()` isn't a lie, it sort of reads like
C's void pointer. But surely something like `Ptr Word8` is a lie, when it
is not actually a Ptr to Word8 values.
On Thu, Oct 25, 2018 at 8:11 PM Daniel Cartwright <
Post by Daniel Cartwright
yes, only the type and its instances should be moved as far as i'm aware.
Also, it's more than just base.
https://hackage.haskell.org/package/ghc-compact-0.1.0.0/docs/GHC-Compact-Serialized.html#t:SerializedCompact
https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-IO-Handle.html
in GHC.Stats, the foreign import "getRTSStats" has `Ptr () -> IO ()`,
this Ptr () is also a lie
These are just off the top of my head, there are more
On Thu, Oct 25, 2018 at 6:46 PM Carter Schonwald <
Post by Carter Schonwald
hrmm, what are the pieces of base that are using Ptr when they really
should be using Addr? This would help me understand what would be made
better in base :)
Post by David Feuer
We shouldn't really need to move anything into base except Addr and
its base instances.
On Oct 25, 2018 5:59 PM, "Carter Schonwald" <
Indeed. The monad transformer instances for primmonad need to live
in primmonad OR transformers to avoid orphans.
Either way, unless transformers moves into base (unlikely), no way
anything using prim monad will.
On Thu, Oct 25, 2018 at 3:34 PM Andrew Martin <
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we cannot
move the entire module since it has functions that talk about PrimMonad,
and we definitely don't want to move that into base.
On Thu, Oct 25, 2018 at 11:25 AM Daniel Cartwright <
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is
used in place of 'Addr', because in base there is no 'Addr', only 'Addr#'.
The problem lies in the fact that many of these uses of 'Ptr a' are lying;
the 'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-26 14:13:58 UTC
Reply
Permalink
Daniel or David, would either of you be interested/willing to do the
legwork on this patch wise (subject to sanity checking whats the impact
surface area?)

On Fri, Oct 26, 2018 at 12:04 AM Carter Schonwald <
Post by Carter Schonwald
Cool. What apis in base should move to use Addr from fake pointer ? Cause
just adding it in isolation seems lame!
I guess I’m just trying to say “what would the impact on base, if every
fake Ptr was moved to be Addr?” Because it’s not something which should be
done by halves.
1) what apis would be changed?
2) what internal things would be changed albeit not Api visible
3). Address arithmetic for Addr is very different from addres arithmetic
on larger than word8 size storable values, is there anything which would
move representations where the change to byte indexed would change the
calculations ?
If we can layout what the impact / scope of changes needed for these and
other considerations, I guess I’d be all for it. Assuming there’s the
corresponding interest in executing changes. (I just have this worry in my
head that it might be one of those icebergs.. like the split base effort )
On Thu, Oct 25, 2018, 11:28 PM Carter Schonwald <
Post by Carter Schonwald
Pretending we’re talking about this with storable as our example
Ptr Void
Corresponds to a memory address you don’t want to read or write to.
This is not so easy to think about (there's not much utility in such a
type). Perhaps Ptr Void is a reasonable type for pointers known to be null
or outside the address space, but I'm not sure.
Post by Carter Schonwald
Ptr () corresponds to a memory location that’s pretty boring to read /
write to
Yes! In other words, it's *not* what people should be using for a pointer
to an arbitrary non-Haskell address. That's precisely what Addr is for.
Post by Carter Schonwald
On Thu, Oct 25, 2018 at 11:22 PM Carter Schonwald <
Post by Carter Schonwald
... when is a valid pointer not going to point at byte addressable
memory on memory architectures ghc can support or target?
On Thu, Oct 25, 2018 at 8:27 PM Daniel Cartwright <
Post by Daniel Cartwright
Now, one could argue that `Ptr ()` isn't a lie, it sort of reads like
C's void pointer. But surely something like `Ptr Word8` is a lie, when it
is not actually a Ptr to Word8 values.
On Thu, Oct 25, 2018 at 8:11 PM Daniel Cartwright <
Post by Daniel Cartwright
yes, only the type and its instances should be moved as far as i'm aware.
Also, it's more than just base.
https://hackage.haskell.org/package/ghc-compact-0.1.0.0/docs/GHC-Compact-Serialized.html#t:SerializedCompact
https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-IO-Handle.html
in GHC.Stats, the foreign import "getRTSStats" has `Ptr () -> IO ()`,
this Ptr () is also a lie
These are just off the top of my head, there are more
On Thu, Oct 25, 2018 at 6:46 PM Carter Schonwald <
Post by Carter Schonwald
hrmm, what are the pieces of base that are using Ptr when they
really should be using Addr? This would help me understand what would be
made better in base :)
Post by David Feuer
We shouldn't really need to move anything into base except Addr and
its base instances.
On Oct 25, 2018 5:59 PM, "Carter Schonwald" <
Indeed. The monad transformer instances for primmonad need to live
in primmonad OR transformers to avoid orphans.
Either way, unless transformers moves into base (unlikely), no way
anything using prim monad will.
On Thu, Oct 25, 2018 at 3:34 PM Andrew Martin <
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we cannot
move the entire module since it has functions that talk about PrimMonad,
and we definitely don't want to move that into base.
On Thu, Oct 25, 2018 at 11:25 AM Daniel Cartwright <
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is
used in place of 'Addr', because in base there is no 'Addr', only 'Addr#'.
The problem lies in the fact that many of these uses of 'Ptr a' are lying;
the 'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Daniel Cartwright
2018-10-26 14:15:05 UTC
Reply
Permalink
I would, yeah. Should the next version of `primitive` just re-export `Addr`
from base in `Data.Primitive.Addr`?

On Fri, Oct 26, 2018 at 10:14 AM Carter Schonwald <
Post by Carter Schonwald
Daniel or David, would either of you be interested/willing to do the
legwork on this patch wise (subject to sanity checking whats the impact
surface area?)
On Fri, Oct 26, 2018 at 12:04 AM Carter Schonwald <
Post by Carter Schonwald
Cool. What apis in base should move to use Addr from fake pointer ? Cause
just adding it in isolation seems lame!
I guess I’m just trying to say “what would the impact on base, if every
fake Ptr was moved to be Addr?” Because it’s not something which should be
done by halves.
1) what apis would be changed?
2) what internal things would be changed albeit not Api visible
3). Address arithmetic for Addr is very different from addres arithmetic
on larger than word8 size storable values, is there anything which would
move representations where the change to byte indexed would change the
calculations ?
If we can layout what the impact / scope of changes needed for these and
other considerations, I guess I’d be all for it. Assuming there’s the
corresponding interest in executing changes. (I just have this worry in my
head that it might be one of those icebergs.. like the split base effort )
On Thu, Oct 25, 2018, 11:28 PM Carter Schonwald <
Post by Carter Schonwald
Pretending we’re talking about this with storable as our example
Ptr Void
Corresponds to a memory address you don’t want to read or write to.
This is not so easy to think about (there's not much utility in such a
type). Perhaps Ptr Void is a reasonable type for pointers known to be null
or outside the address space, but I'm not sure.
Post by Carter Schonwald
Ptr () corresponds to a memory location that’s pretty boring to read /
write to
Yes! In other words, it's *not* what people should be using for a
pointer to an arbitrary non-Haskell address. That's precisely what Addr is
for.
Post by Carter Schonwald
On Thu, Oct 25, 2018 at 11:22 PM Carter Schonwald <
Post by Carter Schonwald
... when is a valid pointer not going to point at byte addressable
memory on memory architectures ghc can support or target?
On Thu, Oct 25, 2018 at 8:27 PM Daniel Cartwright <
Post by Daniel Cartwright
Now, one could argue that `Ptr ()` isn't a lie, it sort of reads like
C's void pointer. But surely something like `Ptr Word8` is a lie, when it
is not actually a Ptr to Word8 values.
On Thu, Oct 25, 2018 at 8:11 PM Daniel Cartwright <
Post by Daniel Cartwright
yes, only the type and its instances should be moved as far as i'm aware.
Also, it's more than just base.
https://hackage.haskell.org/package/ghc-compact-0.1.0.0/docs/GHC-Compact-Serialized.html#t:SerializedCompact
https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-IO-Handle.html
in GHC.Stats, the foreign import "getRTSStats" has `Ptr () -> IO
()`, this Ptr () is also a lie
These are just off the top of my head, there are more
On Thu, Oct 25, 2018 at 6:46 PM Carter Schonwald <
Post by Carter Schonwald
hrmm, what are the pieces of base that are using Ptr when they
really should be using Addr? This would help me understand what would be
made better in base :)
Post by David Feuer
We shouldn't really need to move anything into base except Addr
and its base instances.
On Oct 25, 2018 5:59 PM, "Carter Schonwald" <
Indeed. The monad transformer instances for primmonad need to
live in primmonad OR transformers to avoid orphans.
Either way, unless transformers moves into base (unlikely), no way
anything using prim monad will.
On Thu, Oct 25, 2018 at 3:34 PM Andrew Martin <
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we cannot
move the entire module since it has functions that talk about PrimMonad,
and we definitely don't want to move that into base.
On Thu, Oct 25, 2018 at 11:25 AM Daniel Cartwright <
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is
used in place of 'Addr', because in base there is no 'Addr', only 'Addr#'.
The problem lies in the fact that many of these uses of 'Ptr a' are lying;
the 'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Daniel Cartwright
2018-10-26 15:00:55 UTC
Reply
Permalink
Also, where in base should Addr go?
Post by Daniel Cartwright
I would, yeah. Should the next version of `primitive` just re-export
`Addr` from base in `Data.Primitive.Addr`?
On Fri, Oct 26, 2018 at 10:14 AM Carter Schonwald <
Post by Carter Schonwald
Daniel or David, would either of you be interested/willing to do the
legwork on this patch wise (subject to sanity checking whats the impact
surface area?)
On Fri, Oct 26, 2018 at 12:04 AM Carter Schonwald <
Post by Carter Schonwald
Cool. What apis in base should move to use Addr from fake pointer ?
Cause just adding it in isolation seems lame!
I guess I’m just trying to say “what would the impact on base, if every
fake Ptr was moved to be Addr?” Because it’s not something which should be
done by halves.
1) what apis would be changed?
2) what internal things would be changed albeit not Api visible
3). Address arithmetic for Addr is very different from addres arithmetic
on larger than word8 size storable values, is there anything which would
move representations where the change to byte indexed would change the
calculations ?
If we can layout what the impact / scope of changes needed for these and
other considerations, I guess I’d be all for it. Assuming there’s the
corresponding interest in executing changes. (I just have this worry in my
head that it might be one of those icebergs.. like the split base effort )
On Thu, Oct 25, 2018, 11:28 PM Carter Schonwald <
Post by Carter Schonwald
Pretending we’re talking about this with storable as our example
Ptr Void
Corresponds to a memory address you don’t want to read or write to.
This is not so easy to think about (there's not much utility in such a
type). Perhaps Ptr Void is a reasonable type for pointers known to be null
or outside the address space, but I'm not sure.
Post by Carter Schonwald
Ptr () corresponds to a memory location that’s pretty boring to read /
write to
Yes! In other words, it's *not* what people should be using for a
pointer to an arbitrary non-Haskell address. That's precisely what Addr is
for.
Post by Carter Schonwald
On Thu, Oct 25, 2018 at 11:22 PM Carter Schonwald <
Post by Carter Schonwald
... when is a valid pointer not going to point at byte addressable
memory on memory architectures ghc can support or target?
On Thu, Oct 25, 2018 at 8:27 PM Daniel Cartwright <
Post by Daniel Cartwright
Now, one could argue that `Ptr ()` isn't a lie, it sort of reads
like C's void pointer. But surely something like `Ptr Word8` is a lie, when
it is not actually a Ptr to Word8 values.
On Thu, Oct 25, 2018 at 8:11 PM Daniel Cartwright <
Post by Daniel Cartwright
yes, only the type and its instances should be moved as far as i'm aware.
Also, it's more than just base.
https://hackage.haskell.org/package/ghc-compact-0.1.0.0/docs/GHC-Compact-Serialized.html#t:SerializedCompact
https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-IO-Handle.html
in GHC.Stats, the foreign import "getRTSStats" has `Ptr () -> IO
()`, this Ptr () is also a lie
These are just off the top of my head, there are more
On Thu, Oct 25, 2018 at 6:46 PM Carter Schonwald <
Post by Carter Schonwald
hrmm, what are the pieces of base that are using Ptr when they
really should be using Addr? This would help me understand what would be
made better in base :)
Post by David Feuer
We shouldn't really need to move anything into base except Addr
and its base instances.
On Oct 25, 2018 5:59 PM, "Carter Schonwald" <
Indeed. The monad transformer instances for primmonad need to
live in primmonad OR transformers to avoid orphans.
Either way, unless transformers moves into base (unlikely), no
way anything using prim monad will.
On Thu, Oct 25, 2018 at 3:34 PM Andrew Martin <
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we cannot
move the entire module since it has functions that talk about PrimMonad,
and we definitely don't want to move that into base.
On Thu, Oct 25, 2018 at 11:25 AM Daniel Cartwright <
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is
used in place of 'Addr', because in base there is no 'Addr', only 'Addr#'.
The problem lies in the fact that many of these uses of 'Ptr a' are lying;
the 'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-26 16:18:35 UTC
Reply
Permalink
Before we bike shed these details, let’s evaluate / document the pieces of
base that should also be moved to using Addr. Though that module where

1) What exported types / data definitions / functions will have changes ?

2) what internal apis need to change?

as a lower bound estimate of work surface area, i grepped for "Ptr ()" and
"Addr#" in a fresh recursive clone of ghc at
commit 503514b94f8dc7bd9eab5392206649aee45f140b,
limiting my search to .hs and .hsc files

THERES A LOT of uses of Ptr (), and its siblings StablePtr () and RemotePtr
() , The latter two dont have a simple Addr# underneath,

heres the list of files that match that search rg 'Ptr \(\)' --type
haskell -c

ghc/GHCi/Leak.hs:1
utils/hsc2hs/Main.hs:1
utils/runghc/Main.hs:1
compiler/ghci/GHCi.hs:4
compiler/ghci/ByteCodeLink.hs:3
compiler/ghci/ByteCodeGen.hs:4
compiler/ghci/ByteCodeTypes.hs:1
compiler/ghci/ByteCodeAsm.hs:2
compiler/main/HscTypes.hs:1
libraries/ghci/GHCi/ObjLink.hs:3
libraries/ghci/GHCi/StaticPtrTable.hs:1
libraries/ghci/GHCi/ResolvedBCO.hs:1
libraries/ghci/GHCi/RemoteTypes.hs:2
libraries/ghci/GHCi/Run.hs:2
libraries/ghci/GHCi/Message.hs:5
libraries/base/GHC/Stable.hs:2
libraries/base/GHC/StaticPtr.hs:1
libraries/base/GHC/Generics.hs:2
libraries/base/GHC/TopHandler.hs:1
libraries/base/GHC/Windows.hs:1
libraries/base/tests/dynamic002.hs:2
utils/haddock/haddock-api/src/Haddock.hs:1
libraries/array/Data/Array/IO.hs:2
libraries/base/Foreign/Marshal/Pool.hs:1
libraries/bytestring/Data/ByteString/Builder/Extra.hs:1
libraries/base/GHC/IO/Handle/Text.hs:1
testsuite/tests/rts/T7160.hs:1
testsuite/tests/rts/overflow3.hs:1
testsuite/tests/rts/overflow2.hs:1
testsuite/tests/rts/T5250.hs:1
testsuite/tests/rts/T10296b.hs:2
testsuite/tests/th/T3319.hs:1
testsuite/tests/th/TH_foreignInterruptible.hs:1
testsuite/tests/th/TH_foreignCallingConventions.hs:1
libraries/Cabal/cabal-install/Distribution/Client/Win32SelfUpgrade.hs:1
libraries/Cabal/Cabal/Distribution/Simple/InstallDirs.hs:2
testsuite/tests/llvm/should_compile/T5486.hs:2
testsuite/tests/codeGen/should_run/cgrun070.hs:5
testsuite/tests/codeGen/should_run/cgrun026.hs:3
testsuite/tests/primops/should_run/T4442.hs:1
testsuite/tests/ffi/should_fail/T7243.hs:1
testsuite/tests/ffi/should_fail/T3066.hs:1
testsuite/tests/ffi/should_compile/cc009.hs:1
testsuite/tests/ffi/should_run/ffi021.hs:1
testsuite/tests/typecheck/should_compile/T7408.hs:1
libraries/Cabal/cabal-install/Distribution/Client/Compat/ExecutablePath.hs:1
libraries/Cabal/Cabal/Distribution/Simple/Build/PathsModule.hs:1
libraries/time/lib/Data/Time/Clock/Internal/CTimeval.hs:1
testsuite/tests/rename/should_compile/T3103/Foreign/Ptr.hs:1

likewise the locations where Addr# comes up are as follows (some of these
perhaps should be an Addr? )

$ rg 'Addr#' --type haskell -c
utils/genprimopcode/Main.hs:2
ghc/GHCi/Leak.hs:2
compiler/cmm/CmmMachOp.hs:1
compiler/cmm/CmmUtils.hs:1
compiler/specialise/Rules.hs:2
compiler/basicTypes/MkId.hs:2
compiler/basicTypes/Literal.hs:6
compiler/basicTypes/Unique.hs:2
compiler/utils/StringBuffer.hs:1
compiler/utils/FastString.hs:4
compiler/utils/Encoding.hs:9
compiler/codeGen/StgCmmPrim.hs:3
compiler/coreSyn/MkCore.hs:5
compiler/coreSyn/CoreLint.hs:2
compiler/coreSyn/CoreSyn.hs:4
compiler/coreSyn/CorePrep.hs:1
compiler/stranal/WwLib.hs:1
compiler/simplCore/CSE.hs:1
compiler/simplCore/Simplify.hs:2
compiler/deSugar/DsExpr.hs:1
compiler/typecheck/TcGenDeriv.hs:5
compiler/prelude/ForeignCall.hs:1
compiler/prelude/PrelNames.hs:1
compiler/prelude/TysPrim.hs:1
compiler/ghci/ByteCodeGen.hs:8
libraries/bytestring/tests/revcomp.hs:1
libraries/bytestring/Data/ByteString.hs:5
libraries/ghc-heap/tests/heap_all.hs:1
libraries/ghc-prim/GHC/CString.hs:17
libraries/ghc-prim/GHC/Classes.hs:1
libraries/ghc-prim/GHC/Types.hs:3
libraries/ghci/GHCi/BinaryArray.hs:1
libraries/ghci/GHCi/CreateBCO.hs:5
libraries/base/codepages/MakeTable.hs:1
libraries/base/GHC/Ptr.hs:8
libraries/base/GHC/Generics.hs:5
libraries/base/GHC/Storable.hs:32
libraries/base/GHC/ForeignPtr.hs:6
libraries/base/Foreign/Ptr.hs:2
libraries/bytestring/Data/ByteString/Unsafe.hs:6
libraries/bytestring/Data/ByteString/Internal.hs:7
libraries/ghc-heap/GHC/Exts/Heap.hs:1
libraries/text/Data/Text/Show.hs:2
libraries/text/Data/Text/Lazy.hs:2
libraries/containers/Data/IntSet/Internal.hs:4
libraries/ghc-compact/GHC/Compact/Serialized.hs:11
libraries/base/GHC/IO/Exception.hs:1
libraries/base/Data/Typeable/Internal.hs:3
libraries/base/Control/Exception/Base.hs:1
utils/haddock/html-test/src/Ticket112.hs:1
testsuite/tests/rts/T8242.hs:19
testsuite/tests/ghci.debugger/HappyTest.hs:3
testsuite/tests/arityanal/Main.hs:3
testsuite/tests/th/TH_StringPrimL.hs:2
testsuite/tests/th/T1830_3a.hs:2
libraries/template-haskell/Language/Haskell/TH/Syntax.hs:1
libraries/bytestring/Data/ByteString/Short/Internal.hs:16
libraries/integer-gmp/src/GHC/Integer/Type.hs:11
libraries/base/GHC/IO/Encoding/CodePage.hs:3
libraries/Cabal/Cabal/Distribution/Parsec/Lexer.hs:9
testsuite/tests/generics/GEq/GEq1A.hs:1
testsuite/tests/generics/GEq/GEq1.hs:2
testsuite/tests/codeGen/should_compile/cg008.hs:1
testsuite/tests/codeGen/should_run/cgrun070.hs:4
testsuite/tests/codeGen/should_run/T9577.hs:1
testsuite/tests/codeGen/should_run/cgrun066.hs:1
testsuite/tests/codeGen/should_run/cgrun026.hs:2
testsuite/tests/codeGen/should_run/T2080.hs:2
testsuite/tests/codeGen/should_run/T9577_A.hs:1
testsuite/tests/primops/should_run/T4442.hs:4
testsuite/tests/simplCore/should_compile/T13367.hs:1
testsuite/tests/simplCore/should_compile/T13155.hs:2
testsuite/tests/simplCore/should_compile/T14779a.hs:1
testsuite/tests/simplCore/should_compile/T14779b.hs:2
testsuite/tests/simplCore/should_compile/spec001.hs:1
testsuite/tests/lib/integer/integerGmpInternals.hs:9
testsuite/tests/perf/compiler/T14683.hs:3
testsuite/tests/ghci/should_run/T2589.hs:1
libraries/integer-gmp/src/GHC/Integer/GMP/Internals.hs:7
libraries/text/Data/Text/Internal/Fusion/Common.hs:3
libraries/base/GHC/IO/Encoding/CodePage/Table.hs:1
Post by Daniel Cartwright
Also, where in base should Addr go?
Post by Daniel Cartwright
I would, yeah. Should the next version of `primitive` just re-export
`Addr` from base in `Data.Primitive.Addr`?
On Fri, Oct 26, 2018 at 10:14 AM Carter Schonwald <
Post by Carter Schonwald
Daniel or David, would either of you be interested/willing to do the
legwork on this patch wise (subject to sanity checking whats the impact
surface area?)
On Fri, Oct 26, 2018 at 12:04 AM Carter Schonwald <
Post by Carter Schonwald
Cool. What apis in base should move to use Addr from fake pointer ?
Cause just adding it in isolation seems lame!
I guess I’m just trying to say “what would the impact on base, if every
fake Ptr was moved to be Addr?” Because it’s not something which should be
done by halves.
1) what apis would be changed?
2) what internal things would be changed albeit not Api visible
3). Address arithmetic for Addr is very different from addres
arithmetic on larger than word8 size storable values, is there anything
which would move representations where the change to byte indexed would
change the calculations ?
If we can layout what the impact / scope of changes needed for these
and other considerations, I guess I’d be all for it. Assuming there’s the
corresponding interest in executing changes. (I just have this worry in my
head that it might be one of those icebergs.. like the split base effort )
On Thu, Oct 25, 2018, 11:28 PM Carter Schonwald <
Post by Carter Schonwald
Pretending we’re talking about this with storable as our example
Ptr Void
Corresponds to a memory address you don’t want to read or write to.
This is not so easy to think about (there's not much utility in such a
type). Perhaps Ptr Void is a reasonable type for pointers known to be null
or outside the address space, but I'm not sure.
Post by Carter Schonwald
Ptr () corresponds to a memory location that’s pretty boring to read
/ write to
Yes! In other words, it's *not* what people should be using for a
pointer to an arbitrary non-Haskell address. That's precisely what Addr is
for.
Post by Carter Schonwald
On Thu, Oct 25, 2018 at 11:22 PM Carter Schonwald <
Post by Carter Schonwald
... when is a valid pointer not going to point at byte addressable
memory on memory architectures ghc can support or target?
On Thu, Oct 25, 2018 at 8:27 PM Daniel Cartwright <
Post by Daniel Cartwright
Now, one could argue that `Ptr ()` isn't a lie, it sort of reads
like C's void pointer. But surely something like `Ptr Word8` is a lie, when
it is not actually a Ptr to Word8 values.
On Thu, Oct 25, 2018 at 8:11 PM Daniel Cartwright <
Post by Daniel Cartwright
yes, only the type and its instances should be moved as far as i'm aware.
Also, it's more than just base.
https://hackage.haskell.org/package/ghc-compact-0.1.0.0/docs/GHC-Compact-Serialized.html#t:SerializedCompact
https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-IO-Handle.html
in GHC.Stats, the foreign import "getRTSStats" has `Ptr () -> IO
()`, this Ptr () is also a lie
These are just off the top of my head, there are more
On Thu, Oct 25, 2018 at 6:46 PM Carter Schonwald <
Post by Carter Schonwald
hrmm, what are the pieces of base that are using Ptr when they
really should be using Addr? This would help me understand what would be
made better in base :)
On Thu, Oct 25, 2018 at 6:19 PM David Feuer <
Post by David Feuer
We shouldn't really need to move anything into base except Addr
and its base instances.
On Oct 25, 2018 5:59 PM, "Carter Schonwald" <
Indeed. The monad transformer instances for primmonad need to
live in primmonad OR transformers to avoid orphans.
Either way, unless transformers moves into base (unlikely), no
way anything using prim monad will.
On Thu, Oct 25, 2018 at 3:34 PM Andrew Martin <
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we
cannot move the entire module since it has functions that talk about
PrimMonad, and we definitely don't want to move that into base.
On Thu, Oct 25, 2018 at 11:25 AM Daniel Cartwright <
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is
used in place of 'Addr', because in base there is no 'Addr', only 'Addr#'.
The problem lies in the fact that many of these uses of 'Ptr a' are lying;
the 'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-26 16:23:22 UTC
Reply
Permalink
granted most of the Addr# sites dont matter

a related issue is what operations WOULD be added for Addr?

maybe just memcopy friends plus address arithmetic, plus a mapper from/to
Ptr a?

does it simply become a byte size step sibling to Ptr a that put in
Foreign.Ptr?

On Fri, Oct 26, 2018 at 12:18 PM Carter Schonwald <
Post by Carter Schonwald
Before we bike shed these details, let’s evaluate / document the pieces of
base that should also be moved to using Addr. Though that module where
1) What exported types / data definitions / functions will have changes ?
2) what internal apis need to change?
as a lower bound estimate of work surface area, i grepped for "Ptr ()"
and "Addr#" in a fresh recursive clone of ghc at
commit 503514b94f8dc7bd9eab5392206649aee45f140b,
limiting my search to .hs and .hsc files
THERES A LOT of uses of Ptr (), and its siblings StablePtr () and
RemotePtr () , The latter two dont have a simple Addr# underneath,
heres the list of files that match that search rg 'Ptr \(\)' --type
haskell -c
ghc/GHCi/Leak.hs:1
utils/hsc2hs/Main.hs:1
utils/runghc/Main.hs:1
compiler/ghci/GHCi.hs:4
compiler/ghci/ByteCodeLink.hs:3
compiler/ghci/ByteCodeGen.hs:4
compiler/ghci/ByteCodeTypes.hs:1
compiler/ghci/ByteCodeAsm.hs:2
compiler/main/HscTypes.hs:1
libraries/ghci/GHCi/ObjLink.hs:3
libraries/ghci/GHCi/StaticPtrTable.hs:1
libraries/ghci/GHCi/ResolvedBCO.hs:1
libraries/ghci/GHCi/RemoteTypes.hs:2
libraries/ghci/GHCi/Run.hs:2
libraries/ghci/GHCi/Message.hs:5
libraries/base/GHC/Stable.hs:2
libraries/base/GHC/StaticPtr.hs:1
libraries/base/GHC/Generics.hs:2
libraries/base/GHC/TopHandler.hs:1
libraries/base/GHC/Windows.hs:1
libraries/base/tests/dynamic002.hs:2
utils/haddock/haddock-api/src/Haddock.hs:1
libraries/array/Data/Array/IO.hs:2
libraries/base/Foreign/Marshal/Pool.hs:1
libraries/bytestring/Data/ByteString/Builder/Extra.hs:1
libraries/base/GHC/IO/Handle/Text.hs:1
testsuite/tests/rts/T7160.hs:1
testsuite/tests/rts/overflow3.hs:1
testsuite/tests/rts/overflow2.hs:1
testsuite/tests/rts/T5250.hs:1
testsuite/tests/rts/T10296b.hs:2
testsuite/tests/th/T3319.hs:1
testsuite/tests/th/TH_foreignInterruptible.hs:1
testsuite/tests/th/TH_foreignCallingConventions.hs:1
libraries/Cabal/cabal-install/Distribution/Client/Win32SelfUpgrade.hs:1
libraries/Cabal/Cabal/Distribution/Simple/InstallDirs.hs:2
testsuite/tests/llvm/should_compile/T5486.hs:2
testsuite/tests/codeGen/should_run/cgrun070.hs:5
testsuite/tests/codeGen/should_run/cgrun026.hs:3
testsuite/tests/primops/should_run/T4442.hs:1
testsuite/tests/ffi/should_fail/T7243.hs:1
testsuite/tests/ffi/should_fail/T3066.hs:1
testsuite/tests/ffi/should_compile/cc009.hs:1
testsuite/tests/ffi/should_run/ffi021.hs:1
testsuite/tests/typecheck/should_compile/T7408.hs:1
libraries/Cabal/cabal-install/Distribution/Client/Compat/ExecutablePath.hs:1
libraries/Cabal/Cabal/Distribution/Simple/Build/PathsModule.hs:1
libraries/time/lib/Data/Time/Clock/Internal/CTimeval.hs:1
testsuite/tests/rename/should_compile/T3103/Foreign/Ptr.hs:1
likewise the locations where Addr# comes up are as follows (some of these
perhaps should be an Addr? )
$ rg 'Addr#' --type haskell -c
utils/genprimopcode/Main.hs:2
ghc/GHCi/Leak.hs:2
compiler/cmm/CmmMachOp.hs:1
compiler/cmm/CmmUtils.hs:1
compiler/specialise/Rules.hs:2
compiler/basicTypes/MkId.hs:2
compiler/basicTypes/Literal.hs:6
compiler/basicTypes/Unique.hs:2
compiler/utils/StringBuffer.hs:1
compiler/utils/FastString.hs:4
compiler/utils/Encoding.hs:9
compiler/codeGen/StgCmmPrim.hs:3
compiler/coreSyn/MkCore.hs:5
compiler/coreSyn/CoreLint.hs:2
compiler/coreSyn/CoreSyn.hs:4
compiler/coreSyn/CorePrep.hs:1
compiler/stranal/WwLib.hs:1
compiler/simplCore/CSE.hs:1
compiler/simplCore/Simplify.hs:2
compiler/deSugar/DsExpr.hs:1
compiler/typecheck/TcGenDeriv.hs:5
compiler/prelude/ForeignCall.hs:1
compiler/prelude/PrelNames.hs:1
compiler/prelude/TysPrim.hs:1
compiler/ghci/ByteCodeGen.hs:8
libraries/bytestring/tests/revcomp.hs:1
libraries/bytestring/Data/ByteString.hs:5
libraries/ghc-heap/tests/heap_all.hs:1
libraries/ghc-prim/GHC/CString.hs:17
libraries/ghc-prim/GHC/Classes.hs:1
libraries/ghc-prim/GHC/Types.hs:3
libraries/ghci/GHCi/BinaryArray.hs:1
libraries/ghci/GHCi/CreateBCO.hs:5
libraries/base/codepages/MakeTable.hs:1
libraries/base/GHC/Ptr.hs:8
libraries/base/GHC/Generics.hs:5
libraries/base/GHC/Storable.hs:32
libraries/base/GHC/ForeignPtr.hs:6
libraries/base/Foreign/Ptr.hs:2
libraries/bytestring/Data/ByteString/Unsafe.hs:6
libraries/bytestring/Data/ByteString/Internal.hs:7
libraries/ghc-heap/GHC/Exts/Heap.hs:1
libraries/text/Data/Text/Show.hs:2
libraries/text/Data/Text/Lazy.hs:2
libraries/containers/Data/IntSet/Internal.hs:4
libraries/ghc-compact/GHC/Compact/Serialized.hs:11
libraries/base/GHC/IO/Exception.hs:1
libraries/base/Data/Typeable/Internal.hs:3
libraries/base/Control/Exception/Base.hs:1
utils/haddock/html-test/src/Ticket112.hs:1
testsuite/tests/rts/T8242.hs:19
testsuite/tests/ghci.debugger/HappyTest.hs:3
testsuite/tests/arityanal/Main.hs:3
testsuite/tests/th/TH_StringPrimL.hs:2
testsuite/tests/th/T1830_3a.hs:2
libraries/template-haskell/Language/Haskell/TH/Syntax.hs:1
libraries/bytestring/Data/ByteString/Short/Internal.hs:16
libraries/integer-gmp/src/GHC/Integer/Type.hs:11
libraries/base/GHC/IO/Encoding/CodePage.hs:3
libraries/Cabal/Cabal/Distribution/Parsec/Lexer.hs:9
testsuite/tests/generics/GEq/GEq1A.hs:1
testsuite/tests/generics/GEq/GEq1.hs:2
testsuite/tests/codeGen/should_compile/cg008.hs:1
testsuite/tests/codeGen/should_run/cgrun070.hs:4
testsuite/tests/codeGen/should_run/T9577.hs:1
testsuite/tests/codeGen/should_run/cgrun066.hs:1
testsuite/tests/codeGen/should_run/cgrun026.hs:2
testsuite/tests/codeGen/should_run/T2080.hs:2
testsuite/tests/codeGen/should_run/T9577_A.hs:1
testsuite/tests/primops/should_run/T4442.hs:4
testsuite/tests/simplCore/should_compile/T13367.hs:1
testsuite/tests/simplCore/should_compile/T13155.hs:2
testsuite/tests/simplCore/should_compile/T14779a.hs:1
testsuite/tests/simplCore/should_compile/T14779b.hs:2
testsuite/tests/simplCore/should_compile/spec001.hs:1
testsuite/tests/lib/integer/integerGmpInternals.hs:9
testsuite/tests/perf/compiler/T14683.hs:3
testsuite/tests/ghci/should_run/T2589.hs:1
libraries/integer-gmp/src/GHC/Integer/GMP/Internals.hs:7
libraries/text/Data/Text/Internal/Fusion/Common.hs:3
libraries/base/GHC/IO/Encoding/CodePage/Table.hs:1
Post by Daniel Cartwright
Also, where in base should Addr go?
Post by Daniel Cartwright
I would, yeah. Should the next version of `primitive` just re-export
`Addr` from base in `Data.Primitive.Addr`?
On Fri, Oct 26, 2018 at 10:14 AM Carter Schonwald <
Post by Carter Schonwald
Daniel or David, would either of you be interested/willing to do the
legwork on this patch wise (subject to sanity checking whats the impact
surface area?)
On Fri, Oct 26, 2018 at 12:04 AM Carter Schonwald <
Post by Carter Schonwald
Cool. What apis in base should move to use Addr from fake pointer ?
Cause just adding it in isolation seems lame!
I guess I’m just trying to say “what would the impact on base, if
every fake Ptr was moved to be Addr?” Because it’s not something which
should be done by halves.
1) what apis would be changed?
2) what internal things would be changed albeit not Api visible
3). Address arithmetic for Addr is very different from addres
arithmetic on larger than word8 size storable values, is there anything
which would move representations where the change to byte indexed would
change the calculations ?
If we can layout what the impact / scope of changes needed for these
and other considerations, I guess I’d be all for it. Assuming there’s the
corresponding interest in executing changes. (I just have this worry in my
head that it might be one of those icebergs.. like the split base effort )
On Thu, Oct 25, 2018, 11:28 PM Carter Schonwald <
Post by Carter Schonwald
Pretending we’re talking about this with storable as our example
Ptr Void
Corresponds to a memory address you don’t want to read or write to.
This is not so easy to think about (there's not much utility in such
a type). Perhaps Ptr Void is a reasonable type for pointers known to be
null or outside the address space, but I'm not sure.
Post by Carter Schonwald
Ptr () corresponds to a memory location that’s pretty boring to read
/ write to
Yes! In other words, it's *not* what people should be using for a
pointer to an arbitrary non-Haskell address. That's precisely what Addr is
for.
Post by Carter Schonwald
On Thu, Oct 25, 2018 at 11:22 PM Carter Schonwald <
Post by Carter Schonwald
... when is a valid pointer not going to point at byte addressable
memory on memory architectures ghc can support or target?
On Thu, Oct 25, 2018 at 8:27 PM Daniel Cartwright <
Post by Daniel Cartwright
Now, one could argue that `Ptr ()` isn't a lie, it sort of reads
like C's void pointer. But surely something like `Ptr Word8` is a lie, when
it is not actually a Ptr to Word8 values.
On Thu, Oct 25, 2018 at 8:11 PM Daniel Cartwright <
Post by Daniel Cartwright
yes, only the type and its instances should be moved as far as i'm aware.
Also, it's more than just base.
https://hackage.haskell.org/package/ghc-compact-0.1.0.0/docs/GHC-Compact-Serialized.html#t:SerializedCompact
https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-IO-Handle.html
in GHC.Stats, the foreign import "getRTSStats" has `Ptr () -> IO
()`, this Ptr () is also a lie
These are just off the top of my head, there are more
On Thu, Oct 25, 2018 at 6:46 PM Carter Schonwald <
Post by Carter Schonwald
hrmm, what are the pieces of base that are using Ptr when they
really should be using Addr? This would help me understand what would be
made better in base :)
On Thu, Oct 25, 2018 at 6:19 PM David Feuer <
Post by David Feuer
We shouldn't really need to move anything into base except Addr
and its base instances.
On Oct 25, 2018 5:59 PM, "Carter Schonwald" <
Indeed. The monad transformer instances for primmonad need to
live in primmonad OR transformers to avoid orphans.
Either way, unless transformers moves into base (unlikely), no
way anything using prim monad will.
On Thu, Oct 25, 2018 at 3:34 PM Andrew Martin <
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we
cannot move the entire module since it has functions that talk about
PrimMonad, and we definitely don't want to move that into base.
On Thu, Oct 25, 2018 at 11:25 AM Daniel Cartwright <
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a'
is used in place of 'Addr', because in base there is no 'Addr', only
'Addr#'. The problem lies in the fact that many of these uses of 'Ptr a'
are lying; the 'a' value is meaningless. Authors of functions therein have
used things like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not
mean what they say they mean - they're just Addr. There are probably other
motivations for this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-26 17:08:47 UTC
Reply
Permalink
On the flip side we could just add data Addr ... to foreign .ptr or a child
/ sibling module like System.Mem.Address and defer the associated cleanup

I kinda like the idea of System.Mem.Address,

i put a strawman change set on phab https://phabricator.haskell.org/D5268

On Fri, Oct 26, 2018 at 12:23 PM Carter Schonwald <
Post by Carter Schonwald
granted most of the Addr# sites dont matter
a related issue is what operations WOULD be added for Addr?
maybe just memcopy friends plus address arithmetic, plus a mapper from/to
Ptr a?
does it simply become a byte size step sibling to Ptr a that put in
Foreign.Ptr?
On Fri, Oct 26, 2018 at 12:18 PM Carter Schonwald <
Post by Carter Schonwald
Before we bike shed these details, let’s evaluate / document the pieces
of base that should also be moved to using Addr. Though that module where
1) What exported types / data definitions / functions will have changes ?
2) what internal apis need to change?
as a lower bound estimate of work surface area, i grepped for "Ptr ()"
and "Addr#" in a fresh recursive clone of ghc at
commit 503514b94f8dc7bd9eab5392206649aee45f140b,
limiting my search to .hs and .hsc files
THERES A LOT of uses of Ptr (), and its siblings StablePtr () and
RemotePtr () , The latter two dont have a simple Addr# underneath,
heres the list of files that match that search rg 'Ptr \(\)' --type
haskell -c
ghc/GHCi/Leak.hs:1
utils/hsc2hs/Main.hs:1
utils/runghc/Main.hs:1
compiler/ghci/GHCi.hs:4
compiler/ghci/ByteCodeLink.hs:3
compiler/ghci/ByteCodeGen.hs:4
compiler/ghci/ByteCodeTypes.hs:1
compiler/ghci/ByteCodeAsm.hs:2
compiler/main/HscTypes.hs:1
libraries/ghci/GHCi/ObjLink.hs:3
libraries/ghci/GHCi/StaticPtrTable.hs:1
libraries/ghci/GHCi/ResolvedBCO.hs:1
libraries/ghci/GHCi/RemoteTypes.hs:2
libraries/ghci/GHCi/Run.hs:2
libraries/ghci/GHCi/Message.hs:5
libraries/base/GHC/Stable.hs:2
libraries/base/GHC/StaticPtr.hs:1
libraries/base/GHC/Generics.hs:2
libraries/base/GHC/TopHandler.hs:1
libraries/base/GHC/Windows.hs:1
libraries/base/tests/dynamic002.hs:2
utils/haddock/haddock-api/src/Haddock.hs:1
libraries/array/Data/Array/IO.hs:2
libraries/base/Foreign/Marshal/Pool.hs:1
libraries/bytestring/Data/ByteString/Builder/Extra.hs:1
libraries/base/GHC/IO/Handle/Text.hs:1
testsuite/tests/rts/T7160.hs:1
testsuite/tests/rts/overflow3.hs:1
testsuite/tests/rts/overflow2.hs:1
testsuite/tests/rts/T5250.hs:1
testsuite/tests/rts/T10296b.hs:2
testsuite/tests/th/T3319.hs:1
testsuite/tests/th/TH_foreignInterruptible.hs:1
testsuite/tests/th/TH_foreignCallingConventions.hs:1
libraries/Cabal/cabal-install/Distribution/Client/Win32SelfUpgrade.hs:1
libraries/Cabal/Cabal/Distribution/Simple/InstallDirs.hs:2
testsuite/tests/llvm/should_compile/T5486.hs:2
testsuite/tests/codeGen/should_run/cgrun070.hs:5
testsuite/tests/codeGen/should_run/cgrun026.hs:3
testsuite/tests/primops/should_run/T4442.hs:1
testsuite/tests/ffi/should_fail/T7243.hs:1
testsuite/tests/ffi/should_fail/T3066.hs:1
testsuite/tests/ffi/should_compile/cc009.hs:1
testsuite/tests/ffi/should_run/ffi021.hs:1
testsuite/tests/typecheck/should_compile/T7408.hs:1
libraries/Cabal/cabal-install/Distribution/Client/Compat/ExecutablePath.hs:1
libraries/Cabal/Cabal/Distribution/Simple/Build/PathsModule.hs:1
libraries/time/lib/Data/Time/Clock/Internal/CTimeval.hs:1
testsuite/tests/rename/should_compile/T3103/Foreign/Ptr.hs:1
likewise the locations where Addr# comes up are as follows (some of these
perhaps should be an Addr? )
$ rg 'Addr#' --type haskell -c
utils/genprimopcode/Main.hs:2
ghc/GHCi/Leak.hs:2
compiler/cmm/CmmMachOp.hs:1
compiler/cmm/CmmUtils.hs:1
compiler/specialise/Rules.hs:2
compiler/basicTypes/MkId.hs:2
compiler/basicTypes/Literal.hs:6
compiler/basicTypes/Unique.hs:2
compiler/utils/StringBuffer.hs:1
compiler/utils/FastString.hs:4
compiler/utils/Encoding.hs:9
compiler/codeGen/StgCmmPrim.hs:3
compiler/coreSyn/MkCore.hs:5
compiler/coreSyn/CoreLint.hs:2
compiler/coreSyn/CoreSyn.hs:4
compiler/coreSyn/CorePrep.hs:1
compiler/stranal/WwLib.hs:1
compiler/simplCore/CSE.hs:1
compiler/simplCore/Simplify.hs:2
compiler/deSugar/DsExpr.hs:1
compiler/typecheck/TcGenDeriv.hs:5
compiler/prelude/ForeignCall.hs:1
compiler/prelude/PrelNames.hs:1
compiler/prelude/TysPrim.hs:1
compiler/ghci/ByteCodeGen.hs:8
libraries/bytestring/tests/revcomp.hs:1
libraries/bytestring/Data/ByteString.hs:5
libraries/ghc-heap/tests/heap_all.hs:1
libraries/ghc-prim/GHC/CString.hs:17
libraries/ghc-prim/GHC/Classes.hs:1
libraries/ghc-prim/GHC/Types.hs:3
libraries/ghci/GHCi/BinaryArray.hs:1
libraries/ghci/GHCi/CreateBCO.hs:5
libraries/base/codepages/MakeTable.hs:1
libraries/base/GHC/Ptr.hs:8
libraries/base/GHC/Generics.hs:5
libraries/base/GHC/Storable.hs:32
libraries/base/GHC/ForeignPtr.hs:6
libraries/base/Foreign/Ptr.hs:2
libraries/bytestring/Data/ByteString/Unsafe.hs:6
libraries/bytestring/Data/ByteString/Internal.hs:7
libraries/ghc-heap/GHC/Exts/Heap.hs:1
libraries/text/Data/Text/Show.hs:2
libraries/text/Data/Text/Lazy.hs:2
libraries/containers/Data/IntSet/Internal.hs:4
libraries/ghc-compact/GHC/Compact/Serialized.hs:11
libraries/base/GHC/IO/Exception.hs:1
libraries/base/Data/Typeable/Internal.hs:3
libraries/base/Control/Exception/Base.hs:1
utils/haddock/html-test/src/Ticket112.hs:1
testsuite/tests/rts/T8242.hs:19
testsuite/tests/ghci.debugger/HappyTest.hs:3
testsuite/tests/arityanal/Main.hs:3
testsuite/tests/th/TH_StringPrimL.hs:2
testsuite/tests/th/T1830_3a.hs:2
libraries/template-haskell/Language/Haskell/TH/Syntax.hs:1
libraries/bytestring/Data/ByteString/Short/Internal.hs:16
libraries/integer-gmp/src/GHC/Integer/Type.hs:11
libraries/base/GHC/IO/Encoding/CodePage.hs:3
libraries/Cabal/Cabal/Distribution/Parsec/Lexer.hs:9
testsuite/tests/generics/GEq/GEq1A.hs:1
testsuite/tests/generics/GEq/GEq1.hs:2
testsuite/tests/codeGen/should_compile/cg008.hs:1
testsuite/tests/codeGen/should_run/cgrun070.hs:4
testsuite/tests/codeGen/should_run/T9577.hs:1
testsuite/tests/codeGen/should_run/cgrun066.hs:1
testsuite/tests/codeGen/should_run/cgrun026.hs:2
testsuite/tests/codeGen/should_run/T2080.hs:2
testsuite/tests/codeGen/should_run/T9577_A.hs:1
testsuite/tests/primops/should_run/T4442.hs:4
testsuite/tests/simplCore/should_compile/T13367.hs:1
testsuite/tests/simplCore/should_compile/T13155.hs:2
testsuite/tests/simplCore/should_compile/T14779a.hs:1
testsuite/tests/simplCore/should_compile/T14779b.hs:2
testsuite/tests/simplCore/should_compile/spec001.hs:1
testsuite/tests/lib/integer/integerGmpInternals.hs:9
testsuite/tests/perf/compiler/T14683.hs:3
testsuite/tests/ghci/should_run/T2589.hs:1
libraries/integer-gmp/src/GHC/Integer/GMP/Internals.hs:7
libraries/text/Data/Text/Internal/Fusion/Common.hs:3
libraries/base/GHC/IO/Encoding/CodePage/Table.hs:1
Post by Daniel Cartwright
Also, where in base should Addr go?
On Fri, Oct 26, 2018 at 10:15 AM Daniel Cartwright <
Post by Daniel Cartwright
I would, yeah. Should the next version of `primitive` just re-export
`Addr` from base in `Data.Primitive.Addr`?
On Fri, Oct 26, 2018 at 10:14 AM Carter Schonwald <
Post by Carter Schonwald
Daniel or David, would either of you be interested/willing to do the
legwork on this patch wise (subject to sanity checking whats the impact
surface area?)
On Fri, Oct 26, 2018 at 12:04 AM Carter Schonwald <
Post by Carter Schonwald
Cool. What apis in base should move to use Addr from fake pointer ?
Cause just adding it in isolation seems lame!
I guess I’m just trying to say “what would the impact on base, if
every fake Ptr was moved to be Addr?” Because it’s not something which
should be done by halves.
1) what apis would be changed?
2) what internal things would be changed albeit not Api visible
3). Address arithmetic for Addr is very different from addres
arithmetic on larger than word8 size storable values, is there anything
which would move representations where the change to byte indexed would
change the calculations ?
If we can layout what the impact / scope of changes needed for these
and other considerations, I guess I’d be all for it. Assuming there’s the
corresponding interest in executing changes. (I just have this worry in my
head that it might be one of those icebergs.. like the split base effort )
On Thu, Oct 25, 2018, 11:28 PM Carter Schonwald <
Post by Carter Schonwald
Pretending we’re talking about this with storable as our example
Ptr Void
Corresponds to a memory address you don’t want to read or write to.
This is not so easy to think about (there's not much utility in such
a type). Perhaps Ptr Void is a reasonable type for pointers known to be
null or outside the address space, but I'm not sure.
Post by Carter Schonwald
Ptr () corresponds to a memory location that’s pretty boring to
read / write to
Yes! In other words, it's *not* what people should be using for a
pointer to an arbitrary non-Haskell address. That's precisely what Addr is
for.
Post by Carter Schonwald
On Thu, Oct 25, 2018 at 11:22 PM Carter Schonwald <
Post by Carter Schonwald
... when is a valid pointer not going to point at byte addressable
memory on memory architectures ghc can support or target?
On Thu, Oct 25, 2018 at 8:27 PM Daniel Cartwright <
Post by Daniel Cartwright
Now, one could argue that `Ptr ()` isn't a lie, it sort of reads
like C's void pointer. But surely something like `Ptr Word8` is a lie, when
it is not actually a Ptr to Word8 values.
On Thu, Oct 25, 2018 at 8:11 PM Daniel Cartwright <
Post by Daniel Cartwright
yes, only the type and its instances should be moved as far as
i'm aware.
Also, it's more than just base.
https://hackage.haskell.org/package/ghc-compact-0.1.0.0/docs/GHC-Compact-Serialized.html#t:SerializedCompact
https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-IO-Handle.html
in GHC.Stats, the foreign import "getRTSStats" has `Ptr () -> IO
()`, this Ptr () is also a lie
These are just off the top of my head, there are more
On Thu, Oct 25, 2018 at 6:46 PM Carter Schonwald <
Post by Carter Schonwald
hrmm, what are the pieces of base that are using Ptr when they
really should be using Addr? This would help me understand what would be
made better in base :)
On Thu, Oct 25, 2018 at 6:19 PM David Feuer <
Post by David Feuer
We shouldn't really need to move anything into base except
Addr and its base instances.
On Oct 25, 2018 5:59 PM, "Carter Schonwald" <
Indeed. The monad transformer instances for primmonad need to
live in primmonad OR transformers to avoid orphans.
Either way, unless transformers moves into base (unlikely), no
way anything using prim monad will.
On Thu, Oct 25, 2018 at 3:34 PM Andrew Martin <
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we
cannot move the entire module since it has functions that talk about
PrimMonad, and we definitely don't want to move that into base.
On Thu, Oct 25, 2018 at 11:25 AM Daniel Cartwright <
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a'
is used in place of 'Addr', because in base there is no 'Addr', only
'Addr#'. The problem lies in the fact that many of these uses of 'Ptr a'
are lying; the 'a' value is meaningless. Authors of functions therein have
used things like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not
mean what they say they mean - they're just Addr. There are probably other
motivations for this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-26 17:09:09 UTC
Reply
Permalink
https://phabricator.haskell.org/D5268
Post by Carter Schonwald
On the flip side we could just add data Addr ... to foreign .ptr or a
child / sibling module like System.Mem.Address and defer the associated
cleanup
I kinda like the idea of System.Mem.Address,
i put a strawman change set on phab https://phabricator.haskell.org/D5268
On Fri, Oct 26, 2018 at 12:23 PM Carter Schonwald <
Post by Carter Schonwald
granted most of the Addr# sites dont matter
a related issue is what operations WOULD be added for Addr?
maybe just memcopy friends plus address arithmetic, plus a mapper from/to
Ptr a?
does it simply become a byte size step sibling to Ptr a that put in
Foreign.Ptr?
On Fri, Oct 26, 2018 at 12:18 PM Carter Schonwald <
Post by Carter Schonwald
Before we bike shed these details, let’s evaluate / document the pieces
of base that should also be moved to using Addr. Though that module where
1) What exported types / data definitions / functions will have changes ?
2) what internal apis need to change?
as a lower bound estimate of work surface area, i grepped for "Ptr ()"
and "Addr#" in a fresh recursive clone of ghc at
commit 503514b94f8dc7bd9eab5392206649aee45f140b,
limiting my search to .hs and .hsc files
THERES A LOT of uses of Ptr (), and its siblings StablePtr () and
RemotePtr () , The latter two dont have a simple Addr# underneath,
heres the list of files that match that search rg 'Ptr \(\)' --type
haskell -c
ghc/GHCi/Leak.hs:1
utils/hsc2hs/Main.hs:1
utils/runghc/Main.hs:1
compiler/ghci/GHCi.hs:4
compiler/ghci/ByteCodeLink.hs:3
compiler/ghci/ByteCodeGen.hs:4
compiler/ghci/ByteCodeTypes.hs:1
compiler/ghci/ByteCodeAsm.hs:2
compiler/main/HscTypes.hs:1
libraries/ghci/GHCi/ObjLink.hs:3
libraries/ghci/GHCi/StaticPtrTable.hs:1
libraries/ghci/GHCi/ResolvedBCO.hs:1
libraries/ghci/GHCi/RemoteTypes.hs:2
libraries/ghci/GHCi/Run.hs:2
libraries/ghci/GHCi/Message.hs:5
libraries/base/GHC/Stable.hs:2
libraries/base/GHC/StaticPtr.hs:1
libraries/base/GHC/Generics.hs:2
libraries/base/GHC/TopHandler.hs:1
libraries/base/GHC/Windows.hs:1
libraries/base/tests/dynamic002.hs:2
utils/haddock/haddock-api/src/Haddock.hs:1
libraries/array/Data/Array/IO.hs:2
libraries/base/Foreign/Marshal/Pool.hs:1
libraries/bytestring/Data/ByteString/Builder/Extra.hs:1
libraries/base/GHC/IO/Handle/Text.hs:1
testsuite/tests/rts/T7160.hs:1
testsuite/tests/rts/overflow3.hs:1
testsuite/tests/rts/overflow2.hs:1
testsuite/tests/rts/T5250.hs:1
testsuite/tests/rts/T10296b.hs:2
testsuite/tests/th/T3319.hs:1
testsuite/tests/th/TH_foreignInterruptible.hs:1
testsuite/tests/th/TH_foreignCallingConventions.hs:1
libraries/Cabal/cabal-install/Distribution/Client/Win32SelfUpgrade.hs:1
libraries/Cabal/Cabal/Distribution/Simple/InstallDirs.hs:2
testsuite/tests/llvm/should_compile/T5486.hs:2
testsuite/tests/codeGen/should_run/cgrun070.hs:5
testsuite/tests/codeGen/should_run/cgrun026.hs:3
testsuite/tests/primops/should_run/T4442.hs:1
testsuite/tests/ffi/should_fail/T7243.hs:1
testsuite/tests/ffi/should_fail/T3066.hs:1
testsuite/tests/ffi/should_compile/cc009.hs:1
testsuite/tests/ffi/should_run/ffi021.hs:1
testsuite/tests/typecheck/should_compile/T7408.hs:1
libraries/Cabal/cabal-install/Distribution/Client/Compat/ExecutablePath.hs:1
libraries/Cabal/Cabal/Distribution/Simple/Build/PathsModule.hs:1
libraries/time/lib/Data/Time/Clock/Internal/CTimeval.hs:1
testsuite/tests/rename/should_compile/T3103/Foreign/Ptr.hs:1
likewise the locations where Addr# comes up are as follows (some of
these perhaps should be an Addr? )
$ rg 'Addr#' --type haskell -c
utils/genprimopcode/Main.hs:2
ghc/GHCi/Leak.hs:2
compiler/cmm/CmmMachOp.hs:1
compiler/cmm/CmmUtils.hs:1
compiler/specialise/Rules.hs:2
compiler/basicTypes/MkId.hs:2
compiler/basicTypes/Literal.hs:6
compiler/basicTypes/Unique.hs:2
compiler/utils/StringBuffer.hs:1
compiler/utils/FastString.hs:4
compiler/utils/Encoding.hs:9
compiler/codeGen/StgCmmPrim.hs:3
compiler/coreSyn/MkCore.hs:5
compiler/coreSyn/CoreLint.hs:2
compiler/coreSyn/CoreSyn.hs:4
compiler/coreSyn/CorePrep.hs:1
compiler/stranal/WwLib.hs:1
compiler/simplCore/CSE.hs:1
compiler/simplCore/Simplify.hs:2
compiler/deSugar/DsExpr.hs:1
compiler/typecheck/TcGenDeriv.hs:5
compiler/prelude/ForeignCall.hs:1
compiler/prelude/PrelNames.hs:1
compiler/prelude/TysPrim.hs:1
compiler/ghci/ByteCodeGen.hs:8
libraries/bytestring/tests/revcomp.hs:1
libraries/bytestring/Data/ByteString.hs:5
libraries/ghc-heap/tests/heap_all.hs:1
libraries/ghc-prim/GHC/CString.hs:17
libraries/ghc-prim/GHC/Classes.hs:1
libraries/ghc-prim/GHC/Types.hs:3
libraries/ghci/GHCi/BinaryArray.hs:1
libraries/ghci/GHCi/CreateBCO.hs:5
libraries/base/codepages/MakeTable.hs:1
libraries/base/GHC/Ptr.hs:8
libraries/base/GHC/Generics.hs:5
libraries/base/GHC/Storable.hs:32
libraries/base/GHC/ForeignPtr.hs:6
libraries/base/Foreign/Ptr.hs:2
libraries/bytestring/Data/ByteString/Unsafe.hs:6
libraries/bytestring/Data/ByteString/Internal.hs:7
libraries/ghc-heap/GHC/Exts/Heap.hs:1
libraries/text/Data/Text/Show.hs:2
libraries/text/Data/Text/Lazy.hs:2
libraries/containers/Data/IntSet/Internal.hs:4
libraries/ghc-compact/GHC/Compact/Serialized.hs:11
libraries/base/GHC/IO/Exception.hs:1
libraries/base/Data/Typeable/Internal.hs:3
libraries/base/Control/Exception/Base.hs:1
utils/haddock/html-test/src/Ticket112.hs:1
testsuite/tests/rts/T8242.hs:19
testsuite/tests/ghci.debugger/HappyTest.hs:3
testsuite/tests/arityanal/Main.hs:3
testsuite/tests/th/TH_StringPrimL.hs:2
testsuite/tests/th/T1830_3a.hs:2
libraries/template-haskell/Language/Haskell/TH/Syntax.hs:1
libraries/bytestring/Data/ByteString/Short/Internal.hs:16
libraries/integer-gmp/src/GHC/Integer/Type.hs:11
libraries/base/GHC/IO/Encoding/CodePage.hs:3
libraries/Cabal/Cabal/Distribution/Parsec/Lexer.hs:9
testsuite/tests/generics/GEq/GEq1A.hs:1
testsuite/tests/generics/GEq/GEq1.hs:2
testsuite/tests/codeGen/should_compile/cg008.hs:1
testsuite/tests/codeGen/should_run/cgrun070.hs:4
testsuite/tests/codeGen/should_run/T9577.hs:1
testsuite/tests/codeGen/should_run/cgrun066.hs:1
testsuite/tests/codeGen/should_run/cgrun026.hs:2
testsuite/tests/codeGen/should_run/T2080.hs:2
testsuite/tests/codeGen/should_run/T9577_A.hs:1
testsuite/tests/primops/should_run/T4442.hs:4
testsuite/tests/simplCore/should_compile/T13367.hs:1
testsuite/tests/simplCore/should_compile/T13155.hs:2
testsuite/tests/simplCore/should_compile/T14779a.hs:1
testsuite/tests/simplCore/should_compile/T14779b.hs:2
testsuite/tests/simplCore/should_compile/spec001.hs:1
testsuite/tests/lib/integer/integerGmpInternals.hs:9
testsuite/tests/perf/compiler/T14683.hs:3
testsuite/tests/ghci/should_run/T2589.hs:1
libraries/integer-gmp/src/GHC/Integer/GMP/Internals.hs:7
libraries/text/Data/Text/Internal/Fusion/Common.hs:3
libraries/base/GHC/IO/Encoding/CodePage/Table.hs:1
On Fri, Oct 26, 2018 at 11:01 AM Daniel Cartwright <
Post by Daniel Cartwright
Also, where in base should Addr go?
On Fri, Oct 26, 2018 at 10:15 AM Daniel Cartwright <
Post by Daniel Cartwright
I would, yeah. Should the next version of `primitive` just re-export
`Addr` from base in `Data.Primitive.Addr`?
On Fri, Oct 26, 2018 at 10:14 AM Carter Schonwald <
Post by Carter Schonwald
Daniel or David, would either of you be interested/willing to do the
legwork on this patch wise (subject to sanity checking whats the impact
surface area?)
On Fri, Oct 26, 2018 at 12:04 AM Carter Schonwald <
Post by Carter Schonwald
Cool. What apis in base should move to use Addr from fake pointer ?
Cause just adding it in isolation seems lame!
I guess I’m just trying to say “what would the impact on base, if
every fake Ptr was moved to be Addr?” Because it’s not something which
should be done by halves.
1) what apis would be changed?
2) what internal things would be changed albeit not Api visible
3). Address arithmetic for Addr is very different from addres
arithmetic on larger than word8 size storable values, is there anything
which would move representations where the change to byte indexed would
change the calculations ?
If we can layout what the impact / scope of changes needed for these
and other considerations, I guess I’d be all for it. Assuming there’s the
corresponding interest in executing changes. (I just have this worry in my
head that it might be one of those icebergs.. like the split base effort )
On Thu, Oct 25, 2018, 11:28 PM Carter Schonwald <
Post by Carter Schonwald
Pretending we’re talking about this with storable as our example
Ptr Void
Corresponds to a memory address you don’t want to read or write to.
This is not so easy to think about (there's not much utility in
such a type). Perhaps Ptr Void is a reasonable type for pointers known to
be null or outside the address space, but I'm not sure.
Post by Carter Schonwald
Ptr () corresponds to a memory location that’s pretty boring to
read / write to
Yes! In other words, it's *not* what people should be using for a
pointer to an arbitrary non-Haskell address. That's precisely what Addr is
for.
Post by Carter Schonwald
On Thu, Oct 25, 2018 at 11:22 PM Carter Schonwald <
Post by Carter Schonwald
... when is a valid pointer not going to point at byte
addressable memory on memory architectures ghc can support or target?
On Thu, Oct 25, 2018 at 8:27 PM Daniel Cartwright <
Post by Daniel Cartwright
Now, one could argue that `Ptr ()` isn't a lie, it sort of reads
like C's void pointer. But surely something like `Ptr Word8` is a lie, when
it is not actually a Ptr to Word8 values.
On Thu, Oct 25, 2018 at 8:11 PM Daniel Cartwright <
Post by Daniel Cartwright
yes, only the type and its instances should be moved as far as
i'm aware.
Also, it's more than just base.
https://hackage.haskell.org/package/ghc-compact-0.1.0.0/docs/GHC-Compact-Serialized.html#t:SerializedCompact
https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-IO-Handle.html
in GHC.Stats, the foreign import "getRTSStats" has `Ptr () ->
IO ()`, this Ptr () is also a lie
These are just off the top of my head, there are more
On Thu, Oct 25, 2018 at 6:46 PM Carter Schonwald <
Post by Carter Schonwald
hrmm, what are the pieces of base that are using Ptr when they
really should be using Addr? This would help me understand what would be
made better in base :)
On Thu, Oct 25, 2018 at 6:19 PM David Feuer <
Post by David Feuer
We shouldn't really need to move anything into base except
Addr and its base instances.
On Oct 25, 2018 5:59 PM, "Carter Schonwald" <
Indeed. The monad transformer instances for primmonad need
to live in primmonad OR transformers to avoid orphans.
Either way, unless transformers moves into base (unlikely),
no way anything using prim monad will.
On Thu, Oct 25, 2018 at 3:34 PM Andrew Martin <
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we
cannot move the entire module since it has functions that talk about
PrimMonad, and we definitely don't want to move that into base.
On Thu, Oct 25, 2018 at 11:25 AM Daniel Cartwright <
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a'
is used in place of 'Addr', because in base there is no 'Addr', only
'Addr#'. The problem lies in the fact that many of these uses of 'Ptr a'
are lying; the 'a' value is meaningless. Authors of functions therein have
used things like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not
mean what they say they mean - they're just Addr. There are probably other
motivations for this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Sven Panne
2018-10-26 17:26:33 UTC
Reply
Permalink
Am Fr., 26. Okt. 2018 um 06:05 Uhr schrieb Carter Schonwald <
[...] I guess I’m just trying to say “what would the impact on base, if
every fake Ptr was moved to be Addr?” Because it’s not something which
should be done by halves.
1) [...]
2) [...]
3). [...]
The most important question is missing from this list: What are the
benefits of touching such a crucial part of our API ecosystem? There should
better be extremely good reasons, otherwise lots of annoying work and
incompatibility is generated for nothing. Reading through this thread, I
haven't seen a good motivation for touching Storable/Ptr and friends.
Perhaps I have misunderstood what the actual proposal is, initially I
thought it is just replacing various "Ptr foo" with Addr only within GHC
itself. That's fine, but the scope seems to have broadened.

Just a historical remark: Addr# is a GHCism, and so was Addr. At the time
the FFI came up, Ptr was intended to be the portable type. So yes, "Ptr a"
and "Ptr ()" are basically just Addr (modulo casts), but intentionally so.
Carter Schonwald
2018-10-26 17:35:55 UTC
Reply
Permalink
your perspective here is a good one

1) i absolutely agree, nothing should touch storable, whatesoever,

2) the baseline proposal is to add an Addr to Base (essentially Ptr ()),
which would be a crippled sibling of how its exposed in Data.Primitive I
guess?

3) as a litmus for "what would this acomplish/support", i was asking "how
would this get used/help base be nicer "? If

anyways: i did a strawman of what Addr ripped out of Data.Primitive.Addr
and into base would look like, and it doesn't look especially compelling /
nicer than Ptr shenanigans. Especially since to be useful in base it would
have to have a bunch of IO / ST specific operations that have the option
perhaps of using Storable to read /write at locations. At which point I
still need to have the same API surface area again in Primitive,

see https://phabricator.haskell.org/D5268 for the bare bones stuff (doesn't
type check)

the api i could expose there in base does not reduce the implementation
surface area needed for Primitve...

i'm open to being convinced otherwise, but with Sven's perspective weighed
in,
1) i dont see it being super useful within base/ghc apis, as they exist
today
2) it doesn't reduce implementation surface area burden in the Primitive
package.

so at this point im' weakly against the addition. more work, no clear
reward for me :)
Post by Sven Panne
Am Fr., 26. Okt. 2018 um 06:05 Uhr schrieb Carter Schonwald <
[...] I guess I’m just trying to say “what would the impact on base, if
every fake Ptr was moved to be Addr?” Because it’s not something which
should be done by halves.
1) [...]
2) [...]
3). [...]
The most important question is missing from this list: What are the
benefits of touching such a crucial part of our API ecosystem? There should
better be extremely good reasons, otherwise lots of annoying work and
incompatibility is generated for nothing. Reading through this thread, I
haven't seen a good motivation for touching Storable/Ptr and friends.
Perhaps I have misunderstood what the actual proposal is, initially I
thought it is just replacing various "Ptr foo" with Addr only within GHC
itself. That's fine, but the scope seems to have broadened.
Just a historical remark: Addr# is a GHCism, and so was Addr. At the time
the FFI came up, Ptr was intended to be the portable type. So yes, "Ptr a"
and "Ptr ()" are basically just Addr (modulo casts), but intentionally so.
Daniel Cartwright
2018-10-26 17:42:34 UTC
Reply
Permalink
there was never any hint at helping primitive, i'm not sure where you got
that from. also, the primary motivation was to avoid using 'Ptr a', where
'a' is a lie. not only that, but base seems a natural home for 'Addr', and
people can avoid incurring a dep on primitive when they just need 'Addr'.

'super useful' was never the goal - only correctness and convenience.

Yeah, i agree that Storable should not be touched.
Post by Carter Schonwald
your perspective here is a good one
1) i absolutely agree, nothing should touch storable, whatesoever,
2) the baseline proposal is to add an Addr to Base (essentially Ptr ()),
which would be a crippled sibling of how its exposed in Data.Primitive I
guess?
3) as a litmus for "what would this acomplish/support", i was asking "how
would this get used/help base be nicer "? If
anyways: i did a strawman of what Addr ripped out of Data.Primitive.Addr
and into base would look like, and it doesn't look especially compelling /
nicer than Ptr shenanigans. Especially since to be useful in base it would
have to have a bunch of IO / ST specific operations that have the option
perhaps of using Storable to read /write at locations. At which point I
still need to have the same API surface area again in Primitive,
see https://phabricator.haskell.org/D5268 for the bare bones stuff
(doesn't type check)
the api i could expose there in base does not reduce the implementation
surface area needed for Primitve...
i'm open to being convinced otherwise, but with Sven's perspective weighed
in,
1) i dont see it being super useful within base/ghc apis, as they exist
today
2) it doesn't reduce implementation surface area burden in the Primitive
package.
so at this point im' weakly against the addition. more work, no clear
reward for me :)
Post by Sven Panne
Am Fr., 26. Okt. 2018 um 06:05 Uhr schrieb Carter Schonwald <
[...] I guess I’m just trying to say “what would the impact on base, if
every fake Ptr was moved to be Addr?” Because it’s not something which
should be done by halves.
1) [...]
2) [...]
3). [...]
The most important question is missing from this list: What are the
benefits of touching such a crucial part of our API ecosystem? There should
better be extremely good reasons, otherwise lots of annoying work and
incompatibility is generated for nothing. Reading through this thread, I
haven't seen a good motivation for touching Storable/Ptr and friends.
Perhaps I have misunderstood what the actual proposal is, initially I
thought it is just replacing various "Ptr foo" with Addr only within GHC
itself. That's fine, but the scope seems to have broadened.
Just a historical remark: Addr# is a GHCism, and so was Addr. At the time
the FFI came up, Ptr was intended to be the portable type. So yes, "Ptr a"
and "Ptr ()" are basically just Addr (modulo casts), but intentionally so.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-26 17:55:18 UTC
Reply
Permalink
What api? It’s not obvious, could you spell out what you have in mind.
Relative to the phab straw man?
Post by Daniel Cartwright
there was never any hint at helping primitive, i'm not sure where you got
that from. also, the primary motivation was to avoid using 'Ptr a', where
'a' is a lie. not only that, but base seems a natural home for 'Addr', and
people can avoid incurring a dep on primitive when they just need 'Addr'.
'super useful' was never the goal - only correctness and convenience.
Yeah, i agree that Storable should not be touched.
On Fri, Oct 26, 2018 at 1:36 PM Carter Schonwald <
Post by Carter Schonwald
your perspective here is a good one
1) i absolutely agree, nothing should touch storable, whatesoever,
2) the baseline proposal is to add an Addr to Base (essentially Ptr ()),
which would be a crippled sibling of how its exposed in Data.Primitive I
guess?
3) as a litmus for "what would this acomplish/support", i was asking "how
would this get used/help base be nicer "? If
anyways: i did a strawman of what Addr ripped out of Data.Primitive.Addr
and into base would look like, and it doesn't look especially compelling /
nicer than Ptr shenanigans. Especially since to be useful in base it would
have to have a bunch of IO / ST specific operations that have the option
perhaps of using Storable to read /write at locations. At which point I
still need to have the same API surface area again in Primitive,
see https://phabricator.haskell.org/D5268 for the bare bones stuff
(doesn't type check)
the api i could expose there in base does not reduce the implementation
surface area needed for Primitve...
i'm open to being convinced otherwise, but with Sven's perspective
weighed in,
1) i dont see it being super useful within base/ghc apis, as they exist
today
2) it doesn't reduce implementation surface area burden in the Primitive
package.
so at this point im' weakly against the addition. more work, no clear
reward for me :)
Post by Sven Panne
Am Fr., 26. Okt. 2018 um 06:05 Uhr schrieb Carter Schonwald <
[...] I guess I’m just trying to say “what would the impact on base, if
every fake Ptr was moved to be Addr?” Because it’s not something which
should be done by halves.
1) [...]
2) [...]
3). [...]
The most important question is missing from this list: What are the
benefits of touching such a crucial part of our API ecosystem? There should
better be extremely good reasons, otherwise lots of annoying work and
incompatibility is generated for nothing. Reading through this thread, I
haven't seen a good motivation for touching Storable/Ptr and friends.
Perhaps I have misunderstood what the actual proposal is, initially I
thought it is just replacing various "Ptr foo" with Addr only within GHC
itself. That's fine, but the scope seems to have broadened.
Just a historical remark: Addr# is a GHCism, and so was Addr. At the
time the FFI came up, Ptr was intended to be the portable type. So yes,
"Ptr a" and "Ptr ()" are basically just Addr (modulo casts), but
intentionally so.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-26 18:00:04 UTC
Reply
Permalink
anyways, if you want to do a cleaned up sibling of
https://phabricator.haskell.org/D5268, i vote yes
Post by Carter Schonwald
What api? It’s not obvious, could you spell out what you have in mind.
Relative to the phab straw man?
Post by Daniel Cartwright
there was never any hint at helping primitive, i'm not sure where you got
that from. also, the primary motivation was to avoid using 'Ptr a', where
'a' is a lie. not only that, but base seems a natural home for 'Addr', and
people can avoid incurring a dep on primitive when they just need 'Addr'.
'super useful' was never the goal - only correctness and convenience.
Yeah, i agree that Storable should not be touched.
On Fri, Oct 26, 2018 at 1:36 PM Carter Schonwald <
Post by Carter Schonwald
your perspective here is a good one
1) i absolutely agree, nothing should touch storable, whatesoever,
2) the baseline proposal is to add an Addr to Base (essentially Ptr ()),
which would be a crippled sibling of how its exposed in Data.Primitive I
guess?
3) as a litmus for "what would this acomplish/support", i was asking
"how would this get used/help base be nicer "? If
anyways: i did a strawman of what Addr ripped out of Data.Primitive.Addr
and into base would look like, and it doesn't look especially compelling /
nicer than Ptr shenanigans. Especially since to be useful in base it would
have to have a bunch of IO / ST specific operations that have the option
perhaps of using Storable to read /write at locations. At which point I
still need to have the same API surface area again in Primitive,
see https://phabricator.haskell.org/D5268 for the bare bones stuff
(doesn't type check)
the api i could expose there in base does not reduce the implementation
surface area needed for Primitve...
i'm open to being convinced otherwise, but with Sven's perspective
weighed in,
1) i dont see it being super useful within base/ghc apis, as they exist
today
2) it doesn't reduce implementation surface area burden in the Primitive
package.
so at this point im' weakly against the addition. more work, no clear
reward for me :)
Post by Sven Panne
Am Fr., 26. Okt. 2018 um 06:05 Uhr schrieb Carter Schonwald <
[...] I guess I’m just trying to say “what would the impact on base,
if every fake Ptr was moved to be Addr?” Because it’s not something which
should be done by halves.
1) [...]
2) [...]
3). [...]
The most important question is missing from this list: What are the
benefits of touching such a crucial part of our API ecosystem? There should
better be extremely good reasons, otherwise lots of annoying work and
incompatibility is generated for nothing. Reading through this thread, I
haven't seen a good motivation for touching Storable/Ptr and friends.
Perhaps I have misunderstood what the actual proposal is, initially I
thought it is just replacing various "Ptr foo" with Addr only within GHC
itself. That's fine, but the scope seems to have broadened.
Just a historical remark: Addr# is a GHCism, and so was Addr. At the
time the FFI came up, Ptr was intended to be the portable type. So yes,
"Ptr a" and "Ptr ()" are basically just Addr (modulo casts), but
intentionally so.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Daniel Cartwright
2018-10-26 18:00:41 UTC
Reply
Permalink
I'm only saying that 'Addr', its base-scoped instances, and the API of
'Data.Primitive.Addr' that is base-scoped should be added to base.
Eventually any non-user-facing functions that use 'Ptr LyingType' should be
switched from using 'Ptr' to 'Addr'. There's nothing more to my proposal as
far as action items.

As far as consequences, users may want to have access to 'Addr' without
needing 'primitive'. 'primitive' shouldn't really see any API change, as it
will just re-export whatever gets implemented in base for 'Addr'.
Post by Carter Schonwald
What api? It’s not obvious, could you spell out what you have in mind.
Relative to the phab straw man?
Post by Daniel Cartwright
there was never any hint at helping primitive, i'm not sure where you got
that from. also, the primary motivation was to avoid using 'Ptr a', where
'a' is a lie. not only that, but base seems a natural home for 'Addr', and
people can avoid incurring a dep on primitive when they just need 'Addr'.
'super useful' was never the goal - only correctness and convenience.
Yeah, i agree that Storable should not be touched.
On Fri, Oct 26, 2018 at 1:36 PM Carter Schonwald <
Post by Carter Schonwald
your perspective here is a good one
1) i absolutely agree, nothing should touch storable, whatesoever,
2) the baseline proposal is to add an Addr to Base (essentially Ptr ()),
which would be a crippled sibling of how its exposed in Data.Primitive I
guess?
3) as a litmus for "what would this acomplish/support", i was asking
"how would this get used/help base be nicer "? If
anyways: i did a strawman of what Addr ripped out of Data.Primitive.Addr
and into base would look like, and it doesn't look especially compelling /
nicer than Ptr shenanigans. Especially since to be useful in base it would
have to have a bunch of IO / ST specific operations that have the option
perhaps of using Storable to read /write at locations. At which point I
still need to have the same API surface area again in Primitive,
see https://phabricator.haskell.org/D5268 for the bare bones stuff
(doesn't type check)
the api i could expose there in base does not reduce the implementation
surface area needed for Primitve...
i'm open to being convinced otherwise, but with Sven's perspective
weighed in,
1) i dont see it being super useful within base/ghc apis, as they exist
today
2) it doesn't reduce implementation surface area burden in the Primitive
package.
so at this point im' weakly against the addition. more work, no clear
reward for me :)
Post by Sven Panne
Am Fr., 26. Okt. 2018 um 06:05 Uhr schrieb Carter Schonwald <
[...] I guess I’m just trying to say “what would the impact on base,
if every fake Ptr was moved to be Addr?” Because it’s not something which
should be done by halves.
1) [...]
2) [...]
3). [...]
The most important question is missing from this list: What are the
benefits of touching such a crucial part of our API ecosystem? There should
better be extremely good reasons, otherwise lots of annoying work and
incompatibility is generated for nothing. Reading through this thread, I
haven't seen a good motivation for touching Storable/Ptr and friends.
Perhaps I have misunderstood what the actual proposal is, initially I
thought it is just replacing various "Ptr foo" with Addr only within GHC
itself. That's fine, but the scope seems to have broadened.
Just a historical remark: Addr# is a GHCism, and so was Addr. At the
time the FFI came up, Ptr was intended to be the portable type. So yes,
"Ptr a" and "Ptr ()" are basically just Addr (modulo casts), but
intentionally so.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Sven Panne
2018-10-26 20:08:03 UTC
Reply
Permalink
Am Fr., 26. Okt. 2018 um 20:00 Uhr schrieb Daniel Cartwright <
[...] Eventually any non-user-facing functions that use 'Ptr LyingType'
should be switched from using 'Ptr' to 'Addr'. [...]
Again my question is: Why? When someone sees a "Ptr a" or "Ptr ()", it's
blindingly obvious that this is equivalent to Addr, i.e. you need some
additional information what that thing is pointing to or you don't care
about what's at that location. This is not "lying", quite the opposite.

You can turn the whole proposal 180 degrees around: Let's nuke "Addr" in
favor of "Ptr a"/"Ptr ()"! :-) That would even get rid of a whole type,
something the current proposal doesn't achieve. Addr is strictly less
powerful than Ptr, so why keep the former?
Daniel Cartwright
2018-10-26 20:16:19 UTC
Reply
Permalink
I am referring to the situations when someone uses 'Ptr a', but the Ptr
does not point to anything of type 'a'. If I write 'Ptr Word8', but I am
pointing to a Char, then that is not true.
Post by Sven Panne
Am Fr., 26. Okt. 2018 um 20:00 Uhr schrieb Daniel Cartwright <
[...] Eventually any non-user-facing functions that use 'Ptr LyingType'
should be switched from using 'Ptr' to 'Addr'. [...]
Again my question is: Why? When someone sees a "Ptr a" or "Ptr ()", it's
blindingly obvious that this is equivalent to Addr, i.e. you need some
additional information what that thing is pointing to or you don't care
about what's at that location. This is not "lying", quite the opposite.
You can turn the whole proposal 180 degrees around: Let's nuke "Addr" in
favor of "Ptr a"/"Ptr ()"! :-) That would even get rid of a whole type,
something the current proposal doesn't achieve. Addr is strictly less
powerful than Ptr, so why keep the former?
Sven Panne
2018-10-26 20:26:28 UTC
Reply
Permalink
Am Fr., 26. Okt. 2018 um 22:16 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
I am referring to the situations when someone uses 'Ptr a', but the Ptr
does not point to anything of type 'a'. If I write 'Ptr Word8', but I am
pointing to a Char, then that is not true.
It might not be true, but you might be forced to do such things to use some
ugly C library. The Ptr type carries some valuable information, namely:
What does my C counterpart expect? It might not be 100% true on the Haskell
side, but you are in "unsafe land", anyway, and at some level you *have* to
be able to use some white lie when necessary. Note that I'm not saying that
this is nice, but I haven't heard of a better alternative yet.
Andrew Martin
2018-10-26 20:31:11 UTC
Reply
Permalink
The better alternative suggested in this thread is to use Addr instead.
That way, you don't have to lie about the type of the serialized data that
the pointer is pointing to.
Post by Sven Panne
Am Fr., 26. Okt. 2018 um 22:16 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
I am referring to the situations when someone uses 'Ptr a', but the Ptr
does not point to anything of type 'a'. If I write 'Ptr Word8', but I am
pointing to a Char, then that is not true.
It might not be true, but you might be forced to do such things to use
some ugly C library. The Ptr type carries some valuable information,
namely: What does my C counterpart expect? It might not be 100% true on the
Haskell side, but you are in "unsafe land", anyway, and at some level you
*have* to be able to use some white lie when necessary. Note that I'm not
saying that this is nice, but I haven't heard of a better alternative yet.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
Sven Panne
2018-10-26 20:38:29 UTC
Reply
Permalink
Am Fr., 26. Okt. 2018 um 22:31 Uhr schrieb Andrew Martin <
Post by Andrew Martin
The better alternative suggested in this thread is to use Addr instead.
That way, you don't have to lie about the type of the serialized data that
the pointer is pointing to.
Even if I'm repeating myself: That is not lying, quite the opposite. If you
e.g. use a C library with suboptimal typing (i.e. more often than not), you
make the impedance matching explicit. How would you achieve that with Addr?
Daniel Cartwright
2018-10-26 20:58:06 UTC
Reply
Permalink
There is no operational difference when using `Ptr a` vs `Addr` in such a
case. The problem lies in the type variable `a`. Types are here to guide us
- if I use `Ptr Word8`, and this Ptr is not a Ptr to Word8, there is not
much enforcing this. In such cases, the type annotation is untruthful. We
would like it more often than not to be truthful. Yes, in the underlying C,
there exists suboptimal typing, but that is why we are not writing in C,
and instead lifting the code to Haskell.
Post by Sven Panne
Am Fr., 26. Okt. 2018 um 22:31 Uhr schrieb Andrew Martin <
Post by Andrew Martin
The better alternative suggested in this thread is to use Addr instead.
That way, you don't have to lie about the type of the serialized data that
the pointer is pointing to.
Even if I'm repeating myself: That is not lying, quite the opposite. If
you e.g. use a C library with suboptimal typing (i.e. more often than not),
you make the impedance matching explicit. How would you achieve that with
Addr?
Sven Panne
2018-10-27 10:04:35 UTC
Reply
Permalink
Am Sa., 27. Okt. 2018 um 11:07 Uhr schrieb Bertram Felgenhauer via
[...] We should also discuss the cost associated with mixing two
functionally
equivalent types in the same library, which will make the API less
predictable, are likely to result in duplication in the APIs for Ptr and
Addr, and will lead to more explicit type conversions with little
benefit. [...]
The more I think about it, the more serious I am about my "180 degree"
proposal: Nuke Addr completely in favor of "Ptr a"/"Ptr ()". What can Addr
do what a "Ptr a"/"Ptr ()" can't? Off the top of my head I would say
"nothing". In most other circumstances we like generalizations, why not
here? Having Addr just gives us a bigger API surface and is probably used
mostly within GHC and its closely tied packages, not really "in the wild".

If "Ptr a" or "Ptr ()" or "Ptr Void" is the right thing to use in a
specific place is always a tradeoff between ease of use, being explicit,
readability, and perhaps what a corresponding C library uses. Type safety,
as much as we like it, is just wishful thinking at that level, there's
always castPtr (and of course the FunPtr counterparts).
Carter Schonwald
2018-10-27 13:56:21 UTC
Reply
Permalink
Addr only exists within the primitive package. And it only seems to be
used in one spot in all of the vector package. And it’s a very weird spot
that I honestly may wanna redesign/see about changing given how strange
it is. Especially since it may be one of those things where the current
code needs some benchmarks

https://github.com/haskell/vector/blob/master/Data/Vector/Storable/Mutable.hs#L164-L205


It’s the only instance in all of vector
Post by Sven Panne
Am Sa., 27. Okt. 2018 um 11:07 Uhr schrieb Bertram Felgenhauer via
[...] We should also discuss the cost associated with mixing two
functionally
equivalent types in the same library, which will make the API less
predictable, are likely to result in duplication in the APIs for Ptr and
Addr, and will lead to more explicit type conversions with little
benefit. [...]
The more I think about it, the more serious I am about my "180 degree"
proposal: Nuke Addr completely in favor of "Ptr a"/"Ptr ()". What can Addr
do what a "Ptr a"/"Ptr ()" can't? Off the top of my head I would say
"nothing". In most other circumstances we like generalizations, why not
here? Having Addr just gives us a bigger API surface and is probably used
mostly within GHC and its closely tied packages, not really "in the wild".
If "Ptr a" or "Ptr ()" or "Ptr Void" is the right thing to use in a
specific place is always a tradeoff between ease of use, being explicit,
readability, and perhaps what a corresponding C library uses. Type safety,
as much as we like it, is just wishful thinking at that level, there's
always castPtr (and of course the FunPtr counterparts).
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-27 18:43:21 UTC
Reply
Permalink
*only use i'm aware of

and its a pretty gross one.

are there any ACTUAL uses of Addr? (granted, having a lifted / data'd
version of unlifted types is general a useful thing)

Ptr Void having the byte address oriented interface for indexing arithmetic
sounds good to me
Post by Carter Schonwald
Addr only exists within the primitive package. And it only seems to be
used in one spot in all of the vector package. And it’s a very weird spot
that I honestly may wanna redesign/see about changing given how strange
it is. Especially since it may be one of those things where the current
code needs some benchmarks
https://github.com/haskell/vector/blob/master/Data/Vector/Storable/Mutable.hs#L164-L205
It’s the only instance in all of vector
Post by Sven Panne
Am Sa., 27. Okt. 2018 um 11:07 Uhr schrieb Bertram Felgenhauer via
[...] We should also discuss the cost associated with mixing two
functionally
equivalent types in the same library, which will make the API less
predictable, are likely to result in duplication in the APIs for Ptr and
Addr, and will lead to more explicit type conversions with little
benefit. [...]
The more I think about it, the more serious I am about my "180 degree"
proposal: Nuke Addr completely in favor of "Ptr a"/"Ptr ()". What can Addr
do what a "Ptr a"/"Ptr ()" can't? Off the top of my head I would say
"nothing". In most other circumstances we like generalizations, why not
here? Having Addr just gives us a bigger API surface and is probably used
mostly within GHC and its closely tied packages, not really "in the wild".
If "Ptr a" or "Ptr ()" or "Ptr Void" is the right thing to use in a
specific place is always a tradeoff between ease of use, being explicit,
readability, and perhaps what a corresponding C library uses. Type safety,
as much as we like it, is just wishful thinking at that level, there's
always castPtr (and of course the FunPtr counterparts).
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Daniel Cartwright
2018-10-29 13:25:18 UTC
Reply
Permalink
'Ptr Void' is not a pointer to value of type 'Void'; there are no values of
type 'Void'; this type is nonsensical.
'Ptr a' is not a pointer to a value of type a; what is 'a'?
'Ptr ()' could be a pointer to a value of type '()', and if so, then this
is a correct usage of 'Ptr'. If not, it is an incorrect usage of 'Ptr'.
Post by Carter Schonwald
*only use i'm aware of
and its a pretty gross one.
are there any ACTUAL uses of Addr? (granted, having a lifted / data'd
version of unlifted types is general a useful thing)
Ptr Void having the byte address oriented interface for indexing
arithmetic sounds good to me
On Sat, Oct 27, 2018 at 9:56 AM Carter Schonwald <
Post by Carter Schonwald
Addr only exists within the primitive package. And it only seems to be
used in one spot in all of the vector package. And it’s a very weird spot
that I honestly may wanna redesign/see about changing given how strange
it is. Especially since it may be one of those things where the current
code needs some benchmarks
https://github.com/haskell/vector/blob/master/Data/Vector/Storable/Mutable.hs#L164-L205
It’s the only instance in all of vector
Post by Sven Panne
Am Sa., 27. Okt. 2018 um 11:07 Uhr schrieb Bertram Felgenhauer via
[...] We should also discuss the cost associated with mixing two
functionally
equivalent types in the same library, which will make the API less
predictable, are likely to result in duplication in the APIs for Ptr and
Addr, and will lead to more explicit type conversions with little
benefit. [...]
The more I think about it, the more serious I am about my "180 degree"
proposal: Nuke Addr completely in favor of "Ptr a"/"Ptr ()". What can Addr
do what a "Ptr a"/"Ptr ()" can't? Off the top of my head I would say
"nothing". In most other circumstances we like generalizations, why not
here? Having Addr just gives us a bigger API surface and is probably used
mostly within GHC and its closely tied packages, not really "in the wild".
If "Ptr a" or "Ptr ()" or "Ptr Void" is the right thing to use in a
specific place is always a tradeoff between ease of use, being explicit,
readability, and perhaps what a corresponding C library uses. Type safety,
as much as we like it, is just wishful thinking at that level, there's
always castPtr (and of course the FunPtr counterparts).
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Daniel Cartwright
2018-10-29 13:27:36 UTC
Reply
Permalink
'Ptr Void' is not a pointer to a value of type 'Void'; there are no values
of type 'Void': this type is nonsensical.
'Ptr a' is not a pointer to a value of type a; what is 'a'?
'Ptr ()' could be a pointer to a value of type '()', and if so, then this
is a correct usage of 'Ptr'. If not, it is an incorrect usage of 'Ptr'.
Post by Carter Schonwald
*only use i'm aware of
and its a pretty gross one.
are there any ACTUAL uses of Addr? (granted, having a lifted / data'd
version of unlifted types is general a useful thing)
Ptr Void having the byte address oriented interface for indexing
arithmetic sounds good to me
On Sat, Oct 27, 2018 at 9:56 AM Carter Schonwald <
Post by Carter Schonwald
Addr only exists within the primitive package. And it only seems to be
used in one spot in all of the vector package. And it’s a very weird spot
that I honestly may wanna redesign/see about changing given how strange
it is. Especially since it may be one of those things where the current
code needs some benchmarks
https://github.com/haskell/vector/blob/master/Data/Vector/Storable/Mutable.hs#L164-L205
It’s the only instance in all of vector
Post by Sven Panne
Am Sa., 27. Okt. 2018 um 11:07 Uhr schrieb Bertram Felgenhauer via
[...] We should also discuss the cost associated with mixing two
functionally
equivalent types in the same library, which will make the API less
predictable, are likely to result in duplication in the APIs for Ptr and
Addr, and will lead to more explicit type conversions with little
benefit. [...]
The more I think about it, the more serious I am about my "180 degree"
proposal: Nuke Addr completely in favor of "Ptr a"/"Ptr ()". What can Addr
do what a "Ptr a"/"Ptr ()" can't? Off the top of my head I would say
"nothing". In most other circumstances we like generalizations, why not
here? Having Addr just gives us a bigger API surface and is probably used
mostly within GHC and its closely tied packages, not really "in the wild".
If "Ptr a" or "Ptr ()" or "Ptr Void" is the right thing to use in a
specific place is always a tradeoff between ease of use, being explicit,
readability, and perhaps what a corresponding C library uses. Type safety,
as much as we like it, is just wishful thinking at that level, there's
always castPtr (and of course the FunPtr counterparts).
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Sven Panne
2018-10-29 14:05:14 UTC
Reply
Permalink
Am Mo., 29. Okt. 2018 um 14:27 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
'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++.
Post by Daniel Cartwright
'Ptr a' is not a pointer to a value of type a; what is 'a'?
As usual, it's the "I don't care about it" type. :) Take e.g. mallocBytes:
It returns a "Ptr a" exactly because of the fact that it doesn't care about
what will eventually be stored in the new area. Another API design option
would have been returning "Ptr Void" or "Ptr ()" instead, but this would
have forced API users to insert castPtr, which is only annoying there and
wouldn't buy us a single bit of security in those circumstances.
Post by Daniel Cartwright
'Ptr ()' could be a pointer to a value of type '()', and if so, then this
is a correct usage of 'Ptr'. If not, it is an incorrect usage of 'Ptr'.
You can't store or read "()", so the same holds as for Void (which didn't
exist when the FFI was created IIRC).
David Feuer
2018-10-29 14:10:05 UTC
Reply
Permalink
Post by Sven Panne
Am Mo., 29. Okt. 2018 um 14:27 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
'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.
Post by Sven Panne
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.
Carter Schonwald
2018-10-29 16:11:31 UTC
Reply
Permalink
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!!
Post by David Feuer
Post by Sven Panne
Am Mo., 29. Okt. 2018 um 14:27 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
'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.
Post by Sven Panne
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
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
David Feuer
2018-10-29 16:28:27 UTC
Reply
Permalink
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
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!!
'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
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-29 21:24:13 UTC
Reply
Permalink
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)
Post by David Feuer
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
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
Post by Carter Schonwald
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!!
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
Am Mo., 29. Okt. 2018 um 14:27 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
'Ptr Void' is not a pointer to a value of type 'Void'; there are no
values of type 'Void': this type is nonsensical.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
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++.
Post by Carter Schonwald
Post by David Feuer
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.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
You can't store or read "()", so the same holds as for Void (which
didn't exist when the FFI was created IIRC).
Post by Carter Schonwald
Post by David Feuer
Sure you can. Storing () does nothing and reading it gives (). Our ()
is somewhat similar to C's void return type.
Post by Carter Schonwald
Post by David Feuer
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
David Feuer
2018-10-29 21:33:31 UTC
Reply
Permalink
Good point! Call it nominal then.
Post by Carter Schonwald
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)
Post by David Feuer
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
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
Post by Carter Schonwald
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!!
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
Am Mo., 29. Okt. 2018 um 14:27 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
'Ptr Void' is not a pointer to a value of type 'Void'; there are no
values of type 'Void': this type is nonsensical.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
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++.
Post by Carter Schonwald
Post by David Feuer
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.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
You can't store or read "()", so the same holds as for Void (which
didn't exist when the FFI was created IIRC).
Post by Carter Schonwald
Post by David Feuer
Sure you can. Storing () does nothing and reading it gives (). Our ()
is somewhat similar to C's void return type.
Post by Carter Schonwald
Post by David Feuer
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-29 22:18:51 UTC
Reply
Permalink
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 <***@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.
Post by David Feuer
Good point! Call it nominal then.
Post by Carter Schonwald
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)
Post by David Feuer
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
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
Post by Carter Schonwald
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!!
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
Am Mo., 29. Okt. 2018 um 14:27 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
'Ptr Void' is not a pointer to a value of type 'Void'; there are no
values of type 'Void': this type is nonsensical.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
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++.
Post by Carter Schonwald
Post by David Feuer
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.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
You can't store or read "()", so the same holds as for Void (which
didn't exist when the FFI was created IIRC).
Post by Carter Schonwald
Post by David Feuer
Sure you can. Storing () does nothing and reading it gives (). Our ()
is somewhat similar to C's void return type.
Post by Carter Schonwald
Post by David Feuer
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Daniel Cartwright
2018-10-29 23:03:12 UTC
Reply
Permalink
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.
Post by Carter Schonwald
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 <***@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.
Post by David Feuer
Good point! Call it nominal then.
On Mon, Oct 29, 2018, 5:24 PM Carter Schonwald <
Post by Carter Schonwald
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)
Post by David Feuer
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
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
Post by Carter Schonwald
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!!
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
Am Mo., 29. Okt. 2018 um 14:27 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
'Ptr Void' is not a pointer to a value of type 'Void'; there are
no values of type 'Void': this type is nonsensical.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
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++.
Post by Carter Schonwald
Post by David Feuer
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.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
You can't store or read "()", so the same holds as for Void (which
didn't exist when the FFI was created IIRC).
Post by Carter Schonwald
Post by David Feuer
Sure you can. Storing () does nothing and reading it gives (). Our
() is somewhat similar to C's void return type.
Post by Carter Schonwald
Post by David Feuer
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-29 23:30:53 UTC
Reply
Permalink
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"
Post by Daniel Cartwright
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 <
Post by Carter Schonwald
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 <***@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.
Post by David Feuer
Good point! Call it nominal then.
On Mon, Oct 29, 2018, 5:24 PM Carter Schonwald <
Post by Carter Schonwald
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)
Post by David Feuer
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
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
Post by Carter Schonwald
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!!
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
Am Mo., 29. Okt. 2018 um 14:27 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
'Ptr Void' is not a pointer to a value of type 'Void'; there are
no values of type 'Void': this type is nonsensical.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
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++.
Post by Carter Schonwald
Post by David Feuer
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.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
You can't store or read "()", so the same holds as for Void (which
didn't exist when the FFI was created IIRC).
Post by Carter Schonwald
Post by David Feuer
Sure you can. Storing () does nothing and reading it gives (). Our
() is somewhat similar to C's void return type.
Post by Carter Schonwald
Post by David Feuer
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Dannyu NDos
2018-10-30 00:31:16 UTC
Reply
Permalink
It is Storable that makes Ptr operate as typed pointers. I also think Ptr
on its own doesn't have that much about its argument type, so I'm +1 on the
proposal.

Btw, shouldn't every type be storable? In current Haskell, Maybes or (->)s
aren't Storable, yet in C++, arrays of std::optionals or std::functions are
well-defined.

As an exception, for Void, I agree that they must remain not Storable since
it has no values.
Post by Carter Schonwald
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"
Post by Daniel Cartwright
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 <
Post by Carter Schonwald
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 <***@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.
Post by David Feuer
Good point! Call it nominal then.
On Mon, Oct 29, 2018, 5:24 PM Carter Schonwald <
Post by Carter Schonwald
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)
Post by David Feuer
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
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
Post by Carter Schonwald
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!!
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
Am Mo., 29. Okt. 2018 um 14:27 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
'Ptr Void' is not a pointer to a value of type 'Void'; there are
no values of type 'Void': this type is nonsensical.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
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++.
Post by Carter Schonwald
Post by David Feuer
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.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
You can't store or read "()", so the same holds as for Void
(which didn't exist when the FFI was created IIRC).
Post by Carter Schonwald
Post by David Feuer
Sure you can. Storing () does nothing and reading it gives (). Our
() is somewhat similar to C's void return type.
Post by Carter Schonwald
Post by David Feuer
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-30 00:34:51 UTC
Reply
Permalink
@danny... storable is only for fixed size pinned memory values
Post by Dannyu NDos
It is Storable that makes Ptr operate as typed pointers. I also think Ptr
on its own doesn't have that much about its argument type, so I'm +1 on the
proposal.
Btw, shouldn't every type be storable? In current Haskell, Maybes or (->)s
aren't Storable, yet in C++, arrays of std::optionals or std::functions are
well-defined.
As an exception, for Void, I agree that they must remain not Storable
since it has no values.
Post by Carter Schonwald
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"
Post by Daniel Cartwright
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 <
Post by Carter Schonwald
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 <***@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.
Post by David Feuer
Good point! Call it nominal then.
On Mon, Oct 29, 2018, 5:24 PM Carter Schonwald <
Post by Carter Schonwald
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)
Post by David Feuer
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
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
Post by Carter Schonwald
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!!
Post by Carter Schonwald
On Mon, Oct 29, 2018 at 10:10 AM David Feuer <
Post by David Feuer
Post by Sven Panne
Am Mo., 29. Okt. 2018 um 14:27 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
'Ptr Void' is not a pointer to a value of type 'Void'; there
are no values of type 'Void': this type is nonsensical.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
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++.
Post by Carter Schonwald
Post by David Feuer
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.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
You can't store or read "()", so the same holds as for Void
(which didn't exist when the FFI was created IIRC).
Post by Carter Schonwald
Post by David Feuer
Sure you can. Storing () does nothing and reading it gives ().
Our () is somewhat similar to C's void return type.
Post by Carter Schonwald
Post by David Feuer
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Dannyu NDos
2018-10-30 00:39:19 UTC
Reply
Permalink
You mean Nothing and (Just 0) have actually different sizes? That's so
weird for a former C++ programmer.
Post by Carter Schonwald
@danny... storable is only for fixed size pinned memory values
Post by Dannyu NDos
It is Storable that makes Ptr operate as typed pointers. I also think Ptr
on its own doesn't have that much about its argument type, so I'm +1 on the
proposal.
Btw, shouldn't every type be storable? In current Haskell, Maybes or
(->)s aren't Storable, yet in C++, arrays of std::optionals or
std::functions are well-defined.
As an exception, for Void, I agree that they must remain not Storable
since it has no values.
Post by Carter Schonwald
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"
Post by Daniel Cartwright
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 <
Post by Carter Schonwald
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 <***@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.
Post by David Feuer
Good point! Call it nominal then.
On Mon, Oct 29, 2018, 5:24 PM Carter Schonwald <
Post by Carter Schonwald
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)
Post by David Feuer
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
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
Post by Carter Schonwald
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!!
Post by Carter Schonwald
On Mon, Oct 29, 2018 at 10:10 AM David Feuer <
Post by David Feuer
Post by Sven Panne
Am Mo., 29. Okt. 2018 um 14:27 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
'Ptr Void' is not a pointer to a value of type 'Void'; there
are no values of type 'Void': this type is nonsensical.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
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++.
Post by Carter Schonwald
Post by David Feuer
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.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
You can't store or read "()", so the same holds as for Void
(which didn't exist when the FFI was created IIRC).
Post by Carter Schonwald
Post by David Feuer
Sure you can. Storing () does nothing and reading it gives ().
Our () is somewhat similar to C's void return type.
Post by Carter Schonwald
Post by David Feuer
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Edward Kmett
2018-10-30 01:33:26 UTC
Reply
Permalink
Post by Dannyu NDos
Btw, shouldn't every type be storable? In current Haskell, Maybes or (->)s
aren't Storable, yet in C++, arrays of std::optionals or std::functions are
well-defined.
Consider [a]. There is no fixed size representation of an entire list of
elements. There is no supplementary memory management of auxillary stuff
being managed by Storable instances.

std::function holds onto its own data off to the side for the contexts of
each functor.

We have StablePtrs which give you a way to marshal any Haskell data type
out to C, including functions if you actually need it. However, it pins the
haskell object down on the heap, because we have no insight into what
happens to it once it goes out into C.

Maybe is just one extreme where you _could_ make up some convention and
tagging scheme and store it in-place, same with Either. However, Storable
makes no judgment about how to compose storables even for products, because
there are many reasonable schemes for packing (or not) the data structures
involved, and no real hope of ensuring you comply with whatever the host
compiler's ABI might be.

-Edward

As an exception, for Void, I agree that they must remain not Storable since
Post by Dannyu NDos
it has no values.
Post by Carter Schonwald
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"
Post by Daniel Cartwright
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 <
Post by Carter Schonwald
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 <***@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.
Post by David Feuer
Good point! Call it nominal then.
On Mon, Oct 29, 2018, 5:24 PM Carter Schonwald <
Post by Carter Schonwald
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)
Post by David Feuer
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
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
Post by Carter Schonwald
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!!
Post by Carter Schonwald
On Mon, Oct 29, 2018 at 10:10 AM David Feuer <
Post by David Feuer
Post by Sven Panne
Am Mo., 29. Okt. 2018 um 14:27 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
'Ptr Void' is not a pointer to a value of type 'Void'; there
are no values of type 'Void': this type is nonsensical.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
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++.
Post by Carter Schonwald
Post by David Feuer
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.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
You can't store or read "()", so the same holds as for Void
(which didn't exist when the FFI was created IIRC).
Post by Carter Schonwald
Post by David Feuer
Sure you can. Storing () does nothing and reading it gives ().
Our () is somewhat similar to C's void return type.
Post by Carter Schonwald
Post by David Feuer
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Daniel Cartwright
2018-10-30 13:33:37 UTC
Reply
Permalink
[19:26:50] <chessai_> hPutBuf :: Handle -> Ptr a -> Int -> IO ()
[19:26:50] <chessai_> hPutBuf :: Handle -> Addr -> Int -> IO ()
[19:26:55] <carter> ok
[19:27:15] <carter> maybe i wrote the buffer with bytes
[19:27:18] <carter> or maybe i did words?
[19:27:32] <carter> hputbuff dont care
[19:27:45] <hvr> the problem I see is rather that hPutBuf is a sub-optimal
type-sig
[19:28:04] <hvr> it could refer to Storable
[19:28:19] <chessai_> Storable's Ptr usage is another example
[19:28:23] <hvr> but it doesn't, hence why it seems to be a bit awkward
[19:28:35] <carter> chessai_: whats better there?
[19:28:36] <hvr> so I'd rather blame that it isn't aware of Storable
[19:28:45] <chessai_> hvr: makes sense
[19:28:51] <chessai_> carter: what's better where?
[19:29:27] <carter> what would you feel a better wrapper around storable
would be?
[19:29:36] <carter> addr ruins having good type inference there afaict
[19:30:02] <chessai_> peekByteOff :: Ptr b -> Int -> IO a
[19:30:09] <chessai_> peekByteOff :: Addr -> Int -> IO a
[19:30:26] <chessai_> what is 'b' doing there? it's not used in any
meaningful way by peekByteOff
[19:30:29] <chessai_> it's free
[19:30:39] <hvr> chessai_: so, another option besides making hGetBuf
'Storable'-aware would be to use 'Ptr Word8' imho
[19:31:00] <hvr> as that would imho be more in line with low-levelness of
that operation which is clearly about 8-bit addressable mem
[19:31:10] <hvr> (it even says so in the haddocks)
[19:31:24] <carter> chessai_: ok, thats definitely a bad api in storable
[19:31:32] <carter> seems liek that should have b and a the same in a
higher level wrapper
[19:31:43] <chessai_> or no b at all
[19:32:03] <chessai_> hvr: i think i like both of those options
[19:32:22] <carter> pokeElemOff :: Ptr a -> Int -> a -> IO () --- way
better than peak
[19:32:23] <chessai_> hvr: not sure about how i weigh them
[19:32:34] <carter> peak should be Ptr a -> Int -> IO a
[19:32:35] <hvr> and yes, peekByteOff had a weird type-sig which nobody
dared to fix probably out of fear of breakage
[19:33:12] <carter> hvr: lets add safePeekByteOff :: Ptr a -> Int -> IO a ?
[19:33:15] <carter> or sane
[19:33:23] <hvr> chessai_: but do take into account that if you want to use
'Addr' there, you're going to have a lot more of justification to do, as
this is Haskell2010 territory
[19:33:46] <chessai_> hvr: true. a lot of 'Ptr' usage seems to be part of
the report
[19:34:20] <carter> chessai_: you're giving good examples of apis that are
currently bad
[19:34:28] <carter> but it seems like they're ones we can work together to
make better
[19:34:44] <carter> and Addr vs Ptr a is your way of articulating "this API
smells bad"
[19:35:15] <carter> so i agree with the smell, just not with the cure :)
[19:35:20] <carter> at least atm
[19:35:31] <chessai_> carter: i am glad we agree on the smell
Post by Carter Schonwald
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"
Post by Daniel Cartwright
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 <
Post by Carter Schonwald
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 <***@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.
Post by David Feuer
Good point! Call it nominal then.
On Mon, Oct 29, 2018, 5:24 PM Carter Schonwald <
Post by Carter Schonwald
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)
Post by David Feuer
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
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
Post by Carter Schonwald
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!!
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
Am Mo., 29. Okt. 2018 um 14:27 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
'Ptr Void' is not a pointer to a value of type 'Void'; there are
no values of type 'Void': this type is nonsensical.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
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++.
Post by Carter Schonwald
Post by David Feuer
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.
Post by Carter Schonwald
Post by David Feuer
Post by Sven Panne
You can't store or read "()", so the same holds as for Void
(which didn't exist when the FFI was created IIRC).
Post by Carter Schonwald
Post by David Feuer
Sure you can. Storing () does nothing and reading it gives (). Our
() is somewhat similar to C's void return type.
Post by Carter Schonwald
Post by David Feuer
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Sven Panne
2018-10-30 14:10:45 UTC
Reply
Permalink
I am not sure if everybody fully comprehends what Storable is all about: It
is meant as the lowest-level building block in an Addr-free world
(remember: Addr is a GHCism and is *not* mentioned anywhere in the report)
to put a few well-defined simple Haskell types into memory or read them
from there. Its explicit non-goals are:

* Achieve 100% type safety. In the presence of raw memory access,
castPtr, C calls etc. this would be a total illusion. Forcing API users to
sprinkle tons of castPtr at every possible place over their code wouldn't
improve safety at all, it would only hurt readability.

* Handle more complicated sum/product types. How would you do this?
Respect your native ABI (i.e. automatically handle padding/alignment)?
Tightly packed? Or even handle a foreign ABI? Your own ABI? Some funny
encoding like OpenGL's packed data types? Etc. etc. You can build all of
those things in a layer above Storable, probably introducing other type
classes or some marshaling DSLs.

* Portability of the written values. This is more in the realm of
serialization libraries.

More concretely:

Am Di., 30. Okt. 2018 um 14:34 Uhr schrieb Daniel Cartwright <
[19:26:50] <chessai_> hPutBuf :: Handle -> Ptr a -> Int -> IO () [...]
The signature for this is actually perfect: hPutBuf doesn't care about what
stuff has been written into the given buffer, it just cares about its start
and its size. Forcing castPtr Kung Fu here wouldn't buy you anything: The
buffer will probably contain a wild mix of Haskell values or even no
Haskell values at all, but that doesn't matter. Whatever you pass as "a" or
whatever you cast from/to is probably a lie from the typing perspective. At
this level this is no problem at all.
[19:30:02] <chessai_> peekByteOff :: Ptr b -> Int -> IO a
[19:30:09] <chessai_> peekByteOff :: Addr -> Int -> IO a
[19:30:26] <chessai_> what is 'b' doing there? it's not used in any
meaningful way by peekByteOff [...]
If you have a pointer pointing to something and shift that pointer by some
bytes, you are probably pointing to something completely different, so of
course "b" and "a" have nothing to do with each other. So peekByteOff
intentionally ignores "b".
[19:32:22] <carter> pokeElemOff :: Ptr a -> Int -> a -> IO () --- way
better than peak [...]
Yes, because this is intended to be used for *arrays* of values of the same
type. Note "Elem" vs. "Byte".
[19:33:12] <carter> hvr: lets add safePeekByteOff :: Ptr a -> Int -> IO a
? [...]
This signature doesn't make sense, see above: Shifting a pointer by an
arbitrary amount of bytes will probably change the type of what you're
pointing to. If you shift by units of the underlying type, well, that's
peekElemOff.
[19:35:31] <chessai_> carter: i am glad we agree on the smell
I don't have the full chat log, but I think I don't even agree on the
smell, at least not at the places I've seen... :-)
Daniel Cartwright
2018-10-30 14:18:13 UTC
Reply
Permalink
hPutBuf doesn't care about what stuff has been written into the given
buffer, it just cares about its start and its size.
Seems like a good use for Addr?
If you have a pointer pointing to something and shift that pointer by
some bytes, you are probably pointing to something completely different, so
of course "b" and "a" have nothing to do with each other. So peekByteOff
intentionally ignores "b".
This also seems like a good use for Addr?
It is meant as the lowest-level building block in an Addr-free world
(remember: Addr is a GHCism and is *not* mentioned anywhere in the report)
to put a few well-defined simple Haskell types into memory or read them
* Achieve 100% type safety. In the presence of raw memory access,
castPtr, C calls etc. this would be a total illusion. Forcing API users to
sprinkle tons of castPtr at every possible place over their code wouldn't
improve safety at all, it would only hurt readability.
* Handle more complicated sum/product types. How would you do this?
Respect your native ABI (i.e. automatically handle padding/alignment)?
Tightly packed? Or even handle a foreign ABI? Your own ABI? Some funny
encoding like OpenGL's packed data types? Etc. etc. You can build all of
those things in a layer above Storable, probably introducing other type
classes or some marshaling DSLs.
* Portability of the written values. This is more in the realm of
serialization libraries.
Am Di., 30. Okt. 2018 um 14:34 Uhr schrieb Daniel Cartwright <
[19:26:50] <chessai_> hPutBuf :: Handle -> Ptr a -> Int -> IO () [...]
The signature for this is actually perfect: hPutBuf doesn't care about
what stuff has been written into the given buffer, it just cares about its
The buffer will probably contain a wild mix of Haskell values or even no
Haskell values at all, but that doesn't matter. Whatever you pass as "a" or
whatever you cast from/to is probably a lie from the typing perspective. At
this level this is no problem at all.
[19:30:02] <chessai_> peekByteOff :: Ptr b -> Int -> IO a
[19:30:09] <chessai_> peekByteOff :: Addr -> Int -> IO a
[19:30:26] <chessai_> what is 'b' doing there? it's not used in any
meaningful way by peekByteOff [...]
If you have a pointer pointing to something and shift that pointer by some
bytes, you are probably pointing to something completely different, so of
course "b" and "a" have nothing to do with each other. So peekByteOff
intentionally ignores "b".
[19:32:22] <carter> pokeElemOff :: Ptr a -> Int -> a -> IO () --- way
better than peak [...]
Yes, because this is intended to be used for *arrays* of values of the
same type. Note "Elem" vs. "Byte".
[19:33:12] <carter> hvr: lets add safePeekByteOff :: Ptr a -> Int -> IO a
? [...]
This signature doesn't make sense, see above: Shifting a pointer by an
arbitrary amount of bytes will probably change the type of what you're
pointing to. If you shift by units of the underlying type, well, that's
peekElemOff.
[19:35:31] <chessai_> carter: i am glad we agree on the smell
I don't have the full chat log, but I think I don't even agree on the
smell, at least not at the places I've seen... :-)
Daniel Cartwright
2018-10-30 14:21:00 UTC
Reply
Permalink
Also, just to be clear, no one is talking about changing Storable, that
seems terrible at this point. Your argument still makes sense to make
outside of the context of wanting to change Storable, i just want to make
sure it's reiterated that this is not being suggested.
Post by Daniel Cartwright
hPutBuf doesn't care about what stuff has been written into the given
buffer, it just cares about its start and its size.
Seems like a good use for Addr?
If you have a pointer pointing to something and shift that pointer by
some bytes, you are probably pointing to something completely different, so
of course "b" and "a" have nothing to do with each other. So peekByteOff
intentionally ignores "b".
This also seems like a good use for Addr?
It is meant as the lowest-level building block in an Addr-free world
(remember: Addr is a GHCism and is *not* mentioned anywhere in the report)
to put a few well-defined simple Haskell types into memory or read them
* Achieve 100% type safety. In the presence of raw memory access,
castPtr, C calls etc. this would be a total illusion. Forcing API users to
sprinkle tons of castPtr at every possible place over their code wouldn't
improve safety at all, it would only hurt readability.
* Handle more complicated sum/product types. How would you do this?
Respect your native ABI (i.e. automatically handle padding/alignment)?
Tightly packed? Or even handle a foreign ABI? Your own ABI? Some funny
encoding like OpenGL's packed data types? Etc. etc. You can build all of
those things in a layer above Storable, probably introducing other type
classes or some marshaling DSLs.
* Portability of the written values. This is more in the realm of
serialization libraries.
Am Di., 30. Okt. 2018 um 14:34 Uhr schrieb Daniel Cartwright <
[19:26:50] <chessai_> hPutBuf :: Handle -> Ptr a -> Int -> IO () [...]
The signature for this is actually perfect: hPutBuf doesn't care about
what stuff has been written into the given buffer, it just cares about its
The buffer will probably contain a wild mix of Haskell values or even no
Haskell values at all, but that doesn't matter. Whatever you pass as "a" or
whatever you cast from/to is probably a lie from the typing perspective. At
this level this is no problem at all.
[19:30:02] <chessai_> peekByteOff :: Ptr b -> Int -> IO a
[19:30:09] <chessai_> peekByteOff :: Addr -> Int -> IO a
[19:30:26] <chessai_> what is 'b' doing there? it's not used in any
meaningful way by peekByteOff [...]
If you have a pointer pointing to something and shift that pointer by
some bytes, you are probably pointing to something completely different, so
of course "b" and "a" have nothing to do with each other. So peekByteOff
intentionally ignores "b".
[19:32:22] <carter> pokeElemOff :: Ptr a -> Int -> a -> IO () --- way
better than peak [...]
Yes, because this is intended to be used for *arrays* of values of the
same type. Note "Elem" vs. "Byte".
[19:33:12] <carter> hvr: lets add safePeekByteOff :: Ptr a -> Int -> IO
a ? [...]
This signature doesn't make sense, see above: Shifting a pointer by an
arbitrary amount of bytes will probably change the type of what you're
pointing to. If you shift by units of the underlying type, well, that's
peekElemOff.
[19:35:31] <chessai_> carter: i am glad we agree on the smell
I don't have the full chat log, but I think I don't even agree on the
smell, at least not at the places I've seen... :-)
Sven Panne
2018-10-30 14:41:34 UTC
Reply
Permalink
Am Di., 30. Okt. 2018 um 15:18 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
hPutBuf doesn't care about what stuff has been written into the given
buffer, it just cares about its start and its size.
Seems like a good use for Addr?
Nope, not at all: Using a free type variable like "a" in such a situation
is *the* common idiom to specify that the function doesn't care about the
type, just like "length" doesn't care about the type of the elements. If
you don't like that idiom, fine, but it has been officially enshrined in
the standard and people are using it for decades (well, almost) without any
problems, at least I haven't heard of them.

What would using Addr buy us? Addr is non-standard, and you would have to
use some cast from a Ptr somehow (the world outside GHC's innards is using
Ptr, not Addr). This would buy you exactly zero safety or clarity, and it
would only introduce API friction.
Post by Daniel Cartwright
If you have a pointer pointing to something and shift that pointer by
some bytes, you are probably pointing to something completely different, so
of course "b" and "a" have nothing to do with each other. So peekByteOff
intentionally ignores "b".
This also seems like a good use for Addr?
Nope again, see above.

I still fail to see what problem this whole proposal is actually trying to
solve...
Carter Schonwald
2018-10-30 15:31:53 UTC
Reply
Permalink
Daniel : at this point you’re not show casing examples of why Address leads
to better code than Pointer a

A good library proposal makes code *better* in an unambiguous way. As I
mentioned yesterday , that’s been lacking here. Or any improvements are
ones sven , myself and others don’t see. :)
Post by Sven Panne
Am Di., 30. Okt. 2018 um 15:18 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
hPutBuf doesn't care about what stuff has been written into the given
buffer, it just cares about its start and its size.
Seems like a good use for Addr?
Nope, not at all: Using a free type variable like "a" in such a situation
is *the* common idiom to specify that the function doesn't care about the
type, just like "length" doesn't care about the type of the elements. If
you don't like that idiom, fine, but it has been officially enshrined in
the standard and people are using it for decades (well, almost) without any
problems, at least I haven't heard of them.
What would using Addr buy us? Addr is non-standard, and you would have to
use some cast from a Ptr somehow (the world outside GHC's innards is using
Ptr, not Addr). This would buy you exactly zero safety or clarity, and it
would only introduce API friction.
Post by Daniel Cartwright
If you have a pointer pointing to something and shift that pointer by
some bytes, you are probably pointing to something completely different, so
of course "b" and "a" have nothing to do with each other. So peekByteOff
intentionally ignores "b".
This also seems like a good use for Addr?
Nope again, see above.
I still fail to see what problem this whole proposal is actually trying to
solve...
Andrew Martin
2018-10-30 15:48:46 UTC
Reply
Permalink
Look at the definition of SerializedCompact (in ghc-compact):

data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Ptr a, Word)]
, serializedCompactRoot :: Ptr a
}

The type variables on those Ptrs are a lie. The SerializedCompact needs
that phantom type variable to keep track of what type of object in a
compact region is represented by these blocks. But, the types of its two
fields are extremely misleading. When I first saw this type, I was led to
believe that I could call `peek` on the `serializedCompactRoot` field and
get a value of type `a`. You cannot actually do that since it isn't
actually a pointer to a value of that type. More correct would be:

data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Addr, Word)]
, serializedCompactRoot :: Addr
}

This better documents what's actually going on here. We don't have a bunch
of pointers to `a` values in a list. We value memory addresses that refer
to arbitrary fragments of an object on the heap.


On Tue, Oct 30, 2018 at 11:32 AM Carter Schonwald <
Post by Carter Schonwald
Daniel : at this point you’re not show casing examples of why Address
leads to better code than Pointer a
A good library proposal makes code *better* in an unambiguous way. As I
mentioned yesterday , that’s been lacking here. Or any improvements are
ones sven , myself and others don’t see. :)
Post by Sven Panne
Am Di., 30. Okt. 2018 um 15:18 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
hPutBuf doesn't care about what stuff has been written into the given
buffer, it just cares about its start and its size.
Seems like a good use for Addr?
Nope, not at all: Using a free type variable like "a" in such a situation
is *the* common idiom to specify that the function doesn't care about the
type, just like "length" doesn't care about the type of the elements. If
you don't like that idiom, fine, but it has been officially enshrined in
the standard and people are using it for decades (well, almost) without any
problems, at least I haven't heard of them.
What would using Addr buy us? Addr is non-standard, and you would have to
use some cast from a Ptr somehow (the world outside GHC's innards is using
Ptr, not Addr). This would buy you exactly zero safety or clarity, and it
would only introduce API friction.
Post by Daniel Cartwright
If you have a pointer pointing to something and shift that pointer by
some bytes, you are probably pointing to something completely different, so
of course "b" and "a" have nothing to do with each other. So peekByteOff
intentionally ignores "b".
This also seems like a good use for Addr?
Nope again, see above.
I still fail to see what problem this whole proposal is actually trying
to solve...
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
Carter Schonwald
2018-10-30 16:09:32 UTC
Reply
Permalink
This example seems more a discussion about how the ghc-compact lib could
benefit from better docs.
Post by Andrew Martin
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Ptr a, Word)]
, serializedCompactRoot :: Ptr a
}
The type variables on those Ptrs are a lie. The SerializedCompact needs
that phantom type variable to keep track of what type of object in a
compact region is represented by these blocks. But, the types of its two
fields are extremely misleading. When I first saw this type, I was led to
believe that I could call `peek` on the `serializedCompactRoot` field and
get a value of type `a`. You cannot actually do that since it isn't
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Addr, Word)]
, serializedCompactRoot :: Addr
}
This better documents what's actually going on here. We don't have a bunch
of pointers to `a` values in a list. We value memory addresses that refer
to arbitrary fragments of an object on the heap.
On Tue, Oct 30, 2018 at 11:32 AM Carter Schonwald <
Post by Carter Schonwald
Daniel : at this point you’re not show casing examples of why Address
leads to better code than Pointer a
A good library proposal makes code *better* in an unambiguous way. As I
mentioned yesterday , that’s been lacking here. Or any improvements are
ones sven , myself and others don’t see. :)
Post by Sven Panne
Am Di., 30. Okt. 2018 um 15:18 Uhr schrieb Daniel Cartwright <
Post by Daniel Cartwright
hPutBuf doesn't care about what stuff has been written into the given
buffer, it just cares about its start and its size.
Seems like a good use for Addr?
Nope, not at all: Using a free type variable like "a" in such a
situation is *the* common idiom to specify that the function doesn't care
about the type, just like "length" doesn't care about the type of the
elements. If you don't like that idiom, fine, but it has been officially
enshrined in the standard and people are using it for decades (well,
almost) without any problems, at least I haven't heard of them.
What would using Addr buy us? Addr is non-standard, and you would have
to use some cast from a Ptr somehow (the world outside GHC's innards is
using Ptr, not Addr). This would buy you exactly zero safety or clarity,
and it would only introduce API friction.
Post by Daniel Cartwright
If you have a pointer pointing to something and shift that pointer
by some bytes, you are probably pointing to something completely different,
so of course "b" and "a" have nothing to do with each other. So peekByteOff
intentionally ignores "b".
This also seems like a good use for Addr?
Nope again, see above.
I still fail to see what problem this whole proposal is actually trying
to solve...
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
Carter Schonwald
2018-10-30 16:11:30 UTC
Reply
Permalink
There’s no class constraint here, so I would instead assume I need to read
the paper / docs and source code for how heap objects are encoded here.
Changing the type to Addr vs Ptr a or Ptr void is a red herring /
irrelevant

On Tue, Oct 30, 2018 at 12:09 PM Carter Schonwald <
Post by Carter Schonwald
This example seems more a discussion about how the ghc-compact lib could
benefit from better docs.
Post by Andrew Martin
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Ptr a, Word)]
, serializedCompactRoot :: Ptr a
}
The type variables on those Ptrs are a lie. The SerializedCompact needs
that phantom type variable to keep track of what type of object in a
compact region is represented by these blocks. But, the types of its two
fields are extremely misleading. When I first saw this type, I was led to
believe that I could call `peek` on the `serializedCompactRoot` field and
get a value of type `a`. You cannot actually do that since it isn't
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Addr, Word)]
, serializedCompactRoot :: Addr
}
This better documents what's actually going on here. We don't have a
bunch of pointers to `a` values in a list. We value memory addresses that
refer to arbitrary fragments of an object on the heap.
On Tue, Oct 30, 2018 at 11:32 AM Carter Schonwald <
Post by Carter Schonwald
Daniel : at this point you’re not show casing examples of why Address
leads to better code than Pointer a
A good library proposal makes code *better* in an unambiguous way. As I
mentioned yesterday , that’s been lacking here. Or any improvements are
ones sven , myself and others don’t see. :)
Post by Sven Panne
Am Di., 30. Okt. 2018 um 15:18 Uhr schrieb Daniel Cartwright <
hPutBuf doesn't care about what stuff has been written into the
given buffer, it just cares about its start and its size.
Seems like a good use for Addr?
Nope, not at all: Using a free type variable like "a" in such a
situation is *the* common idiom to specify that the function doesn't care
about the type, just like "length" doesn't care about the type of the
elements. If you don't like that idiom, fine, but it has been officially
enshrined in the standard and people are using it for decades (well,
almost) without any problems, at least I haven't heard of them.
What would using Addr buy us? Addr is non-standard, and you would have
to use some cast from a Ptr somehow (the world outside GHC's innards is
using Ptr, not Addr). This would buy you exactly zero safety or clarity,
and it would only introduce API friction.
If you have a pointer pointing to something and shift that pointer
by some bytes, you are probably pointing to something completely different,
so of course "b" and "a" have nothing to do with each other. So peekByteOff
intentionally ignores "b".
This also seems like a good use for Addr?
Nope again, see above.
I still fail to see what problem this whole proposal is actually trying
to solve...
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
Carter Schonwald
2018-10-30 16:21:45 UTC
Reply
Permalink
Anyways. This proposal is dead.

Changing this internal stuff from Ptr to Addr doesn’t make an argument that
the code is better for it. That has not be made.

Saying ptr a is a lie is about as informative as saying virtual memory is a
lie. Or the cpu caches are a lie.

Evidence works. Saying something is a lie doesn’t.

On Tue, Oct 30, 2018 at 12:11 PM Carter Schonwald <
Post by Carter Schonwald
There’s no class constraint here, so I would instead assume I need to read
the paper / docs and source code for how heap objects are encoded here.
Changing the type to Addr vs Ptr a or Ptr void is a red herring /
irrelevant
On Tue, Oct 30, 2018 at 12:09 PM Carter Schonwald <
Post by Carter Schonwald
This example seems more a discussion about how the ghc-compact lib could
benefit from better docs.
Post by Andrew Martin
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Ptr a, Word)]
, serializedCompactRoot :: Ptr a
}
The type variables on those Ptrs are a lie. The SerializedCompact needs
that phantom type variable to keep track of what type of object in a
compact region is represented by these blocks. But, the types of its two
fields are extremely misleading. When I first saw this type, I was led to
believe that I could call `peek` on the `serializedCompactRoot` field and
get a value of type `a`. You cannot actually do that since it isn't
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Addr, Word)]
, serializedCompactRoot :: Addr
}
This better documents what's actually going on here. We don't have a
bunch of pointers to `a` values in a list. We value memory addresses that
refer to arbitrary fragments of an object on the heap.
On Tue, Oct 30, 2018 at 11:32 AM Carter Schonwald <
Post by Carter Schonwald
Daniel : at this point you’re not show casing examples of why Address
leads to better code than Pointer a
A good library proposal makes code *better* in an unambiguous way. As
I mentioned yesterday , that’s been lacking here. Or any improvements are
ones sven , myself and others don’t see. :)
Post by Sven Panne
Am Di., 30. Okt. 2018 um 15:18 Uhr schrieb Daniel Cartwright <
hPutBuf doesn't care about what stuff has been written into the
given buffer, it just cares about its start and its size.
Seems like a good use for Addr?
Nope, not at all: Using a free type variable like "a" in such a
situation is *the* common idiom to specify that the function doesn't care
about the type, just like "length" doesn't care about the type of the
elements. If you don't like that idiom, fine, but it has been officially
enshrined in the standard and people are using it for decades (well,
almost) without any problems, at least I haven't heard of them.
What would using Addr buy us? Addr is non-standard, and you would have
to use some cast from a Ptr somehow (the world outside GHC's innards is
using Ptr, not Addr). This would buy you exactly zero safety or clarity,
and it would only introduce API friction.
If you have a pointer pointing to something and shift that pointer
by some bytes, you are probably pointing to something completely different,
so of course "b" and "a" have nothing to do with each other. So peekByteOff
intentionally ignores "b".
This also seems like a good use for Addr?
Nope again, see above.
I still fail to see what problem this whole proposal is actually
trying to solve...
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
David Feuer
2018-10-30 16:25:14 UTC
Reply
Permalink
Thankfully, Carter, you're not the sole arbiter of whether a library
proposal is dead. The discussion can surely continue without you.
Post by Carter Schonwald
Anyways. This proposal is dead.
Changing this internal stuff from Ptr to Addr doesn’t make an argument
that the code is better for it. That has not be made.
Saying ptr a is a lie is about as informative as saying virtual memory is
a lie. Or the cpu caches are a lie.
Evidence works. Saying something is a lie doesn’t.
On Tue, Oct 30, 2018 at 12:11 PM Carter Schonwald <
Post by Carter Schonwald
There’s no class constraint here, so I would instead assume I need to
read the paper / docs and source code for how heap objects are encoded
here. Changing the type to Addr vs Ptr a or Ptr void is a red herring /
irrelevant
On Tue, Oct 30, 2018 at 12:09 PM Carter Schonwald <
Post by Carter Schonwald
This example seems more a discussion about how the ghc-compact lib could
benefit from better docs.
On Tue, Oct 30, 2018 at 11:48 AM Andrew Martin <
Post by Andrew Martin
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Ptr a, Word)]
, serializedCompactRoot :: Ptr a
}
The type variables on those Ptrs are a lie. The SerializedCompact needs
that phantom type variable to keep track of what type of object in a
compact region is represented by these blocks. But, the types of its two
fields are extremely misleading. When I first saw this type, I was led to
believe that I could call `peek` on the `serializedCompactRoot` field and
get a value of type `a`. You cannot actually do that since it isn't
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Addr, Word)]
, serializedCompactRoot :: Addr
}
This better documents what's actually going on here. We don't have a
bunch of pointers to `a` values in a list. We value memory addresses that
refer to arbitrary fragments of an object on the heap.
On Tue, Oct 30, 2018 at 11:32 AM Carter Schonwald <
Post by Carter Schonwald
Daniel : at this point you’re not show casing examples of why Address
leads to better code than Pointer a
A good library proposal makes code *better* in an unambiguous way. As
I mentioned yesterday , that’s been lacking here. Or any improvements are
ones sven , myself and others don’t see. :)
Post by Sven Panne
Am Di., 30. Okt. 2018 um 15:18 Uhr schrieb Daniel Cartwright <
hPutBuf doesn't care about what stuff has been written into the
given buffer, it just cares about its start and its size.
Seems like a good use for Addr?
Nope, not at all: Using a free type variable like "a" in such a
situation is *the* common idiom to specify that the function doesn't care
about the type, just like "length" doesn't care about the type of the
elements. If you don't like that idiom, fine, but it has been officially
enshrined in the standard and people are using it for decades (well,
almost) without any problems, at least I haven't heard of them.
What would using Addr buy us? Addr is non-standard, and you would
have to use some cast from a Ptr somehow (the world outside GHC's innards
is using Ptr, not Addr). This would buy you exactly zero safety or clarity,
and it would only introduce API friction.
If you have a pointer pointing to something and shift that
pointer by some bytes, you are probably pointing to something completely
different, so of course "b" and "a" have nothing to do with each other. So
peekByteOff intentionally ignores "b".
This also seems like a good use for Addr?
Nope again, see above.
I still fail to see what problem this whole proposal is actually
trying to solve...
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-30 16:35:58 UTC
Reply
Permalink
Repeating it’s a lie isn’t an argument.

Writing code and comparing it is a way to make a case. I even put some up
on phabticator. Then decided it’s actually not a useful piece of code.

I’ve spoke with a number of folks privately and I’m arriculating the lack
of suport and clear case.

I’m open to being wrong and that this proposal is great. But changing a
type signature isn’t show casing what code is improved. It’s just a proof
that the change can be made.

I need evidence. As does everyone :)
Post by David Feuer
Thankfully, Carter, you're not the sole arbiter of whether a library
proposal is dead. The discussion can surely continue without you.
On Tue, Oct 30, 2018, 12:22 PM Carter Schonwald <
Post by Carter Schonwald
Anyways. This proposal is dead.
Changing this internal stuff from Ptr to Addr doesn’t make an argument
that the code is better for it. That has not be made.
Saying ptr a is a lie is about as informative as saying virtual memory is
a lie. Or the cpu caches are a lie.
Evidence works. Saying something is a lie doesn’t.
On Tue, Oct 30, 2018 at 12:11 PM Carter Schonwald <
Post by Carter Schonwald
There’s no class constraint here, so I would instead assume I need to
read the paper / docs and source code for how heap objects are encoded
here. Changing the type to Addr vs Ptr a or Ptr void is a red herring /
irrelevant
On Tue, Oct 30, 2018 at 12:09 PM Carter Schonwald <
Post by Carter Schonwald
This example seems more a discussion about how the ghc-compact lib
could benefit from better docs.
On Tue, Oct 30, 2018 at 11:48 AM Andrew Martin <
Post by Andrew Martin
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Ptr a, Word)]
, serializedCompactRoot :: Ptr a
}
The type variables on those Ptrs are a lie. The SerializedCompact
needs that phantom type variable to keep track of what type of object in a
compact region is represented by these blocks. But, the types of its two
fields are extremely misleading. When I first saw this type, I was led to
believe that I could call `peek` on the `serializedCompactRoot` field and
get a value of type `a`. You cannot actually do that since it isn't
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Addr, Word)]
, serializedCompactRoot :: Addr
}
This better documents what's actually going on here. We don't have a
bunch of pointers to `a` values in a list. We value memory addresses that
refer to arbitrary fragments of an object on the heap.
On Tue, Oct 30, 2018 at 11:32 AM Carter Schonwald <
Post by Carter Schonwald
Daniel : at this point you’re not show casing examples of why Address
leads to better code than Pointer a
A good library proposal makes code *better* in an unambiguous way.
As I mentioned yesterday , that’s been lacking here. Or any improvements
are ones sven , myself and others don’t see. :)
Post by Sven Panne
Am Di., 30. Okt. 2018 um 15:18 Uhr schrieb Daniel Cartwright <
hPutBuf doesn't care about what stuff has been written into the
given buffer, it just cares about its start and its size.
Seems like a good use for Addr?
Nope, not at all: Using a free type variable like "a" in such a
situation is *the* common idiom to specify that the function doesn't care
about the type, just like "length" doesn't care about the type of the
elements. If you don't like that idiom, fine, but it has been officially
enshrined in the standard and people are using it for decades (well,
almost) without any problems, at least I haven't heard of them.
What would using Addr buy us? Addr is non-standard, and you would
have to use some cast from a Ptr somehow (the world outside GHC's innards
is using Ptr, not Addr). This would buy you exactly zero safety or clarity,
and it would only introduce API friction.
If you have a pointer pointing to something and shift that
pointer by some bytes, you are probably pointing to something completely
different, so of course "b" and "a" have nothing to do with each other. So
peekByteOff intentionally ignores "b".
This also seems like a good use for Addr?
Nope again, see above.
I still fail to see what problem this whole proposal is actually
trying to solve...
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
David Feuer
2018-10-30 16:38:04 UTC
Reply
Permalink
Private off-list discussions are not, were never, and will never be a part
of the proposal process, and for good reasons. Mentioning them only makes
you look like you're trying to use your connections to bypass the process.
Please don't.
Post by Carter Schonwald
Repeating it’s a lie isn’t an argument.
Writing code and comparing it is a way to make a case. I even put some up
on phabticator. Then decided it’s actually not a useful piece of code.
I’ve spoke with a number of folks privately and I’m arriculating the lack
of suport and clear case.
I’m open to being wrong and that this proposal is great. But changing a
type signature isn’t show casing what code is improved. It’s just a proof
that the change can be made.
I need evidence. As does everyone :)
Post by David Feuer
Thankfully, Carter, you're not the sole arbiter of whether a library
proposal is dead. The discussion can surely continue without you.
On Tue, Oct 30, 2018, 12:22 PM Carter Schonwald <
Post by Carter Schonwald
Anyways. This proposal is dead.
Changing this internal stuff from Ptr to Addr doesn’t make an argument
that the code is better for it. That has not be made.
Saying ptr a is a lie is about as informative as saying virtual memory
is a lie. Or the cpu caches are a lie.
Evidence works. Saying something is a lie doesn’t.
On Tue, Oct 30, 2018 at 12:11 PM Carter Schonwald <
Post by Carter Schonwald
There’s no class constraint here, so I would instead assume I need to
read the paper / docs and source code for how heap objects are encoded
here. Changing the type to Addr vs Ptr a or Ptr void is a red herring /
irrelevant
On Tue, Oct 30, 2018 at 12:09 PM Carter Schonwald <
Post by Carter Schonwald
This example seems more a discussion about how the ghc-compact lib
could benefit from better docs.
On Tue, Oct 30, 2018 at 11:48 AM Andrew Martin <
Post by Andrew Martin
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Ptr a, Word)]
, serializedCompactRoot :: Ptr a
}
The type variables on those Ptrs are a lie. The SerializedCompact
needs that phantom type variable to keep track of what type of object in a
compact region is represented by these blocks. But, the types of its two
fields are extremely misleading. When I first saw this type, I was led to
believe that I could call `peek` on the `serializedCompactRoot` field and
get a value of type `a`. You cannot actually do that since it isn't
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Addr, Word)]
, serializedCompactRoot :: Addr
}
This better documents what's actually going on here. We don't have a
bunch of pointers to `a` values in a list. We value memory addresses that
refer to arbitrary fragments of an object on the heap.
On Tue, Oct 30, 2018 at 11:32 AM Carter Schonwald <
Post by Carter Schonwald
Daniel : at this point you’re not show casing examples of why
Address leads to better code than Pointer a
A good library proposal makes code *better* in an unambiguous way.
As I mentioned yesterday , that’s been lacking here. Or any improvements
are ones sven , myself and others don’t see. :)
Post by Sven Panne
Am Di., 30. Okt. 2018 um 15:18 Uhr schrieb Daniel Cartwright <
hPutBuf doesn't care about what stuff has been written into the
given buffer, it just cares about its start and its size.
Seems like a good use for Addr?
Nope, not at all: Using a free type variable like "a" in such a
situation is *the* common idiom to specify that the function doesn't care
about the type, just like "length" doesn't care about the type of the
elements. If you don't like that idiom, fine, but it has been officially
enshrined in the standard and people are using it for decades (well,
almost) without any problems, at least I haven't heard of them.
What would using Addr buy us? Addr is non-standard, and you would
have to use some cast from a Ptr somehow (the world outside GHC's innards
is using Ptr, not Addr). This would buy you exactly zero safety or clarity,
and it would only introduce API friction.
If you have a pointer pointing to something and shift that
pointer by some bytes, you are probably pointing to something completely
different, so of course "b" and "a" have nothing to do with each other. So
peekByteOff intentionally ignores "b".
This also seems like a good use for Addr?
Nope again, see above.
I still fail to see what problem this whole proposal is actually
trying to solve...
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-30 16:45:16 UTC
Reply
Permalink
David:
Please don’t make this personal.

Either way you’re definitely correct that this is a discussion list to
inform clc decisions and or applicable library maintainers.

I’m speaking as a maintainer.of vector and primitive
Post by David Feuer
Private off-list discussions are not, were never, and will never be a part
of the proposal process, and for good reasons. Mentioning them only makes
you look like you're trying to use your connections to bypass the process.
Please don't.
On Tue, Oct 30, 2018, 12:36 PM Carter Schonwald <
Post by Carter Schonwald
Repeating it’s a lie isn’t an argument.
Writing code and comparing it is a way to make a case. I even put some up
on phabticator. Then decided it’s actually not a useful piece of code.
I’ve spoke with a number of folks privately and I’m arriculating the lack
of suport and clear case.
I’m open to being wrong and that this proposal is great. But changing a
type signature isn’t show casing what code is improved. It’s just a proof
that the change can be made.
I need evidence. As does everyone :)
Post by David Feuer
Thankfully, Carter, you're not the sole arbiter of whether a library
proposal is dead. The discussion can surely continue without you.
On Tue, Oct 30, 2018, 12:22 PM Carter Schonwald <
Post by Carter Schonwald
Anyways. This proposal is dead.
Changing this internal stuff from Ptr to Addr doesn’t make an argument
that the code is better for it. That has not be made.
Saying ptr a is a lie is about as informative as saying virtual memory
is a lie. Or the cpu caches are a lie.
Evidence works. Saying something is a lie doesn’t.
On Tue, Oct 30, 2018 at 12:11 PM Carter Schonwald <
Post by Carter Schonwald
There’s no class constraint here, so I would instead assume I need to
read the paper / docs and source code for how heap objects are encoded
here. Changing the type to Addr vs Ptr a or Ptr void is a red herring /
irrelevant
On Tue, Oct 30, 2018 at 12:09 PM Carter Schonwald <
Post by Carter Schonwald
This example seems more a discussion about how the ghc-compact lib
could benefit from better docs.
On Tue, Oct 30, 2018 at 11:48 AM Andrew Martin <
Post by Andrew Martin
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Ptr a, Word)]
, serializedCompactRoot :: Ptr a
}
The type variables on those Ptrs are a lie. The SerializedCompact
needs that phantom type variable to keep track of what type of object in a
compact region is represented by these blocks. But, the types of its two
fields are extremely misleading. When I first saw this type, I was led to
believe that I could call `peek` on the `serializedCompactRoot` field and
get a value of type `a`. You cannot actually do that since it isn't
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Addr, Word)]
, serializedCompactRoot :: Addr
}
This better documents what's actually going on here. We don't have a
bunch of pointers to `a` values in a list. We value memory addresses that
refer to arbitrary fragments of an object on the heap.
On Tue, Oct 30, 2018 at 11:32 AM Carter Schonwald <
Post by Carter Schonwald
Daniel : at this point you’re not show casing examples of why
Address leads to better code than Pointer a
A good library proposal makes code *better* in an unambiguous way.
As I mentioned yesterday , that’s been lacking here. Or any improvements
are ones sven , myself and others don’t see. :)
Post by Sven Panne
Am Di., 30. Okt. 2018 um 15:18 Uhr schrieb Daniel Cartwright <
hPutBuf doesn't care about what stuff has been written into the
given buffer, it just cares about its start and its size.
Seems like a good use for Addr?
Nope, not at all: Using a free type variable like "a" in such a
situation is *the* common idiom to specify that the function doesn't care
about the type, just like "length" doesn't care about the type of the
elements. If you don't like that idiom, fine, but it has been officially
enshrined in the standard and people are using it for decades (well,
almost) without any problems, at least I haven't heard of them.
What would using Addr buy us? Addr is non-standard, and you would
have to use some cast from a Ptr somehow (the world outside GHC's innards
is using Ptr, not Addr). This would buy you exactly zero safety or clarity,
and it would only introduce API friction.
If you have a pointer pointing to something and shift that
pointer by some bytes, you are probably pointing to something completely
different, so of course "b" and "a" have nothing to do with each other. So
peekByteOff intentionally ignores "b".
This also seems like a good use for Addr?
Nope again, see above.
I still fail to see what problem this whole proposal is actually
trying to solve...
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Sven Panne
2018-10-30 17:21:58 UTC
Reply
Permalink
Am Di., 30. Okt. 2018 um 16:48 Uhr schrieb Andrew Martin <
Post by Andrew Martin
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Ptr a, Word)]
, serializedCompactRoot :: Ptr a
}
[...]
I haven't used the ghc-compact or compact packages yet, so I can't really
comment on the details here. The question boils down to: Why does
Compact/SerializedCompact have a type parameter at all? Quickly browsing
over the Hadoock documentation of both packages doesn't make that clear to
me, but as I said: I can't comment on the design decision of someone else's
API if I don't fully understand the use cases and tradeoffs involved.

In any case: This example has exactly *nothing* to do with the proposal at
hand. If the API above uses "a" for some good reason/convenience etc. it's
perfectly OK, if not, it should better use "Ptr ()" or "Ptr Void". This is
perhaps an example of incomplete documentation and/or suboptimal API
design, but nothing more. Using Addr here wouldn't improve usability or
safety, it would just introduce a non-standard data type for nothing.

I could show you tons of APIs out in the wild where e.g. lists are used,
but where they are actually not really the right data structure for the
problem at hand. Nevertheless, this is not an argument against lists per
se, this is a problem of the API which abuses them.
Edward Kmett
2018-11-01 00:22:17 UTC
Reply
Permalink
One messy sketch of how this could proceed would be to make additional
Addr-based analogues of the report specified type-unrelated "Ptr a"
functions and install them side by side with the existing functions. This
would behave much like how we have both readsPrec and readPrec for standard
vs. GHC specific Read internals. With MINIMAL pragmas it should basically
become transparent if they are mutually defined. Since generally Storable
dictionaries aren't built out of compositions of other Storable
dictionaries, growing the class shouldn't do any measurable harm to
performance. We haven't been shy about adding new members to
report-specified classes like Bits. This doesn't strike me as much
different.

At some point in the future we can work out if it is worth it to get the
report fixed up by incorporating the Addr-based API as the default and make
the _other_ the legacy.

-Edward
It is meant as the lowest-level building block in an Addr-free world
(remember: Addr is a GHCism and is *not* mentioned anywhere in the report)
to put a few well-defined simple Haskell types into memory or read them
* Achieve 100% type safety. In the presence of raw memory access,
castPtr, C calls etc. this would be a total illusion. Forcing API users to
sprinkle tons of castPtr at every possible place over their code wouldn't
improve safety at all, it would only hurt readability.
* Handle more complicated sum/product types. How would you do this?
Respect your native ABI (i.e. automatically handle padding/alignment)?
Tightly packed? Or even handle a foreign ABI? Your own ABI? Some funny
encoding like OpenGL's packed data types? Etc. etc. You can build all of
those things in a layer above Storable, probably introducing other type
classes or some marshaling DSLs.
* Portability of the written values. This is more in the realm of
serialization libraries.
Am Di., 30. Okt. 2018 um 14:34 Uhr schrieb Daniel Cartwright <
[19:26:50] <chessai_> hPutBuf :: Handle -> Ptr a -> Int -> IO () [...]
The signature for this is actually perfect: hPutBuf doesn't care about
what stuff has been written into the given buffer, it just cares about its
The buffer will probably contain a wild mix of Haskell values or even no
Haskell values at all, but that doesn't matter. Whatever you pass as "a" or
whatever you cast from/to is probably a lie from the typing perspective. At
this level this is no problem at all.
[19:30:02] <chessai_> peekByteOff :: Ptr b -> Int -> IO a
[19:30:09] <chessai_> peekByteOff :: Addr -> Int -> IO a
[19:30:26] <chessai_> what is 'b' doing there? it's not used in any
meaningful way by peekByteOff [...]
If you have a pointer pointing to something and shift that pointer by some
bytes, you are probably pointing to something completely different, so of
course "b" and "a" have nothing to do with each other. So peekByteOff
intentionally ignores "b".
[19:32:22] <carter> pokeElemOff :: Ptr a -> Int -> a -> IO () --- way
better than peak [...]
Yes, because this is intended to be used for *arrays* of values of the
same type. Note "Elem" vs. "Byte".
[19:33:12] <carter> hvr: lets add safePeekByteOff :: Ptr a -> Int -> IO a
? [...]
This signature doesn't make sense, see above: Shifting a pointer by an
arbitrary amount of bytes will probably change the type of what you're
pointing to. If you shift by units of the underlying type, well, that's
peekElemOff.
[19:35:31] <chessai_> carter: i am glad we agree on the smell
I don't have the full chat log, but I think I don't even agree on the
smell, at least not at the places I've seen... :-)
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Anthony Cowley
2018-11-01 01:07:49 UTC
Reply
Permalink
Post by Edward Kmett
One messy sketch of how this could proceed would be to make additional
Addr-based analogues of the report specified type-unrelated "Ptr a"
functions and install them side by side with the existing functions. This
would behave much like how we have both readsPrec and readPrec for standard
vs. GHC specific Read internals. With MINIMAL pragmas it should basically
become transparent if they are mutually defined. Since generally Storable
dictionaries aren't built out of compositions of other Storable
dictionaries, growing the class shouldn't do any measurable harm to
performance.
This doesn't sound right to me. I'm probably an outlier, but I rely heavily on composite Storable instances in vinyl and Frames and general FFI situations. I don't know if a more common usage like an ad hoc record relying on the Storable instances of its fields would be greatly impacted, but this needs some investigation. More generally, I'm in agreement with the points Sven has been making in this discussion, and wouldn't like to see such an unresolved debate be resolved by imposing a performance penalty on everyone as a compromise.
Post by Edward Kmett
We haven't been shy about adding new members to
report-specified classes like Bits. This doesn't strike me as much
different.
It is similar, but I think composite Storable instances are much more common than composite Bits instances.

Anthony
Post by Edward Kmett
At some point in the future we can work out if it is worth it to get the
report fixed up by incorporating the Addr-based API as the default and make
the _other_ the legacy.
-Edward
It is meant as the lowest-level building block in an Addr-free world
(remember: Addr is a GHCism and is *not* mentioned anywhere in the report)
to put a few well-defined simple Haskell types into memory or read them
* Achieve 100% type safety. In the presence of raw memory access,
castPtr, C calls etc. this would be a total illusion. Forcing API users to
sprinkle tons of castPtr at every possible place over their code wouldn't
improve safety at all, it would only hurt readability.
* Handle more complicated sum/product types. How would you do this?
Respect your native ABI (i.e. automatically handle padding/alignment)?
Tightly packed? Or even handle a foreign ABI? Your own ABI? Some funny
encoding like OpenGL's packed data types? Etc. etc. You can build all of
those things in a layer above Storable, probably introducing other type
classes or some marshaling DSLs.
* Portability of the written values. This is more in the realm of
serialization libraries.
Am Di., 30. Okt. 2018 um 14:34 Uhr schrieb Daniel Cartwright <
[19:26:50] <chessai_> hPutBuf :: Handle -> Ptr a -> Int -> IO () [...]
The signature for this is actually perfect: hPutBuf doesn't care about
what stuff has been written into the given buffer, it just cares about its
The buffer will probably contain a wild mix of Haskell values or even no
Haskell values at all, but that doesn't matter. Whatever you pass as "a" or
whatever you cast from/to is probably a lie from the typing perspective. At
this level this is no problem at all.
[19:30:02] <chessai_> peekByteOff :: Ptr b -> Int -> IO a
[19:30:09] <chessai_> peekByteOff :: Addr -> Int -> IO a
[19:30:26] <chessai_> what is 'b' doing there? it's not used in any
meaningful way by peekByteOff [...]
If you have a pointer pointing to something and shift that pointer by some
bytes, you are probably pointing to something completely different, so of
course "b" and "a" have nothing to do with each other. So peekByteOff
intentionally ignores "b".
[19:32:22] <carter> pokeElemOff :: Ptr a -> Int -> a -> IO () --- way
better than peak [...]
Yes, because this is intended to be used for *arrays* of values of the
same type. Note "Elem" vs. "Byte".
[19:33:12] <carter> hvr: lets add safePeekByteOff :: Ptr a -> Int -> IO a
? [...]
This signature doesn't make sense, see above: Shifting a pointer by an
arbitrary amount of bytes will probably change the type of what you're
pointing to. If you shift by units of the underlying type, well, that's
peekElemOff.
[19:35:31] <chessai_> carter: i am glad we agree on the smell
I don't have the full chat log, but I think I don't even agree on the
smell, at least not at the places I've seen... :-)
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Edward Kmett
2018-11-01 06:37:35 UTC
Reply
Permalink
Post by Sven Panne
Post by Edward Kmett
One messy sketch of how this could proceed would be to make additional
Addr-based analogues of the report specified type-unrelated "Ptr a"
functions and install them side by side with the existing functions. This
would behave much like how we have both readsPrec and readPrec for
standard
Post by Edward Kmett
vs. GHC specific Read internals. With MINIMAL pragmas it should basically
become transparent if they are mutually defined. Since generally Storable
dictionaries aren't built out of compositions of other Storable
dictionaries, growing the class shouldn't do any measurable harm to
performance.
This doesn't sound right to me. I'm probably an outlier, but I rely
heavily on composite Storable instances in vinyl and Frames and general FFI
situations. I don't know if a more common usage like an ad hoc record
relying on the Storable instances of its fields would be greatly impacted,
but this needs some investigation.
Fair point. It does feel at least worth benchmarking if we do decide to go
down this path.
Post by Sven Panne
More generally, I'm in agreement with the points Sven has been making in
this discussion, and wouldn't like to see such an unresolved debate be
resolved by imposing a performance penalty on everyone as a compromise.
That said coercing copies of ~2 definitions into a class that already has 8
members seems unlikely to move the needle on this to me. If, say, 1-3% is a
cost that could never be borne then we'd never be able to get around to
fixing things like, say, sizeOf or alignment taking actively harmful
arguments, rather than just type arguments or proxies, so we might need to
consider what is an acceptable trade off in terms of leaning into the
current local optima vs. allowing for growth. Fixing those warts some day
in an eventually standardizable way would incur exactly the same amount of
overhead.

If on the other hand the cost winds up being appreciably higher than that,
then by all means its worth considering other approaches like leaving the
methods in the class alone and adding the Addr versions as top level
methods, if we decide we do want to move Addr into base. I like that option
somewhat less as it means that there is no real sane roadmap for how to go
from there to a simpler story in the future, even if we don't choose to
start down the road to standardizing that behavior prematurely today.
Post by Sven Panne
We haven't been shy about adding new members to
Post by Edward Kmett
report-specified classes like Bits. This doesn't strike me as much
different.
It is similar, but I think composite Storable instances are much more
common than composite Bits instances.
Fair, I wound up using a similar scheme for OpenGL Uniform and SSBO
serialization.

It is kind of a mess though as you need to track not just the max
alignment, you need to run through a pass computing current term alignments
in order to correctly pack and compute sizeOf. Otherwise if you stuck a
pair of Word16s after a Word32 you're stuck with Word32 alignment all the
way through, and it doesn't even manage to resemble even the worst struct
packing schemes of the C world.

It strikes me that relative to _that_ setup or evaluation overhead, the
overhead of gluing an extra couple of methods for {peek|poke}ByteOffAddr
onto a class that already has 8 fields in it is unlikely to be appreciable.

I could well be wrong.

My comment was not an attempt to shut down debate but to try to find some
way under which the proposal could plausibly proceed.

-Edward

Anthony
Post by Sven Panne
Post by Edward Kmett
At some point in the future we can work out if it is worth it to get the
report fixed up by incorporating the Addr-based API as the default and
make
Post by Edward Kmett
the _other_ the legacy.
-Edward
It is meant as the lowest-level building block in an Addr-free world
(remember: Addr is a GHCism and is *not* mentioned anywhere in the
report)
Post by Edward Kmett
to put a few well-defined simple Haskell types into memory or read them
* Achieve 100% type safety. In the presence of raw memory access,
castPtr, C calls etc. this would be a total illusion. Forcing API users
to
Post by Edward Kmett
sprinkle tons of castPtr at every possible place over their code
wouldn't
Post by Edward Kmett
improve safety at all, it would only hurt readability.
* Handle more complicated sum/product types. How would you do this?
Respect your native ABI (i.e. automatically handle padding/alignment)?
Tightly packed? Or even handle a foreign ABI? Your own ABI? Some funny
encoding like OpenGL's packed data types? Etc. etc. You can build all of
those things in a layer above Storable, probably introducing other type
classes or some marshaling DSLs.
* Portability of the written values. This is more in the realm of
serialization libraries.
Am Di., 30. Okt. 2018 um 14:34 Uhr schrieb Daniel Cartwright <
[19:26:50] <chessai_> hPutBuf :: Handle -> Ptr a -> Int -> IO () [...]
The signature for this is actually perfect: hPutBuf doesn't care about
what stuff has been written into the given buffer, it just cares about
its
Post by Edward Kmett
start and its size. Forcing castPtr Kung Fu here wouldn't buy you
The buffer will probably contain a wild mix of Haskell values or even no
Haskell values at all, but that doesn't matter. Whatever you pass as
"a" or
Post by Edward Kmett
whatever you cast from/to is probably a lie from the typing
perspective. At
Post by Edward Kmett
this level this is no problem at all.
[19:30:02] <chessai_> peekByteOff :: Ptr b -> Int -> IO a
[19:30:09] <chessai_> peekByteOff :: Addr -> Int -> IO a
[19:30:26] <chessai_> what is 'b' doing there? it's not used in any
meaningful way by peekByteOff [...]
If you have a pointer pointing to something and shift that pointer by
some
Post by Edward Kmett
bytes, you are probably pointing to something completely different, so
of
Post by Edward Kmett
course "b" and "a" have nothing to do with each other. So peekByteOff
intentionally ignores "b".
[19:32:22] <carter> pokeElemOff :: Ptr a -> Int -> a -> IO () --- way
better than peak [...]
Yes, because this is intended to be used for *arrays* of values of the
same type. Note "Elem" vs. "Byte".
[19:33:12] <carter> hvr: lets add safePeekByteOff :: Ptr a -> Int ->
IO a
Post by Edward Kmett
? [...]
This signature doesn't make sense, see above: Shifting a pointer by an
arbitrary amount of bytes will probably change the type of what you're
pointing to. If you shift by units of the underlying type, well, that's
peekElemOff.
[19:35:31] <chessai_> carter: i am glad we agree on the smell
I don't have the full chat log, but I think I don't even agree on the
smell, at least not at the places I've seen... :-)
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Sven Panne
2018-11-01 12:07:34 UTC
Reply
Permalink
[...] At some point in the future we can work out if it is worth it to get
the report fixed up by incorporating the Addr-based API as the default and
make the _other_ the legacy.
Even though this thread is slowly approaching 100 mails, I still haven't
heard a single convincing argument *why* anything should changed or *what*
exactly is broken and *how* it effects API users. I very much disagree that
there is anything to be "fixed" in that area. If you dislike the part of
the Haskell Report, you are free to build your own APIs built on Addr,
nothing is stopping you from doing that. Of course you will have some
friction to the rest of the world which is using Ptr, but this is the price
to pay when you deviate from standards.

In a nutshell: Please show me e.g. some Wiki page with facts and real
problems, not aesthetic opinions. It should be clear by now that we will
never reach a consensus on that level, so in consequence the current status
quo *must* win.

Regarding the more fancy suggestions to sizeOf/alignment (proxies, some
type Kung Fu): Remember that the FFI is part of the Haskell Report, so
unless these things are in the report, too, there is no point discussing
about such options. I'm not opposed to include such things in the report,
far from it, but these things must go in first.
Carter Schonwald
2018-11-01 17:24:45 UTC
Reply
Permalink
Sven raises a good point :

Why can’t this all be workshopped out in user space ? Plus it’s pretty
easy to ground proposals that might break stuff by ... trying to build
stuff!
Post by Sven Panne
[...] At some point in the future we can work out if it is worth it to
get the report fixed up by incorporating the Addr-based API as the default
and make the _other_ the legacy.
Even though this thread is slowly approaching 100 mails, I still haven't
heard a single convincing argument *why* anything should changed or *what*
exactly is broken and *how* it effects API users. I very much disagree that
there is anything to be "fixed" in that area. If you dislike the part of
the Haskell Report, you are free to build your own APIs built on Addr,
nothing is stopping you from doing that. Of course you will have some
friction to the rest of the world which is using Ptr, but this is the price
to pay when you deviate from standards.
In a nutshell: Please show me e.g. some Wiki page with facts and real
problems, not aesthetic opinions. It should be clear by now that we will
never reach a consensus on that level, so in consequence the current status
quo *must* win.
Regarding the more fancy suggestions to sizeOf/alignment (proxies, some
type Kung Fu): Remember that the FFI is part of the Haskell Report, so
unless these things are in the report, too, there is no point discussing
about such options. I'm not opposed to include such things in the report,
far from it, but these things must go in first.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
David Feuer
2018-10-26 20:59:16 UTC
Reply
Permalink
I think you're looking at this wrong. An Addr doesn't need to point to
anything corresponding to a Haskell value at all. It's perfectly
acceptable for an FFI call to return an Addr pointing to some C
structure somewhere that Haskell never touches at all. Instead,
Haskell code may use it only as an argument to some other FFI call.
The only real reason to *have* Addr# rather than just using Int# or
Word# is that there's no inherent guarantee that a long in C is the
same size as a pointer.
The better alternative suggested in this thread is to use Addr instead. That way, you don't have to lie about the type of the serialized data that the pointer is pointing to.
Even if I'm repeating myself: That is not lying, quite the opposite. If you e.g. use a C library with suboptimal typing (i.e. more often than not), you make the impedance matching explicit. How would you achieve that with Addr?
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Daniel Cartwright
2018-10-26 21:04:24 UTC
Reply
Permalink
Yeah, that's a good point, David.
Also, no one is talking about removing the existence of Ptr - just
providing Addr and using it where appropriate.
Carter Schonwald
2018-10-27 00:02:01 UTC
Reply
Permalink
What’s a good use you have in mind?
Post by Daniel Cartwright
Yeah, that's a good point, David.
Also, no one is talking about removing the existence of Ptr - just
providing Addr and using it where appropriate.
Post by Daniel Cartwright
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
David Feuer
2018-10-26 18:02:23 UTC
Reply
Permalink
The arithmetic parts are pretty obvious (indeed, it might be nice to add
some more arithmetic primops to treat Addr# as a uintptr_t). The rest are
much less obvious; it may make more sense to convert an Addr to a Ptr
before performing any dereferencing operations.
Post by Carter Schonwald
What api? It’s not obvious, could you spell out what you have in mind.
Relative to the phab straw man?
Post by Daniel Cartwright
there was never any hint at helping primitive, i'm not sure where you got
that from. also, the primary motivation was to avoid using 'Ptr a', where
'a' is a lie. not only that, but base seems a natural home for 'Addr', and
people can avoid incurring a dep on primitive when they just need 'Addr'.
'super useful' was never the goal - only correctness and convenience.
Yeah, i agree that Storable should not be touched.
On Fri, Oct 26, 2018 at 1:36 PM Carter Schonwald <
Post by Carter Schonwald
your perspective here is a good one
1) i absolutely agree, nothing should touch storable, whatesoever,
2) the baseline proposal is to add an Addr to Base (essentially Ptr ()),
which would be a crippled sibling of how its exposed in Data.Primitive I
guess?
3) as a litmus for "what would this acomplish/support", i was asking
"how would this get used/help base be nicer "? If
anyways: i did a strawman of what Addr ripped out of Data.Primitive.Addr
and into base would look like, and it doesn't look especially compelling /
nicer than Ptr shenanigans. Especially since to be useful in base it would
have to have a bunch of IO / ST specific operations that have the option
perhaps of using Storable to read /write at locations. At which point I
still need to have the same API surface area again in Primitive,
see https://phabricator.haskell.org/D5268 for the bare bones stuff
(doesn't type check)
the api i could expose there in base does not reduce the implementation
surface area needed for Primitve...
i'm open to being convinced otherwise, but with Sven's perspective
weighed in,
1) i dont see it being super useful within base/ghc apis, as they exist
today
2) it doesn't reduce implementation surface area burden in the Primitive
package.
so at this point im' weakly against the addition. more work, no clear
reward for me :)
Post by Sven Panne
Am Fr., 26. Okt. 2018 um 06:05 Uhr schrieb Carter Schonwald <
[...] I guess I’m just trying to say “what would the impact on base,
if every fake Ptr was moved to be Addr?” Because it’s not something which
should be done by halves.
1) [...]
2) [...]
3). [...]
The most important question is missing from this list: What are the
benefits of touching such a crucial part of our API ecosystem? There should
better be extremely good reasons, otherwise lots of annoying work and
incompatibility is generated for nothing. Reading through this thread, I
haven't seen a good motivation for touching Storable/Ptr and friends.
Perhaps I have misunderstood what the actual proposal is, initially I
thought it is just replacing various "Ptr foo" with Addr only within GHC
itself. That's fine, but the scope seems to have broadened.
Just a historical remark: Addr# is a GHCism, and so was Addr. At the
time the FFI came up, Ptr was intended to be the portable type. So yes,
"Ptr a" and "Ptr ()" are basically just Addr (modulo casts), but
intentionally so.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-26 18:13:41 UTC
Reply
Permalink
yeah, lets do that, so roughly very little impact but easy opt in.

Is the design code strawman in https://phabricator.haskell.org/D5268
acceptable?

@David Feuer <***@gmail.com> could you help me dig out where in
ghc / base / ghc-prims we expose the memmove/memcopy/memset intrinsics? I
can only seem to find the c ffi call ones,
but I know ghc itself can compile that more smartly? i started but then i
got lost, seems like everywhere in base its just a bespoked c ffi binding
introduced locally ..
Post by David Feuer
The arithmetic parts are pretty obvious (indeed, it might be nice to add
some more arithmetic primops to treat Addr# as a uintptr_t). The rest are
much less obvious; it may make more sense to convert an Addr to a Ptr
before performing any dereferencing operations.
Post by Carter Schonwald
What api? It’s not obvious, could you spell out what you have in mind.
Relative to the phab straw man?
Post by Daniel Cartwright
there was never any hint at helping primitive, i'm not sure where you
got that from. also, the primary motivation was to avoid using 'Ptr a',
where 'a' is a lie. not only that, but base seems a natural home for
'Addr', and people can avoid incurring a dep on primitive when they just
need 'Addr'.
'super useful' was never the goal - only correctness and convenience.
Yeah, i agree that Storable should not be touched.
On Fri, Oct 26, 2018 at 1:36 PM Carter Schonwald <
Post by Carter Schonwald
your perspective here is a good one
1) i absolutely agree, nothing should touch storable, whatesoever,
2) the baseline proposal is to add an Addr to Base (essentially Ptr
()), which would be a crippled sibling of how its exposed in Data.Primitive
I guess?
3) as a litmus for "what would this acomplish/support", i was asking
"how would this get used/help base be nicer "? If
anyways: i did a strawman of what Addr ripped out of
Data.Primitive.Addr and into base would look like, and it doesn't look
especially compelling / nicer than Ptr shenanigans. Especially since to be
useful in base it would have to have a bunch of IO / ST specific operations
that have the option perhaps of using Storable to read /write at
locations. At which point I still need to have the same API surface area
again in Primitive,
see https://phabricator.haskell.org/D5268 for the bare bones stuff
(doesn't type check)
the api i could expose there in base does not reduce the implementation
surface area needed for Primitve...
i'm open to being convinced otherwise, but with Sven's perspective
weighed in,
1) i dont see it being super useful within base/ghc apis, as they exist
today
2) it doesn't reduce implementation surface area burden in the
Primitive package.
so at this point im' weakly against the addition. more work, no clear
reward for me :)
Post by Sven Panne
Am Fr., 26. Okt. 2018 um 06:05 Uhr schrieb Carter Schonwald <
[...] I guess I’m just trying to say “what would the impact on base,
if every fake Ptr was moved to be Addr?” Because it’s not something which
should be done by halves.
1) [...]
2) [...]
3). [...]
The most important question is missing from this list: What are the
benefits of touching such a crucial part of our API ecosystem? There should
better be extremely good reasons, otherwise lots of annoying work and
incompatibility is generated for nothing. Reading through this thread, I
haven't seen a good motivation for touching Storable/Ptr and friends.
Perhaps I have misunderstood what the actual proposal is, initially I
thought it is just replacing various "Ptr foo" with Addr only within GHC
itself. That's fine, but the scope seems to have broadened.
Just a historical remark: Addr# is a GHCism, and so was Addr. At the
time the FFI came up, Ptr was intended to be the portable type. So yes,
"Ptr a" and "Ptr ()" are basically just Addr (modulo casts), but
intentionally so.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Carter Schonwald
2018-10-26 18:15:59 UTC
Reply
Permalink
hrmm, it looks like those aren't exposed directly to the HS layer because
of the necessary compiler time static alignment requirements for that in
code gen,
Post by Carter Schonwald
yeah, lets do that, so roughly very little impact but easy opt in.
Is the design code strawman in https://phabricator.haskell.org/D5268
acceptable?
@David Feuer <***@gmail.com> could you help me dig out where in
ghc / base / ghc-prims we expose the memmove/memcopy/memset intrinsics? I
can only seem to find the c ffi call ones,
but I know ghc itself can compile that more smartly? i started but then i
got lost, seems like everywhere in base its just a bespoked c ffi binding
introduced locally ..
Post by David Feuer
The arithmetic parts are pretty obvious (indeed, it might be nice to add
some more arithmetic primops to treat Addr# as a uintptr_t). The rest are
much less obvious; it may make more sense to convert an Addr to a Ptr
before performing any dereferencing operations.
On Fri, Oct 26, 2018, 1:55 PM Carter Schonwald <
Post by Carter Schonwald
What api? It’s not obvious, could you spell out what you have in mind.
Relative to the phab straw man?
Post by Daniel Cartwright
there was never any hint at helping primitive, i'm not sure where you
got that from. also, the primary motivation was to avoid using 'Ptr a',
where 'a' is a lie. not only that, but base seems a natural home for
'Addr', and people can avoid incurring a dep on primitive when they just
need 'Addr'.
'super useful' was never the goal - only correctness and convenience.
Yeah, i agree that Storable should not be touched.
On Fri, Oct 26, 2018 at 1:36 PM Carter Schonwald <
Post by Carter Schonwald
your perspective here is a good one
1) i absolutely agree, nothing should touch storable, whatesoever,
2) the baseline proposal is to add an Addr to Base (essentially Ptr
()), which would be a crippled sibling of how its exposed in Data.Primitive
I guess?
3) as a litmus for "what would this acomplish/support", i was asking
"how would this get used/help base be nicer "? If
anyways: i did a strawman of what Addr ripped out of
Data.Primitive.Addr and into base would look like, and it doesn't look
especially compelling / nicer than Ptr shenanigans. Especially since to be
useful in base it would have to have a bunch of IO / ST specific operations
that have the option perhaps of using Storable to read /write at
locations. At which point I still need to have the same API surface area
again in Primitive,
see https://phabricator.haskell.org/D5268 for the bare bones stuff
(doesn't type check)
the api i could expose there in base does not reduce the
implementation surface area needed for Primitve...
i'm open to being convinced otherwise, but with Sven's perspective
weighed in,
1) i dont see it being super useful within base/ghc apis, as they
exist today
2) it doesn't reduce implementation surface area burden in the
Primitive package.
so at this point im' weakly against the addition. more work, no clear
reward for me :)
Post by Sven Panne
Am Fr., 26. Okt. 2018 um 06:05 Uhr schrieb Carter Schonwald <
[...] I guess I’m just trying to say “what would the impact on base,
if every fake Ptr was moved to be Addr?” Because it’s not something which
should be done by halves.
1) [...]
2) [...]
3). [...]
The most important question is missing from this list: What are the
benefits of touching such a crucial part of our API ecosystem? There should
better be extremely good reasons, otherwise lots of annoying work and
incompatibility is generated for nothing. Reading through this thread, I
haven't seen a good motivation for touching Storable/Ptr and friends.
Perhaps I have misunderstood what the actual proposal is, initially I
thought it is just replacing various "Ptr foo" with Addr only within GHC
itself. That's fine, but the scope seems to have broadened.
Just a historical remark: Addr# is a GHCism, and so was Addr. At the
time the FFI came up, Ptr was intended to be the portable type. So yes,
"Ptr a" and "Ptr ()" are basically just Addr (modulo casts), but
intentionally so.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Sven Panne
2018-10-26 17:18:01 UTC
Reply
Permalink
Am Fr., 26. Okt. 2018 um 05:28 Uhr schrieb Carter Schonwald <
[...] Ptr Void
Corresponds to a memory address you don’t want to read or write to.
Hmmm, I haven't seen that much in the wild...

Ptr () corresponds to a memory location that’s pretty boring to read /
write to
The intention in lots of APIs is quite different: A "Ptr ()" is a pointer
to some memory of unknown/externally specified format, *and* the consumer
of the API should be forced to insert explicit casts, for whatever reason.
This can be a good idea, but it can be *extremely* annoying, too, it
depends. If you don't want to force casts upon your API users, you use "Ptr
a".
David Feuer
2018-10-26 03:29:31 UTC
Reply
Permalink
Ptr Word8 is not (just) a pointer to byte-addressable memory. It's
specifically a pointer to something representing an 8-bit unsigned integer.
If you use a Ptr Word8 for the address of a floating point value, then you
are *wrong* (or doing something very weird, anyway). To quote the
documentation,

A value of type Ptr a represents a pointer to an object, or an array of
objects, which may be marshalled to or from Haskell values of type a.
Post by Carter Schonwald
... when is a valid pointer not going to point at byte addressable memory
on memory architectures ghc can support or target?
Post by Daniel Cartwright
Now, one could argue that `Ptr ()` isn't a lie, it sort of reads like C's
void pointer. But surely something like `Ptr Word8` is a lie, when it is
not actually a Ptr to Word8 values.
Post by Daniel Cartwright
yes, only the type and its instances should be moved as far as i'm aware.
Also, it's more than just base.
https://hackage.haskell.org/package/ghc-compact-0.1.0.0/docs/GHC-Compact-Serialized.html#t:SerializedCompact
https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-IO-Handle.html
in GHC.Stats, the foreign import "getRTSStats" has `Ptr () -> IO ()`,
this Ptr () is also a lie
These are just off the top of my head, there are more
On Thu, Oct 25, 2018 at 6:46 PM Carter Schonwald <
Post by Carter Schonwald
hrmm, what are the pieces of base that are using Ptr when they really
should be using Addr? This would help me understand what would be made
better in base :)
Post by David Feuer
We shouldn't really need to move anything into base except Addr and
its base instances.
On Oct 25, 2018 5:59 PM, "Carter Schonwald" <
Indeed. The monad transformer instances for primmonad need to live in
primmonad OR transformers to avoid orphans.
Either way, unless transformers moves into base (unlikely), no way
anything using prim monad will.
On Thu, Oct 25, 2018 at 3:34 PM Andrew Martin <
Post by Andrew Martin
I like the idea of moving the type Addr into base. But we cannot move
the entire module since it has functions that talk about PrimMonad, and we
definitely don't want to move that into base.
On Thu, Oct 25, 2018 at 11:25 AM Daniel Cartwright <
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is used
in place of 'Addr', because in base there is no 'Addr', only 'Addr#'. The
problem lies in the fact that many of these uses of 'Ptr a' are lying; the
'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Henning Thielemann
2018-10-26 09:15:02 UTC
Reply
Permalink
Post by David Feuer
Ptr Word8 is not (just) a pointer to byte-addressable memory. It's
specifically a pointer to something representing an 8-bit unsigned
integer. If you use a Ptr Word8 for the address of a floating point
value, then you are *wrong* (or doing something very weird, anyway). To
quote the documentation,
A value of type Ptr a represents a pointer to an object, or an array of
objects, which may be marshalled to or from Haskell values of type a.
Interesting observations.

There are the Storable methods

peekByteOff :: Ptr b -> Int -> IO a
pokeByteOff :: Ptr b -> Int -> a -> IO ()

They ignore the target types of their pointers. Should be Addr, then, too?

And if we are touching Storable class, how about passing Proxy's to sizeOf
and alignment instead of undefined values? Maybe we should add new methods
to Storable class with default implementations that redirect to the old
methods.
David Feuer
2018-10-26 10:16:15 UTC
Reply
Permalink
While we're in that realm, it would be nice to find a mechanism that will
explain what we need for both Storable (stick something at an Addr address)
and Primitive (stick something in a MutableByteArray). The current
situation is rather annoying. Can the compiler help?

On Fri, Oct 26, 2018, 5:15 AM Henning Thielemann <
Post by Henning Thielemann
Post by David Feuer
Ptr Word8 is not (just) a pointer to byte-addressable memory. It's
specifically a pointer to something representing an 8-bit unsigned
integer. If you use a Ptr Word8 for the address of a floating point
value, then you are *wrong* (or doing something very weird, anyway). To
quote the documentation,
A value of type Ptr a represents a pointer to an object, or an array of
objects, which may be marshalled to or from Haskell values of type a.
Interesting observations.
There are the Storable methods
peekByteOff :: Ptr b -> Int -> IO a
pokeByteOff :: Ptr b -> Int -> a -> IO ()
They ignore the target types of their pointers. Should be Addr, then, too?
And if we are touching Storable class, how about passing Proxy's to sizeOf
and alignment instead of undefined values? Maybe we should add new methods
to Storable class with default implementations that redirect to the old
methods.
Carter Schonwald
2018-10-26 13:19:49 UTC
Reply
Permalink
The law of Prim is “whatever is best for vector ”, which is really about
making sure it’s easy to write soa and aos memory layouts representations
for vector. It has nothing to do with storable. Storable is for fixed size
c struct mappable values. That they do similar things api wise is a trick
rather than a connection.

Either way that’s orthogonal to Ptr and Adr.
Post by David Feuer
While we're in that realm, it would be nice to find a mechanism that will
explain what we need for both Storable (stick something at an Addr address)
and Primitive (stick something in a MutableByteArray). The current
situation is rather annoying. Can the compiler help?
On Fri, Oct 26, 2018, 5:15 AM Henning Thielemann <
Post by Henning Thielemann
Post by David Feuer
Ptr Word8 is not (just) a pointer to byte-addressable memory. It's
specifically a pointer to something representing an 8-bit unsigned
integer. If you use a Ptr Word8 for the address of a floating point
value, then you are *wrong* (or doing something very weird, anyway). To
quote the documentation,
A value of type Ptr a represents a pointer to an object, or an array of
objects, which may be marshalled to or from Haskell values of type a.
Interesting observations.
There are the Storable methods
peekByteOff :: Ptr b -> Int -> IO a
pokeByteOff :: Ptr b -> Int -> a -> IO ()
They ignore the target types of their pointers. Should be Addr, then, too?
And if we are touching Storable class, how about passing Proxy's to sizeOf
and alignment instead of undefined values? Maybe we should add new methods
to Storable class with default implementations that redirect to the old
methods.
Sven Panne
2018-10-26 17:11:51 UTC
Reply
Permalink
Am Fr., 26. Okt. 2018 um 11:15 Uhr schrieb Henning Thielemann <
[...] There are the Storable methods
peekByteOff :: Ptr b -> Int -> IO a
pokeByteOff :: Ptr b -> Int -> a -> IO ()
They ignore the target types of their pointers.
... and for a good reason: This was intentionally specified this way to
avoid the castPtr-Kung-Fu which would arise if the pointer arguments were
e.g. "Ptr ()". Remember: You are on a totally unsafe level here, anyway, so
adding tons of casts would not really help here much.
[...] And if we are touching Storable class, [...]
I really hope that Storable remains *totally* untouched, at least in the
sense that it is only changed in a 100% backwards-compatible away.
Otherwise basically the whole Haskell ecosystem with its tons of native
bindings will explode... There is nothing wrong with a new class, but this
one is effectively "untouchable".
Henning Thielemann
2018-11-03 06:56:17 UTC
Reply
Permalink
Post by Henning Thielemann
There are the Storable methods
peekByteOff :: Ptr b -> Int -> IO a
pokeByteOff :: Ptr b -> Int -> a -> IO ()
They ignore the target types of their pointers. Should be Addr, then, too?
Thinking about it ... these functions are intended for access of record
fields. Then the following type signatures would have been better:

peekField :: Ptr b -> Offset b a -> IO a
pokeField :: Ptr b -> Offset b a -> a -> IO ()

newtype Offset b a = Offset Int

This way we had more type safety and no need for Addr or lying Ptr's.
Carter Schonwald
2018-11-03 12:49:27 UTC
Reply
Permalink
That’s not a bad design pattern. I think eds struct Lib is sortah similar
to that.

On Sat, Nov 3, 2018 at 2:56 AM Henning Thielemann <
Post by Henning Thielemann
Post by Henning Thielemann
There are the Storable methods
peekByteOff :: Ptr b -> Int -> IO a
pokeByteOff :: Ptr b -> Int -> a -> IO ()
They ignore the target types of their pointers. Should be Addr, then,
too?
Thinking about it ... these functions are intended for access of record
peekField :: Ptr b -> Offset b a -> IO a
pokeField :: Ptr b -> Offset b a -> a -> IO ()
newtype Offset b a = Offset Int
This way we had more type safety and no need for Addr or lying Ptr's.
Henning Thielemann
2018-11-03 13:04:17 UTC
Reply
Permalink
That’s not a bad design pattern. I think eds struct Lib is sortah similar to that. 
What is "eds struct Lib" ?
Oliver Charles
2018-11-03 13:12:45 UTC
Reply
Permalink
http://hackage.haskell.org/package/structs
On Sat, Nov 3, 2018 at 1:04 PM Henning Thielemann
That’s not a bad design pattern. I think eds struct Lib is sortah similar to that.
What is "eds struct Lib" ?_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Daniel Cartwright
2018-10-26 00:19:56 UTC
Reply
Permalink
Oh, another motivation might be: users wish to use `Addr` without incurring
a dependency on `primitive`.
Post by Daniel Cartwright
Motivation: There are a lot of places in base where 'Ptr a' is used in
place of 'Addr', because in base there is no 'Addr', only 'Addr#'. The
problem lies in the fact that many of these uses of 'Ptr a' are lying; the
'a' value is meaningless. Authors of functions therein have used things
like 'Ptr ()', 'Ptr Word8', 'Ptr a', but these types do not mean what they
say they mean - they're just Addr. There are probably other motivations for
this that I can't think of off the top of my head right now.
Loading...