Hi All, I'm pleased to announce the release of network-address v0.2.0. The library provides data structures and textual representation of network addresses (IPv4, IPv6, subnets). Major changes in this release: * Revised Address type class (readAddress was moved out of the class, readsAddress :: String -> ReadS a was added for better error reporting) * Better support for IPv6 parsing (compressed zeroes). * Implementation of RFC5952 (a recommendation for IPv6 text representation). Most notably showAddress for IPv6 compresses zeroes. Example GHCi session: *Data.Network.Address> let ip = readAddress "2001:db8:0:0:0::1" :: IPv6 *Data.Network.Address> ip IPv6 2306139568115548160 1 *Data.Network.Address> showAddress ip "2001:db8::1" *Data.Network.Address> let subnet = readSubnet "2001:db8::1/56" :: IPSubnet IPv6 *Data.Network.Address> showSubnet subnet "2001:db8::/56" *Data.Network.Address> ip `member` subnet True Planned for the next release: * Support for parsing IPv4 notation embedded in IPv6 (e.g. "::192.168.1.1") * Performance optimisations - IPv6 parsing/pretty printing is quite slow due to zero compression (>2x speed decrease) The next release will likely be v1.0.0 as there isn't much to add. I'd like to keep the API stable in that version, I welcome any feedback regarding the API (or otherwise). Hackage: http://hackage.haskell.org/package/network-address GitHub: https://github.com/sebnow/haskell-network-address Regards, Sebastian
On 7 September 2011 20:03, Sebastian Nowicki <sebnow@gmail.com> wrote:
Hi All,
I'm pleased to announce the release of network-address v0.2.0. The library provides data structures and textual representation of network addresses (IPv4, IPv6, subnets).
Major changes in this release:
* Revised Address type class (readAddress was moved out of the class, readsAddress :: String -> ReadS a was added for better error reporting) * Better support for IPv6 parsing (compressed zeroes). * Implementation of RFC5952 (a recommendation for IPv6 text representation). Most notably showAddress for IPv6 compresses zeroes.
Example GHCi session:
*Data.Network.Address> let ip = readAddress "2001:db8:0:0:0::1" :: IPv6 *Data.Network.Address> ip IPv6 2306139568115548160 1 *Data.Network.Address> showAddress ip "2001:db8::1" *Data.Network.Address> let subnet = readSubnet "2001:db8::1/56" :: IPSubnet IPv6 *Data.Network.Address> showSubnet subnet "2001:db8::/56" *Data.Network.Address> ip `member` subnet True
Hi, given that readAddress can parse the output of showAddress, and readSubnet can parse the output of showSubnet, is there any reason not to use these for the implementation of Show and Read instances? I notice that currently you deriving Show and Read instances: -- |The abstract data structure to represent an IPv4 address. data IPv4 = IPv4 !Word32 deriving (Eq, Ord, Bounded, Show, Read) -- |The abstract data structure to represent an IPv6 address. data IPv6 = IPv6 !Word64 !Word64 deriving (Eq, Ord, Show, Read) resulting in strings like "IPv6 2306139568115548160 1" above. I can't really see a use for that big number representation (other than for debugging the library...) so why not just use your existing show*/read* functions?
Planned for the next release:
* Support for parsing IPv4 notation embedded in IPv6 (e.g. "::192.168.1.1")
is the result a value of type IPv4 or IPv6? For an IPv4-Compatible address I'd expect the result to be IPv4. It might also be useful to add a conversion function to turn an IPv4 address into an IPv4-Mapped IPv6 address. cheers, Conrad.
* Performance optimisations - IPv6 parsing/pretty printing is quite slow due to zero compression (>2x speed decrease)
The next release will likely be v1.0.0 as there isn't much to add. I'd like to keep the API stable in that version, I welcome any feedback regarding the API (or otherwise).
Hackage: http://hackage.haskell.org/package/network-address GitHub: https://github.com/sebnow/haskell-network-address
Regards, Sebastian
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
On 8 September 2011 12:19, Conrad Parker <conrad@metadecks.org> wrote:
given that readAddress can parse the output of showAddress, and readSubnet can parse the output of showSubnet, is there any reason not to use these for the implementation of Show and Read instances?
My guess is that since showAddress and readsAddress are class-based, there might be some defaulting issues if you use them. Also, unless the constructor isn't exported, isn't it usually preferable to have Show and Read instances produce/use actual values directly? -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com
On 8 September 2011 10:35, Ivan Lazar Miljenovic <ivan.miljenovic@gmail.com> wrote:
On 8 September 2011 12:19, Conrad Parker <conrad@metadecks.org> wrote:
given that readAddress can parse the output of showAddress, and readSubnet can parse the output of showSubnet, is there any reason not to use these for the implementation of Show and Read instances?
My guess is that since showAddress and readsAddress are class-based, there might be some defaulting issues if you use them.
well, then remove them from the class interface and just use the Read and Show classes ...
Also, unless the constructor isn't exported, isn't it usually preferable to have Show and Read instances produce/use actual values directly?
sure, but the roundtripping seems fairly unambiguous here. Conrad.
On Thu, Sep 8, 2011 at 10:19 AM, Conrad Parker <conrad@metadecks.org> wrote:
On 7 September 2011 20:03, Sebastian Nowicki <sebnow@gmail.com> wrote:
Hi All,
I'm pleased to announce the release of network-address v0.2.0. The library provides data structures and textual representation of network addresses (IPv4, IPv6, subnets).
Major changes in this release:
* Revised Address type class (readAddress was moved out of the class, readsAddress :: String -> ReadS a was added for better error reporting) * Better support for IPv6 parsing (compressed zeroes). * Implementation of RFC5952 (a recommendation for IPv6 text representation). Most notably showAddress for IPv6 compresses zeroes.
Example GHCi session:
*Data.Network.Address> let ip = readAddress "2001:db8:0:0:0::1" :: IPv6 *Data.Network.Address> ip IPv6 2306139568115548160 1 *Data.Network.Address> showAddress ip "2001:db8::1" *Data.Network.Address> let subnet = readSubnet "2001:db8::1/56" :: IPSubnet IPv6 *Data.Network.Address> showSubnet subnet "2001:db8::/56" *Data.Network.Address> ip `member` subnet True
Hi,
given that readAddress can parse the output of showAddress, and readSubnet can parse the output of showSubnet, is there any reason not to use these for the implementation of Show and Read instances?
No reason other than semantics. I did originally provide custom Address/Subnet instances which just parsed/printed plain addresses/subnets. After reading the documentation of Show, which states that "the result of show is a syntactically correct Haskell expression", I decided to expose a read function which acted as a constructor. That resulted in show actually producing "readIPv4 \"192.168.1.1\"", but that seemed silly so I opted for the current solution. I don't know if it's generally accepted to provide Read/Show instances which don't parse/print Haskell syntax.
I notice that currently you deriving Show and Read instances:
-- |The abstract data structure to represent an IPv4 address. data IPv4 = IPv4 !Word32 deriving (Eq, Ord, Bounded, Show, Read)
-- |The abstract data structure to represent an IPv6 address. data IPv6 = IPv6 !Word64 !Word64 deriving (Eq, Ord, Show, Read)
resulting in strings like "IPv6 2306139568115548160 1" above. I can't really see a use for that big number representation (other than for debugging the library...) so why not just use your existing show*/read* functions?
Planned for the next release:
* Support for parsing IPv4 notation embedded in IPv6 (e.g. "::192.168.1.1")
is the result a value of type IPv4 or IPv6? For an IPv4-Compatible address I'd expect the result to be IPv4. It might also be useful to add a conversion function to turn an IPv4 address into an IPv4-Mapped IPv6 address.
Technically it's an IPv6 address, "::192.168.1.1" isn't a valid IPv4 string (hence parsing should fail). You can convert from one address to another using toAddress . fromAddress, i.e.: (toAddress . fromAddress $ (readAddress "192.168.1.1" :: IPv4)) :: IPv6
On Thu, Sep 8, 2011 at 3:23 PM, Sebastian Nowicki <sebnow@gmail.com> wrote:
I don't know if it's generally accepted to provide Read/Show instances which don't parse/print Haskell syntax.
It's quite common, and several "standard" libraries do it. Handle for example has a (fairly useless) Show instance. Whether it's a good idea or not is another question :)
Planned for the next release:
* Support for parsing IPv4 notation embedded in IPv6 (e.g. "::192.168.1.1")
is the result a value of type IPv4 or IPv6? For an IPv4-Compatible address I'd expect the result to be IPv4. It might also be useful to add a conversion function to turn an IPv4 address into an IPv4-Mapped IPv6 address.
Technically it's an IPv6 address, "::192.168.1.1" isn't a valid IPv4 string (hence parsing should fail). You can convert from one address to another using toAddress . fromAddress, i.e.:
(toAddress . fromAddress $ (readAddress "192.168.1.1" :: IPv4)) :: IPv6
If these sorts of type coercions are often necessary, maybe you should just expose read(s)IPv4 and toIPv6 and friends?
On Wed, Sep 7, 2011 at 1:03 PM, Sebastian Nowicki <sebnow@gmail.com> wrote:
The next release will likely be v1.0.0 as there isn't much to add. I'd like to keep the API stable in that version, I welcome any feedback regarding the API (or otherwise).
The main problem is lacking an effective way to parse addresses from strings - the readAddress interface is unsafe and doesn't give the remainder of the string. Consider using the ReadS convention, providing a function readsAddress :: String -> [(a,String)] which provides all possible parses (usually at most one) and the remainder of the string. Then users can parse addresses followed by other data easily. I'm actually also not clear how I'd actually *use* one of these addresses with any network library. Regarding the whole read/show question, there's some dispute about what those two functions are actually supposed to do. It therefore seems sensible to have functions explicitly for transforming into the standard string representations of addresses, rather than the read/show functions which are basically permitted to do whatever they like.
On 8 September 2011 23:05, Ben Millwood <haskell@benmachine.co.uk> wrote:
On Wed, Sep 7, 2011 at 1:03 PM, Sebastian Nowicki <sebnow@gmail.com> wrote:
The next release will likely be v1.0.0 as there isn't much to add. I'd like to keep the API stable in that version, I welcome any feedback regarding the API (or otherwise).
The main problem is lacking an effective way to parse addresses from strings - the readAddress interface is unsafe and doesn't give the remainder of the string. Consider using the ReadS convention, providing a function readsAddress :: String -> [(a,String)] which provides all possible parses (usually at most one) and the remainder of the string. Then users can parse addresses followed by other data easily.
There is one, in the Address class; readAddress just uses readsAddress. -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com
On Thu, Sep 8, 2011 at 2:05 PM, Ben Millwood <haskell@benmachine.co.uk> wrote:
The main problem is lacking an effective way to parse addresses from strings - the readAddress interface is unsafe and doesn't give the remainder of the string. Consider using the ReadS convention, providing a function readsAddress :: String -> [(a,String)] which provides all possible parses (usually at most one) and the remainder of the string. Then users can parse addresses followed by other data easily.
Oh, ignore this. The haddock docs hadn't built so I used cabal unpack to take a look, but I evidently haven't updated recently and got 0.1.0 instead :( The other points still stand, and also I'd point out that Subnet could also be implemented with type families rather than MPTCs+fundeps.
On Thu, Sep 8, 2011 at 9:05 PM, Ben Millwood <haskell@benmachine.co.uk> wrote:
On Wed, Sep 7, 2011 at 1:03 PM, Sebastian Nowicki <sebnow@gmail.com> wrote:
The next release will likely be v1.0.0 as there isn't much to add. I'd like to keep the API stable in that version, I welcome any feedback regarding the API (or otherwise).
The main problem is lacking an effective way to parse addresses from strings - the readAddress interface is unsafe and doesn't give the remainder of the string. Consider using the ReadS convention, providing a function readsAddress :: String -> [(a,String)] which provides all possible parses (usually at most one) and the remainder of the string. Then users can parse addresses followed by other data easily.
I'm actually also not clear how I'd actually *use* one of these addresses with any network library.
I probably should have looked into this more before creating new data types. I was focusing on efficient/convenient data storage (e.g. database) rather than using it in a networking library. Network.Socket has two address types: type HostAddress = Word32 type HostAddress6 = (Word32, Word32, Word32, Word32) For IPv4 it's pretty easy to convert (although ideally you shouldn't have to): *Data.Network.Address Network.Socket> let ip = readAddress "8.8.8.8" :: IPv4 *Data.Network.Address Network.Socket> inet_ntoa . fromInteger . fromAddress $ ip "8.8.8.8" And of course you can just deconstruct IPv4: *Data.Network.Address Network.Socket> let (IPv4 ip') = ip in inet_ntoa ip' "8.8.8.8" IPv6 isn't compatible with HostAddress6 though. Maybe it'd be a good idea to just write Address instances for HostAddress and HostAddress6. Is there any other networking library that should be supported? Regarding using type families for subnets, I wasn't aware of them. I didn't like the idea of using MPTC and fund eps, but I couldn't think of a more elegant solution. I'll read up on it. Thanks.
participants (4)
-
Ben Millwood -
Conrad Parker -
Ivan Lazar Miljenovic -
Sebastian Nowicki