Using a lambda expression with match - f#

I am trying to use a lambda expression to help me return a value but I am getting an error that says
the function takes too many agruments, or is used in a context where a
function is not expected
.
Here is the sample code:
match isTrue with
| true -> 1
| false -> (fun () -> 2) //<----Error
So is it not possible to use a lambda expression here, or am I missing something?

Being new to F#, I assumed that:
(fun () -> 2)
would automatically execute in the match expression. I just simply need to write the code needed as in
match isTrue with
| true -> 1
| false ->
let something = 48 + 3
something + 4

Related

Match on discriminated union case not contents

Is it possible in F# to match a Discriminated Union based on its case rather than by case contents? For example, if I wanted to filter a list by elements that are of the case Flag, is it possible to filter as such? Currently, I am forced to have three separate functions to filter the way I desire. This is the approach I have so far:
type Option =
{Id : string
Arg : string}
type Argument =
| Flag of string
| Option of Option
| Unannotated of string
//This is what I'm going for, but it does not work as the "other" match case will never be matched
let LocateByCase (case:Argument) (args : Argument List) =
args
|> List.filter (fun x -> match x with
| case -> true
| _ -> false)
let LocateAllFlags args =
args
|> List.filter (fun x -> match x with
| Flag y -> true
| _ -> false)
let LocateAllOptions args =
args
|> List.filter (fun x -> match x with
| Option y -> true
| _ -> false)
let LocateAllUnannotated args =
args
|> List.filter (fun x -> match x with
| Unannotated y -> true
| _ -> false)
Am I missing some facet of the F# language that would make this much easier to deal with?
There is no built-in way to find out the case of a DU value. The usual approach, when faced with such requirement, is to provide appropriate functions for each case:
type Argument =
| Flag of string
| Option of Option
| Unannotated of string
with
static member isFlag = function Flag _ -> true | _ -> false
static member isOption = function Option _ -> true | _ -> false
static member isUnannotated = function Unannotated _ -> true | _ -> false
let LocateByCase case args = List.filter case args
let LocateAllFlags args = LocateByCase Argument.isFlag args
(needless to say, the LocateByCase function is actually redundant, but I decided to keep it in to make the answer clearer)
WARNING: DIRTY HACK BELOW
Alternatively, you could provide the case as a quotation, and make yourself a function that will analyze that quotation, fish the case name out of it, and compare it to the given value:
open FSharp.Quotations
let isCase (case: Expr<'t -> Argument>) (value: Argument) =
match case with
| Patterns.Lambda (_, Patterns.NewUnionCase(case, _)) -> case.Name = value.GetType().Name
| _ -> false
// Usage:
isCase <# Flag #> (Unannotated "") // returns false
isCase <# Flag #> (Flag "") // returns true
Then use this function to filter:
let LocateByCase case args = List.filter (isCase case) args
let LocateAllFlags args = LocateByCase <# Flag #> args
HOWEVER, this is essentially a dirty hack. Its dirtiness and hackiness comes from the fact that, because you can't require a certain quotation shape at compile time, it will allow nonsensical programs. For example:
isCase <# fun() -> Flag "abc" #> (Flag "xyz") // Returns true!
isCase <# fun() -> let x = "abc" in Flag x #> (Flag "xyz") // Returns false. WTF?
// And so on...
Another gotcha may happen if a future version of the compiler decides to generate quotations slightly differently, and your code won't recognize them and report false negatives all the time.
I would recommend avoiding messing with quotations if at all possible. It may look easy on the surface, but it's really a case of easy over simple.

In F#, return true if expression matches pattern?

I am looking for a shorter/neater way of doing the equivalent of the following (for any pattern known at compile time):
let f x = match x with | ['A'::_] -> true ; | _ -> false
is there a way of doing this in general, i.e. return true iff an expression matches a given pattern?
You could shorten it slightly using function:
let f = function ['A'::_] -> true | _ -> false
In f#, patterns are not values themselves, and there is no mechanism for converting them to values(*). So, no, there is no neater way.
That said, you may have other options depending on why you're interested in checking whether a pattern matches. Caring about whether a pattern matches but not about which values were matched seems a bit unusual to me, so maybe there's an opportunity for refactoring.
As a simple example, suppose you're doing this:
let t = match e with <pattern> -> true | _ -> false
...
if t then
(* Do something. *)
else
(* Do something else. *)
...
In that case, you could consider instead doing this:
...
match e with
<pattern> -> (* Do something. *)
| _ -> (* Do something else. *)
...
(Supposing the test happens only once, of course.)
(*) Ignoring reflection and quotations.
You may be thinking of an Active Pattern here, specifically its single-case form. It would allow you to create a pattern which returns a boolean value:
let (|F|) = function
| ['A'::_] -> true
| _ -> false
let (F x) = [['A']] // val x : bool = true
The Active Pattern can be parameterized. Of the (n + 1) arguments it accepts, the first n get passed to the syntactic function, and the last argument is the value matched.
let (|G|) e = function
| [d::_] when d = e -> true
| _ -> false
let (G 'A' y) = [['A']] // val y : bool = true

How to return unit from an expressions in f#

How can i return unit from an expression in f#? For example:
let readInt =
let str = Console.ReadLine()
let (succ, num) = Int32.TryParse(str)
match succ with
| true -> Some(num)
| _ -> None
match readInt with
| Some(v) -> Console.WriteLine(v)
| None -> ignore //i don't want to do anything,
// but i don't know how to ignore this brunch of the expression
The (only possible) unit value in F# is written as
()
So your code becomes
...
| None -> ()
Just write () as follows
match readInt with
| Some(v) -> Console.WriteLine(v)
| None -> ()
Keep in mind the unit value (), it is handy in many situations.
In this case, you could use iter function from Option module:
Option.iter Console.WriteLine readInt
It also highlights the fact that iter functions (e.g. those from Seq, List and Array module) will always give you the unit value ().

F# Quotations - traversing into function calls represented by a Value

I've spent a few hours trying to get to grips with F# Quotations, but I've come across a bit of a road block. My requirement is to take simple functions (just integers,+,-,/,*) out of a discriminated union type and generate an expression tree that will eventually be used to generate C code. I know this is possible using Quotations with 'direct' functions.
My problem is that the expression tree seems to terminate with a "Value", and I can't figure out how to traverse into that value.
My questions is
whether this is actually possible in this situation? or are there any other approaches that are worth considering.
type FuncType =
| A of (int -> int -> int)
| B
| C
[<ReflectedDefinition>]
let add x y = x + y
let myFunc1 = A (fun x y -> x + y )
let myFunc2 = A add
let thefunc expr =
match expr with
| A(x) ->
<# x #>
| _ ->
failwith "fail"
printfn "%A" (thefunc myFunc1) // prints "Value (<fun:myFunc1#14>)"
printfn "%A" (thefunc myFunc2) // prints "Value (<fun:myFunc2#15>)"
printfn "%A" <# fun x y -> x + y #> // generates usable expression tree
Quotations represent the F# code that was quoted syntactically. This means that if you write something like <# x #>, the quotation will contain just Value case specifying that you quoted something which has the specified value. (Variables are automatically replaced with values if the variable is defined outside of the quotation).
You can only get quotation of code that was explicitly quoted using <# .. #> or of a function that was marked as ReflectedDefinition and is referred to by name in a quotation (e.g. <# add #> but not for example let f = add in <# f #>).
To be able to do what your snippet suggests, you'll need to store quotations in your FuncType too (so that the lambda function that you write is also quoted and you can get its body). Something like:
type FuncType =
| A of Expr<int -> int -> int>
| B | C
[<ReflectedDefinition>]
let add x y = x + y
let myFunc1 = A <# fun x y -> x + y #>
let myFunc2 = A <# add #>
let thefunc expr =
match expr with
| A(x) -> x
| _ -> failwith "fail"
This should work for functions marked as ReflectedDefinition too. To extract the body of the function you need to add something like (you'll need to substitute arguments of the function for parameters, but this should give you some idea):
match expr with
| Lambdas(_, body) ->
match body with
| Call(_, mi, _) when Expr.TryGetReflectedDefinition(mi) <> None ->
let func = Expr.TryGetReflectedDefinition(mi)
match func with
| Some(Lambdas(_, body)) ->
// 'body' is the quotation of the body
| _ -> failwith "Not supported function"
| _ -> failwith "Not supported function"
| _ -> failwith "Not supported expression"

F# matching with two values

I'm fairly new to F# and I wanted to compare two values with the (match ... with ...) syntax
The problem arises when I attempt to compare two values like this:
let value1 = 19
let isValue1 y =
match y with
| value1 -> y + 1
| _ -> y
I get a warning that the "| _ -> y" portion of the code will never be reached. Why is this?
I know that I can do the following to get the function to work the way I want it to:
let value1 = 19
let isValue1 y =
match y with
| _ when y = value1 -> true
| _ -> false
This works as well
let value1 = 19
let isValue1 y =
match y with
| 19 -> true
| _ -> false
I'm just curious about why I can't do that, and how match actually works.
The value1 within the match statement is defined as a new variable, the value of which is set to y (as a match). The value1 you define just above is ignored, just as if you were declaring a local variable in a C# function with the same name as a class variable. For this reason, the first match condition will match everything, not just the previously defined value of value1, hence the error. Hope that clarifies matters.
Pattern-matching is both a control construct (what code executes next) and a binding construct (like 'let', bind a name to a value). So when you do
match expr with
| name -> ...
the pattern ("name") always matches and the identifier 'name' just gets bound to the value of the expression. This is why pattern-matching is mostly used with discriminated unions (case types), where you match based on the structure. E.g.
match someOption with
| Some(x) -> ... // binds x
| None -> ...
match someList with
| h :: t -> ... // binds h and t to head/tail
| [] -> ...
You can just match the Input to Literals/Identifiers marked by the [<Literal>] Attribute without binding it.
For Example:
#light
[<Literal>]
let E = 2.718281828459
let isE x =
match x with
| E -> true
| _ -> false
print_any (isE 3.2)
print_any (isE E)
According to Crish Smith

Resources