Pointer equality for nullary constructors

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

Pointer equality for nullary constructors

David Feuer
Can I use reallyUnsafePtrEquality# reliably to identify whether a value is a nullary constructor of a particular type? For example, if I have

data Foo = Foo

Can I write

isFoo :: a -> Bool
isFoo !a = isTrue# (reallyUnsafePtrEquality# a Foo)

instead of

isFoo :: forall a. Typeable a => a -> Bool
isFoo a
  | Just Refl <- eqTypeRep (typeRep @a) (typeRep @Foo)
  , Foo <- a
  = True
  | otherwise = False

The reason I'm asking is because this would let me (potentially) raiseIO# a nullary constructor and then catch# it and see if it was what I was looking for rather than having to open a SomeException to get to an Exception dictionary, open that to get a TypeRep, and then peer inside that to check a Fingerprint. That is, I'd get lighter-weight exceptions that only carry the information I actually need.

Thanks,
David

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Pointer equality for nullary constructors

Edward Kmett-2
Keep in mind a newtype of Foo will have a different TypeRep, but will compare as equal under reallyUnsafePtrEquality#.

-Edward

On Sun, Feb 11, 2018 at 5:14 AM, David Feuer <[hidden email]> wrote:
Can I use reallyUnsafePtrEquality# reliably to identify whether a value is a nullary constructor of a particular type? For example, if I have

data Foo = Foo

Can I write

isFoo :: a -> Bool
isFoo !a = isTrue# (reallyUnsafePtrEquality# a Foo)

instead of

isFoo :: forall a. Typeable a => a -> Bool
isFoo a
  | Just Refl <- eqTypeRep (typeRep @a) (typeRep @Foo)
  , Foo <- a
  = True
  | otherwise = False

The reason I'm asking is because this would let me (potentially) raiseIO# a nullary constructor and then catch# it and see if it was what I was looking for rather than having to open a SomeException to get to an Exception dictionary, open that to get a TypeRep, and then peer inside that to check a Fingerprint. That is, I'd get lighter-weight exceptions that only carry the information I actually need.

Thanks,
David

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Pointer equality for nullary constructors

David Feuer
Sure, but that's okay, because I never need to expose the type to anyone. I'm just nervous because I haven't seen documentation saying those values are type-specific.

On Feb 11, 2018 10:37 PM, "Edward Kmett" <[hidden email]> wrote:
Keep in mind a newtype of Foo will have a different TypeRep, but will compare as equal under reallyUnsafePtrEquality#.

-Edward

On Sun, Feb 11, 2018 at 5:14 AM, David Feuer <[hidden email]> wrote:
Can I use reallyUnsafePtrEquality# reliably to identify whether a value is a nullary constructor of a particular type? For example, if I have

data Foo = Foo

Can I write

isFoo :: a -> Bool
isFoo !a = isTrue# (reallyUnsafePtrEquality# a Foo)

instead of

isFoo :: forall a. Typeable a => a -> Bool
isFoo a
  | Just Refl <- eqTypeRep (typeRep @a) (typeRep @Foo)
  , Foo <- a
  = True
  | otherwise = False

The reason I'm asking is because this would let me (potentially) raiseIO# a nullary constructor and then catch# it and see if it was what I was looking for rather than having to open a SomeException to get to an Exception dictionary, open that to get a TypeRep, and then peer inside that to check a Fingerprint. That is, I'd get lighter-weight exceptions that only carry the information I actually need.

Thanks,
David

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Pointer equality for nullary constructors

Joachim Breitner-2
In reply to this post by David Feuer
Hi David,

Am Sonntag, den 11.02.2018, 05:14 -0500 schrieb David Feuer:
> Can I use reallyUnsafePtrEquality# reliably to identify whether a
> value is a nullary constructor of a particular type?

after reading this I cam up with this idea:
https://ghc.haskell.org/trac/ghc/ticket/14826

You might have an idea of whether this would be useful in practice.

Cheers,
Joachim

--
Joachim “nomeata” Breitner
  [hidden email]
  https://www.joachim-breitner.de/

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Pointer equality for nullary constructors

Gregory Collins-3
In reply to this post by David Feuer
On Sun, Feb 11, 2018 at 5:14 AM, David Feuer <[hidden email]> wrote:
Can I use reallyUnsafePtrEquality# reliably to identify whether a value is a nullary constructor of a particular type? For example, if I have

