-
Notifications
You must be signed in to change notification settings - Fork 189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improving sendMsg and recvMsg #445
Conversation
Yes, that's what I had in mind. Do you agree that it is an improvement? |
But also the same change for the Windows version of the code. |
Network/Socket/Posix/Cmsg.hsc
Outdated
@@ -87,24 +88,27 @@ filterCmsg cid cmsgs = filter (\cmsg -> cmsgId cmsg == cid) cmsgs | |||
-- Each control message type has a numeric 'CmsgId' and a 'Storable' | |||
-- data representation. | |||
class Storable a => ControlMessage a where | |||
controlMessageId :: a -> CmsgId | |||
controlMessageId :: Proxy a -> CmsgId |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way, in similar situations I see other Haskell modules using a universally-quantified type variable here, instead of explicit Proxy
. It makes no difference in practice. Not sure which is better style.
controlMessageId :: Proxy a -> CmsgId | |
controlMessageId :: p a -> CmsgId |
Of course we still need a concrete phantom type (such as Proxy a
) at the call sites.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't even need the Proxy argument if we drop the support for GHC 8.0 (cf. https://ryanglscott.github.io/2019/02/06/proxy-arguments-in-class-methods/). In general, polymorphic proxy type in class methods is not necessarily a good idea since it prevents GeneralisedNewtypeDeriving but I guess it doesn't matter here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean "drop the support for GHC 7.x"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did mean GHC 8.0. GHC 8.0 doesn't support the following definition even with AllowAmbiguousTypes
:
class C a where
foo :: Int
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I read the blog post, and it is quite interesting material, but I don't see a compelling need for newtype deriving with socket Control message structures, so we can go with the abstract proxy
without fear, but the concrete Proxy
is perhaps in fact less restrictive. The deriving issues don't come up, and a programmer passing undefined :: Proxy a
rather than Proxy :: Proxy a
deserves any resulting breakage.
So I'd keep it simple and stick with Proxy a
and not yet require the fancier techniques that need much more recent advanced GHC features.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does look like GHC 8.0 supports the simple signature with no argument. Running stack ghci --resolver lts-7.24
I get GHC 8.0.1, which handles the form with no arguments:
GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help
Prelude> :set -XTypeApplications
Prelude> :set -XAllowAmbiguousTypes
Prelude> class C a where { foo :: Int }
Prelude> instance C Int where { foo = 0 }
Prelude> instance C Char where { foo = 1 }
Prelude> foo @Int
0
Prelude> foo @Char
1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But, it breaks GeneralizedNewtypeDeriving
with GHC prior to 8.8. Do we care?
Here's the error with 8.6.5:
GHCi, version 8.6.5: http://www.haskell.org/ghc/ :? for help
Prelude> :set -XTypeApplications
Prelude> :set -XAllowAmbiguousTypes
Prelude> :set -XGeneralizedNewtypeDeriving
Prelude> class C a where { foo :: Int }
Prelude> instance C Int where { foo = 0 }
Prelude> instance C Char where { foo = 1 }
Prelude> foo @Int
0
Prelude> foo @Char
1
Prelude> newtype Bar = Bar Int deriving(C)
<interactive>:9:32: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘foo’
prevents the constraint ‘(C a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance C Bar -- Defined at <interactive>:9:32
instance [safe] C Char -- Defined at <interactive>:6:10
instance [safe] C Int -- Defined at <interactive>:5:10
• In the third argument of ‘GHC.Prim.coerce’, namely ‘foo’
In the expression: GHC.Prim.coerce @Int @Int foo :: Int
In an equation for ‘foo’:
foo = GHC.Prim.coerce @Int @Int foo :: Int
When typechecking the code for ‘foo’
in a derived instance for ‘C Bar’:
To see the code I am typechecking, use -ddump-deriv
and success with 8.8.3:
GHCi, version 8.8.3: https://www.haskell.org/ghc/ :? for help
Prelude> :set -XGeneralizedNewtypeDeriving
Prelude> :set -XTypeApplications
Prelude> :set -XAllowAmbiguousTypes
Prelude> class C a where { foo :: Int }
Prelude> instance C Int where { foo = 0 }
Prelude> instance C Char where { foo = 1 }
Prelude> foo @Int
0
Prelude> foo @Char
1
Prelude> newtype Bar = Bar Int deriving(C)
Prelude> foo @Bar
0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. GHC 8.0 is supported. So, I prefer to controlMessageId :: CmsgId
with AllowAmbiguousTypes
and TypeApplications
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need deriving(ControlMessage)
? I don't think so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works for me. I don't think that lack of support for newtype deriving in GHC 8.0–8.6 is a significant drawback, especially since Cmsg
is a new interface with no legacy users.
Network/Socket/Posix/Cmsg.hsc
Outdated
encodeCmsg x = unsafeDupablePerformIO $ do | ||
bs <- create siz $ \p0 -> do | ||
let p = castPtr p0 | ||
poke p x | ||
return $ Cmsg (controlMessageId x) bs | ||
let cmsid = controlMessageId (Proxy :: Proxy a) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, and entirely cosmetic, with -XTypeApplications
one could also, here and in decodeCmsg
, write:
let cmsid = controlMessageId (Proxy :: Proxy a) | |
let cmsid = controlMessageId $ Proxy @a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TypeApplications
was introduced in GHC 8.0.1. Since network
v4 supports GHC 8 only, we can use it. But I don't know which is better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a matter of style really, whichever you find more to your liking. There are more compelling uses of type applications, this one is not one of them, just cosmetic.
@Mistuke Please give a look at the CI results: https://ci.appveyor.com/project/eborden/network/builds/32030872 Can we get |
@vdukhovni Yes, this is improvement! Thank you for your suggestion! |
We can, all the tests pass locally for me so it must be something with the AppVeyor network setup. I'll take a look tomorrow night along with simplifying the buffer code. |
I pushed the commit to use AllowAmbiguousTypes and TypeApplications. |
Looks good. |
@Mistuke Here is todo on Windows:
|
I'm not really sure what's doing on with AppVeyor... If I set If I set Both of which are not according to https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options So I wonder if they're not supported but |
Anyone got any thoughts? |
Sorry, I have minimal Windows development experience, and even less with AppVeyor. Rumour has it there's some way to debug AppVeyor interactively. I have no idea how. |
@Mistuke Let's keep item 1 undone. Would you tackle item 2 and item 3? |
@kazu-yamamoto yeah I will push those today |
This PR has been merged. Thank you, guys, for your contributions! |
@vdukhovni Is this
Proxy
usage what you suggested?@Mistuke Would you add commits to simplify the code in this PR?