Implicit Multi Threading in Switch Case

Hi, After reading "Push-Pull Functional Reactive Programming https://pdfs.semanticscholar.org/fb7a/879d639641341e025197b40afad9e21f0ce5.p..." 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

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.p..." 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.

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,
Hi, After reading "Push-Pull Functional Reactive Programming https://pdfs.semanticscholar.org/fb7a/879d639641341e025197b40afad9e21f0ce5.p..." 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.

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
https://hackage.haskell.org/package/unamb-0.2.5.
On Tue, Jun 20, 2017 at 8:10 PM, Isaac Elliott
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,
wrote: Hi, After reading "Push-Pull Functional Reactive Programming https://pdfs.semanticscholar.org/fb7a/879d639641341e025197b40afad9e21f0ce5.p..." 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.

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.

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.
participants (7)
-
Albert Y. C. Lai
-
Clinton Mead
-
Isaac Elliott
-
Joachim Durchholz
-
Jonas Scholl
-
Richard A. O'Keefe
-
Yotam Ohad