data Foo = Foo

Can I write

isFoo :: a -> Bool
isFoo !a = isTrue# (reallyUnsafePtrEquality# a Foo)


My experience is that this works, except when doing coverage, where the compiler adds instrumentation code that breaks the technique. I #ifdef'd my way around the problem, swapping out a slower impl when I was doing code coverage.

Greg

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Pointer equality for nullary constructors

Joachim Breitner-2
Hi,

Am Dienstag, den 20.02.2018, 17:56 -0500 schrieb Gregory Collins:
> You mean like this? https://github.com/gregorycollins/hashtables/blob/master/src/Data/HashTable/Internal/UnsafeTricks.hs#L72
>
> My experience is that this works, except when doing coverage, where the compiler adds instrumentation code that breaks the technique. I #ifdef'd my way around the problem, swapping out a slower impl when I was doing code coverage.

it seems that in this case,
https://ghc.haskell.org/trac/ghc/ticket/14826
would very much apply, wouldn’t it?

Cheers,
Joachim

--
Joachim Breitner
  [hidden email]
  http://www.joachim-breitner.de/

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Pointer equality for nullary constructors

Doug McIlroy
In reply to this post by David Feuer

> > Can I use reallyUnsafePtrEquality# reliably to identify whether a value is
> a nullary constructor of a particular type?

Can this "optimization" possibly save enough time to justify
nonstandard trickery?
This kind of obscure brittle coding may have been OK 50 years
ago. But why do it now?

Doug
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Pointer equality for nullary constructors

David Feuer
Because sometimes the sanctioned way is inefficient. throwIO always
wraps its exception argument in a SomeException constructor before
calling raiseIO# on the result. That extra baggage is likely enough to
make the implementation I'm considering too slow to bother with, so I
care right now in 2018. I'd very much prefer to get an
officially-approved way to do what I want, but barring that I'll take
one that works.

On Wed, Feb 21, 2018 at 9:33 AM, Doug McIlroy <[hidden email]> wrote:

>
>> > Can I use reallyUnsafePtrEquality# reliably to identify whether a value is
>> a nullary constructor of a particular type?
>
> Can this "optimization" possibly save enough time to justify
> nonstandard trickery?
> This kind of obscure brittle coding may have been OK 50 years
> ago. But why do it now?
>
> Doug
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Pointer equality for nullary constructors

Branimir Maksimovic
Hm, isn't that exceptions are exceptional?


On 22.02.2018. 05:21, David Feuer wrote:

> Because sometimes the sanctioned way is inefficient. throwIO always
> wraps its exception argument in a SomeException constructor before
> calling raiseIO# on the result. That extra baggage is likely enough to
> make the implementation I'm considering too slow to bother with, so I
> care right now in 2018. I'd very much prefer to get an
> officially-approved way to do what I want, but barring that I'll take
> one that works.
>
> On Wed, Feb 21, 2018 at 9:33 AM, Doug McIlroy <[hidden email]> wrote:
>>>> Can I use reallyUnsafePtrEquality# reliably to identify whether a value is
>>> a nullary constructor of a particular type?
>> Can this "optimization" possibly save enough time to justify
>> nonstandard trickery?
>> This kind of obscure brittle coding may have been OK 50 years
>> ago. But why do it now?
>>
>> Doug
>> _______________________________________________
>> Haskell-Cafe mailing list
>> To (un)subscribe, modify options or view archives go to:
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>> Only members subscribed via the mailman list are allowed to post.
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Pointer equality for nullary constructors

David Feuer
Well, not always. They have special support in the RTS that seems worth experimenting with. setjmp/longjmp is what I'm after.

On Feb 21, 2018 11:24 PM, "Branimir Maksimovic" <[hidden email]> wrote:
Hm, isn't that exceptions are exceptional?


On <a href="tel:22.02.2018.%2005" value="+12202201805" target="_blank">22.02.2018. 05:21, David Feuer wrote:
Because sometimes the sanctioned way is inefficient. throwIO always
wraps its exception argument in a SomeException constructor before
calling raiseIO# on the result. That extra baggage is likely enough to
make the implementation I'm considering too slow to bother with, so I
care right now in 2018. I'd very much prefer to get an
officially-approved way to do what I want, but barring that I'll take
one that works.

