Implicit Multi Threading in Switch Case

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

Implicit Multi Threading in Switch Case

Yotam Ohad
Hi,
After reading "Push-Pull Functional Reactive Programming" I had an idea about deciding which, of two events, comes first. Instead of using forkIO, I tried something like the following:

infi :: Maybe Int
infi = infi

stop :: Maybe Int
stop = Nothing

test :: Int
test = case (infi, stop) of
    (Nothing, Just _) -> 1
    (_, _) -> 2

Here, infi is an action that never ends, and stop a function that ends immediately. I thought that the compiler would see that stop evaluates immediately to Nothing and thus will return 2, but it tries to evaluate infi and get stuck.

I think it happens because I am using a tuple to hold both values (but not really sure about it). Do you know a way to make this arrangement work?

Yotam

_______________________________________________
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: Implicit Multi Threading in Switch Case

Jonas Scholl
You have to keep in mind that you can only pattern match against a
single thing at once. If you match at multiple things like you are
doing, this is just syntactic sugar for the following:

test = case (infi, stop) of
    (a, b) -> case a of
        Nothing -> case b of
            Just _ -> 1
            _ -> 2
        _ -> 2

The Haskell report states this in section 3.17.2 ("Pattern matching
proceeds from left to right, and outside to inside") resp. section 3.17.3.

To match with stop first, you either need to put it left of infi, or use
multiple case statements. However, if you do not know, which of stop and
infi will run forever (or throw an exception or behave like _|_ in any
other way), you are stuck, because now you need to pick one to evaluate
and if it is the wrong one, there is nothing you can do.

If you want to leave the sane world, you could try to see if one of the
arguments is already evaluated. However, your code would then be neither
portable nor pure anymore. GHC tags pointers to evaluated values, so you
can actually see if a value is evaluated without entering (evaluating)
it - but there can be false negatives, not every evaluated closure is
guaranteed to have the tag bits set and if neither of infi and stop has
them set, you are back at square one.

On 06/20/2017 11:28 AM, Yotam Ohad wrote:

> Hi,
> After reading "Push-Pull Functional Reactive Programming
> <https://pdfs.semanticscholar.org/fb7a/879d639641341e025197b40afad9e21f0ce5.pdf>"
> I had an idea about deciding which, of two events, comes first. Instead
> of using forkIO, I tried something like the following:
>
> infi :: Maybe Int
> infi = infi
>
> stop :: Maybe Int
> stop = Nothing
>
> test :: Int
> test = case (infi, stop) of
>     (Nothing, Just _) -> 1
>     (_, _) -> 2
>
> Here, infi is an action that never ends, and stop a function that ends
> immediately. I thought that the compiler would see that stop evaluates
> immediately to Nothing and thus will return 2, but it tries to evaluate
> infi and get stuck.
>
> I think it happens because I am using a tuple to hold both values (but
> not really sure about it). Do you know a way to make this arrangement work?
>
> Yotam
>
>
> _______________________________________________
> 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.

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

Re: Implicit Multi Threading in Switch Case

Isaac Elliott
In reply to this post by Yotam Ohad

Hey Yotam,

Pattern matching clauses evaluate from left to right. You can get the behavour you're after by swapping the arguments in the tuple:

case (stop, infi) of
  (Just _, Nothing) -> 1
  (_, _) -> 2

Evaluates to 2


On Tue, 20 Jun. 2017, 7:29 pm Yotam Ohad, <[hidden email]> wrote:
Hi,
After reading "Push-Pull Functional Reactive Programming" I had an idea about deciding which, of two events, comes first. Instead of using forkIO, I tried something like the following:

infi :: Maybe Int
infi = infi

stop :: Maybe Int
stop = Nothing

test :: Int
test = case (infi, stop) of
    (Nothing, Just _) -> 1
    (_, _) -> 2

Here, infi is an action that never ends, and stop a function that ends immediately. I thought that the compiler would see that stop evaluates immediately to Nothing and thus will return 2, but it tries to evaluate infi and get stuck.

I think it happens because I am using a tuple to hold both values (but not really sure about it). Do you know a way to make this arrangement work?

Yotam
_______________________________________________
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: Implicit Multi Threading in Switch Case

Clinton Mead
I don't think you're going to be able to achieve this with pattern matches. 

What may be useful is some of the stuff in the package unamb.

On Tue, Jun 20, 2017 at 8:10 PM, Isaac Elliott <[hidden email]> wrote:

Hey Yotam,

Pattern matching clauses evaluate from left to right. You can get the behavour you're after by swapping the arguments in the tuple:

case (stop, infi) of
  (Just _, Nothing) -> 1
  (_, _) -> 2

Evaluates to 2


On Tue, 20 Jun. 2017, 7:29 pm Yotam Ohad, <[hidden email]> wrote:
Hi,
After reading "Push-Pull Functional Reactive Programming" I had an idea about deciding which, of two events, comes first. Instead of using forkIO, I tried something like the following:

infi :: Maybe Int
infi = infi

stop :: Maybe Int
stop = Nothing

test :: Int
test = case (infi, stop) of
    (Nothing, Just _) -> 1
    (_, _) -> 2

Here, infi is an action that never ends, and stop a function that ends immediately. I thought that the compiler would see that stop evaluates immediately to Nothing and thus will return 2, but it tries to evaluate infi and get stuck.

I think it happens because I am using a tuple to hold both values (but not really sure about it). Do you know a way to make this arrangement work?

Yotam
_______________________________________________
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: Implicit Multi Threading in Switch Case

Richard A. O'Keefe
As I understand it, the original poster wanted the arguments
to be evaluated *concurrently* and to catch whichever of them
finished first.  (OK, define "finished" to be "evaluated to
WHNF".)  Years ago people used to discuss the question of
whether it was possible to define

   or True _ = True
   or _ True = True
   or False x = x
   or x False = x

symmetrically, so that if *either* argument returned True,
the result True would be delivered, even if the other
argument diverged.  As I recall it, the answer was "NO",
but I don't recall the proof.


_______________________________________________
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: Implicit Multi Threading in Switch Case

Joachim Durchholz
Am 21.06.2017 um 00:23 schrieb Richard A. O'Keefe:

> As I understand it, the original poster wanted the arguments
> to be evaluated *concurrently* and to catch whichever of them
> finished first.  (OK, define "finished" to be "evaluated to
> WHNF".)  Years ago people used to discuss the question of
> whether it was possible to define
>
>     or True _ = True
>     or _ True = True
>     or False x = x
>     or x False = x
>
> symmetrically, so that if *either* argument returned True,
> the result True would be delivered, even if the other
> argument diverged.  As I recall it, the answer was "NO",
> but I don't recall the proof.

It depends on evaluation strategy I'd say.

If evaluation is sequential ("depth-first"), if the first argument
diverges, then the whole expression diverges and you never get to
inspect the second argument to see whether it evaluates to True.

If evaluation alternates ("breadth-first", "concurrently"), then
infinities-caused divergence does not matter.
Divergence due to invalid operations (division by zero, taking the head
of an empty list etc.) will still cause failure.
Of course this means evaluating both parameters, which is less efficient
than just evaluating one of them and touch the second one only if needed.

To capture invalidity divergence, you'll need to modify evaluation
strategy further by allowing "known to diverge" as if it were an
ordinary result (similar to NaN values in IEEE arithmetic).
Actually SQL defines such a strategy, it assumes that divergence is
equivalent to "this might be any value", which gives us counterintuitive
answers like NULL == NULL evaluating to False, which is a well-known and
rich source of bugs in any but the most trivial SQL statements.
So this approach isn't a good idea at all.
_______________________________________________
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: Implicit Multi Threading in Switch Case

Albert Y. C. Lai
On 2017-06-20 07:28 PM, Joachim Durchholz wrote:
> It depends on evaluation strategy I'd say.

No, without nailing an evaluation strategy, Haskell 2010 (and 98, and
...) still manages to denotationally rule out the parallel-or example.
_______________________________________________
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.