How to use matching on argument level, is it possible? Guards?

95 Views Asked by At

for example

let When true d = d
let foo = () |> When false

So I've got side effect I don't like because it's error: MatchFailureException

I know that I can have good side effect here: let foo = if false then ()

But warning Incomplete pattern matches on this expression. tells me like I can add what I need. I just don't know how or if it possible? Else way why I even can use values as arguments?

btw: I know that I can write When b d = if b then d else () but question is more general.

added explain in haskell

    let wh :: Bool -> IO () -> IO ()
        wh True f = f
        wh False f = return ()
2

There are 2 best solutions below

4
On BEST ANSWER

The fact that this is allowed is more of a quirk of the spec, and is really so you can do things like

let (a,b) = 1,2

Your question isn't particularly clear, but I think you are looking for something like

let 1 |2 = 1

Essentially the syntax is the same as after match except you don't need the first |

Side note, this allows for the craziest piece of F# code that I wrote in a while:

let 1 = 2

This will compile (with a warning) but fail at runtime.

1
On

When you write something like:

let When true d = d

You're telling F# to create a function that takes two arguments and you're matching the two arguments against patterns true and d, respectively. The true pattern is incomplete and fails when the input is not a true value. The d pattern is variable binding and it always succeeds.

The fact that you can use incomplete patterns in arguments of function declarations is not particularly useful (but I suppose you could use a more complex pattern that the compiler just cannot verify).

Incomplete patterns really only make sense when you're using match or when you're using function. The function keyword gives you something like guards in other languages - but it only works with functions taking single argument. If you change When to accept a tuple, you can write:

let When = function
  | true, f -> f()
  | false, _ -> ()

Alternatively, you could reverse the order of arguments (and use currying) as in the answer from Vesa.A.J.K.