On Wed, Feb 21, 2018 at 9:33 AM, Doug McIlroy <[hidden email]> wrote:
Can I use reallyUnsafePtrEquality# reliably to identify whether a value is
a nullary constructor of a particular type?
Can this "optimization" possibly save enough time to justify
nonstandard trickery?
This kind of obscure brittle coding may have been OK 50 years
ago. But why do it now?

Doug
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Pointer equality for nullary constructors

Brandon Allbery
But in most cases exceptions are the slow path. There's a few languages that use them heavily as what one could think of as a form of out of band dynamic typing for function results, and which have specific support for fast exceptions to support that. In most, exception handling is much heavier weight than the usual code path, and needs to be because it needs to unwind the stack and free up allocated temporaries (presumably that last doesn't apply to Haskell. The pattern match stack would need the same unwind cleanup though) and otherwise clean up any unfinished business that will never finish as a result, as it propagates looking for a handler. Since they also usually contain an execution trace, that makes them even heavier (again, ghc does this differently --- one could argue worse, since the price is paid by all functions with HasCallStack context. I think only Icon of other languages I know penalize the normal path the same way --- because it's also how &fail / retry semantics is implemented).

...looking at that again, maybe I'm too tired to do this. Hopefully you can unpack that concept hairball....

On Thu, Feb 22, 2018 at 6:15 AM, David Feuer <[hidden email]> wrote:
Well, not always. They have special support in the RTS that seems worth experimenting with. setjmp/longjmp is what I'm after.

On Feb 21, 2018 11:24 PM, "Branimir Maksimovic" <[hidden email]> wrote:
Hm, isn't that exceptions are exceptional?


On <a href="tel:22.02.2018.%2005" value="+12202201805" target="_blank">22.02.2018. 05:21, David Feuer wrote:
Because sometimes the sanctioned way is inefficient. throwIO always
wraps its exception argument in a SomeException constructor before
calling raiseIO# on the result. That extra baggage is likely enough to
make the implementation I'm considering too slow to bother with, so I
care right now in 2018. I'd very much prefer to get an
officially-approved way to do what I want, but barring that I'll take
one that works.

On Wed, Feb 21, 2018 at 9:33 AM, Doug McIlroy <[hidden email]> wrote:
Can I use reallyUnsafePtrEquality# reliably to identify whether a value is
a nullary constructor of a particular type?
Can this "optimization" possibly save enough time to justify
nonstandard trickery?
This kind of obscure brittle coding may have been OK 50 years
ago. But why do it now?

Doug
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.



--
brandon s allbery kf8nh                               sine nomine associates
[hidden email]                                  [hidden email]
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Pointer equality for nullary constructors

Carter Schonwald
In reply to this post by David Feuer
David: 
i'm inclined to agree with Doug here.

Phrased differently: what is the example change in overheads in micro or milliseconds? 
what is an example tiny program where those overheads are a significant part of  program overhead?

why woulnd't they use something like https://www.microsoft.com/en-us/research/wp-content/uploads/2007/10/compilingwithcontinuationscontinued.pdf  aka the so called "double barrelled cps" transform?

On Wed, Feb 21, 2018 at 11:21 PM, David Feuer <[hidden email]> wrote:
Because sometimes the sanctioned way is inefficient. throwIO always
wraps its exception argument in a SomeException constructor before
calling raiseIO# on the result. That extra baggage is likely enough to
make the implementation I'm considering too slow to bother with, so I
care right now in 2018. I'd very much prefer to get an
officially-approved way to do what I want, but barring that I'll take
one that works.

On Wed, Feb 21, 2018 at 9:33 AM, Doug McIlroy <[hidden email]> wrote:
>
>> > Can I use reallyUnsafePtrEquality# reliably to identify whether a value is
>> a nullary constructor of a particular type?
>
> Can this "optimization" possibly save enough time to justify
> nonstandard trickery?
> This kind of obscure brittle coding may have been OK 50 years
> ago. But why do it now?
>
> Doug
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Pointer equality for nullary constructors

David Feuer
Double-barreled continuations don't seem to work well when you want to abort construction of a recursive structure. Think about Data.HashMap.Strict.insert. We don't really want to have to walk all the way back up to the top if we discover that the value pointer we're inserting is the same as the I've already in the map.

On Feb 22, 2018 2:55 PM, "Carter Schonwald" <[hidden email]> wrote:
David: 
i'm inclined to agree with Doug here.

Phrased differently: what is the example change in overheads in micro or milliseconds? 
what is an example tiny program where those overheads are a significant part of  program overhead?

why woulnd't they use something like https://www.microsoft.com/en-us/research/wp-content/uploads/2007/10/compilingwithcontinuationscontinued.pdf  aka the so called "double barrelled cps" transform?

On Wed, Feb 21, 2018 at 11:21 PM, David Feuer <[hidden email]> wrote:
Because sometimes the sanctioned way is inefficient. throwIO always
wraps its exception argument in a SomeException constructor before
calling raiseIO# on the result. That extra baggage is likely enough to
make the implementation I'm considering too slow to bother with, so I
care right now in 2018. I'd very much prefer to get an
officially-approved way to do what I want, but barring that I'll take
one that works.

On Wed, Feb 21, 2018 at 9:33 AM, Doug McIlroy <[hidden email]> wrote:
>
>> > Can I use reallyUnsafePtrEquality# reliably to identify whether a value is
>> a nullary constructor of a particular type?
>
> Can this "optimization" possibly save enough time to justify
> nonstandard trickery?
> This kind of obscure brittle coding may have been OK 50 years
> ago. But why do it now?
>
> Doug
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.



_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Pointer equality for nullary constructors

Gregory Collins-3
In reply to this post by Joachim Breitner-2
That's a really interesting idea, thanks for linking it.

On Tue, Feb 20, 2018 at 9:43 PM, Joachim Breitner <[hidden email]> wrote:
Hi,

Am Dienstag, den 20.02.2018, 17:56 -0500 schrieb Gregory Collins:
> You mean like this? https://github.com/gregorycollins/hashtables/blob/master/src/Data/HashTable/Internal/UnsafeTricks.hs#L72
>
> My experience is that this works, except when doing coverage, where the compiler adds instrumentation code that breaks the technique. I #ifdef'd my way around the problem, swapping out a slower impl when I was doing code coverage.

it seems that in this case,
https://ghc.haskell.org/trac/ghc/ticket/14826
would very much apply, wouldn’t it?

Cheers,
Joachim

--
Joachim Breitner
  [hidden email]
  http://www.joachim-breitner.de/

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.



--
Gregory Collins <[hidden email]>

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Pointer equality for nullary constructors

David Feuer
In reply to this post by David Feuer
Yes, by the way, insert would be a poor use case, since the "same value pointer" case will be fairly rare. The actual use-case I have in mind is alterF, where that case is much more likely.

On Feb 22, 2018 3:12 PM, "David Feuer" <[hidden email]> wrote:
Double-barreled continuations don't seem to work well when you want to abort construction of a recursive structure. Think about Data.HashMap.Strict.insert. We don't really want to have to walk all the way back up to the top if we discover that the value pointer we're inserting is the same as the I've already in the map.

On Feb 22, 2018 2:55 PM, "Carter Schonwald" <[hidden email]> wrote:
David: 
i'm inclined to agree with Doug here.

Phrased differently: what is the example change in overheads in micro or milliseconds? 
what is an example tiny program where those overheads are a significant part of  program overhead?

why woulnd't they use something like https://www.microsoft.com/en-us/research/wp-content/uploads/2007/10/compilingwithcontinuationscontinued.pdf  aka the so called "double barrelled cps" transform?

On Wed, Feb 21, 2018 at 11:21 PM, David Feuer <[hidden email]> wrote:
Because sometimes the sanctioned way is inefficient. throwIO always
wraps its exception argument in a SomeException constructor before
calling raiseIO# on the result. That extra baggage is likely enough to
make the implementation I'm considering too slow to bother with, so I
care right now in 2018. I'd very much prefer to get an
officially-approved way to do what I want, but barring that I'll take
one that works.

On Wed, Feb 21, 2018 at 9:33 AM, Doug McIlroy <[hidden email]> wrote:
>
>> > Can I use reallyUnsafePtrEquality# reliably to identify whether a value is
>> a nullary constructor of a particular type?
>
> Can this "optimization" possibly save enough time to justify
> nonstandard trickery?
> This kind of obscure brittle coding may have been OK 50 years
> ago. But why do it now?
>
> Doug
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.



_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.