Difference between two ways of partial application in F# [duplicate] - f#

This question already has answers here:
Generic type annotation in F#
(2 answers)
Closed 7 years ago.
Let's say we have the following function (body isn't very important):
let writelogf greeting x =
Printf.printf "%A" greeting
Printf.printf "%A" x
The type of this function is 'a -> 'b -> unit which is what I want.
Now I define a partially applied function:
let logf x = writelogf "Hello!" x
The type of this function is 'a -> unit which is what I expect. I'm able to use it with arguments of any type:
logf "Test"
logf 1
But if I try to simplify the declaration and repeat the calls:
let logf2 = writelogf "Hello!"
logf2 "Test"
logf2 1
it won't compile anymore, because logf2 is not generalized, it has type string -> unit (infered from first usage).
Why is that? If I have a function with 5 parameters and I need to partially apply one, do I have to repeat the other 4?

In the case where you have written:
let logf2 = writelogf "Hello!"
You are effectively binding a value, the type of which is generic. If you change your definition into a function, e.g. by taking the argument explicitly, or an argument of unit type, you can resolve the issue.
let logf x = writelogf "Hello!" x
let logf2() = writelogf "Hello!"
If you have a function with 5 parameters and you partially apply one, again you will need to take at least one argument explicitly but you do not need to repeat the other 3.
let test5 a b c d e =
printfn "%A" (a, b, c, d, e)
let testApplyOne x = test5 "Hello!" x

Related

F# GreaterThanZero passing int or decimal

I want to create a function that check if the passed value is greater than zero.
The passed value can be an int or a decimal (ideally a "numeric value").
In the immediate I just started with this:
type number =
| I of int
| D of decimal
type Checker () =
member this.Validate value =
match value with
| I x when x > 0 -> "ok"
| D x when x > 0m -> "ok"
| _ -> "error"
let a = 1f
let b = 1m
//let a_IsValid = Checker().Validate(a) // does not compile, expect number (not int)
//let b_IsValid = Checker().Validate(b) // does not compile, expect number (not decimal)
Found not immediate to pass a "number" so tried something different...
I found this article (http://tomasp.net/blog/fsharp-generic-numeric.aspx/) and I thought
"static member constraint" is the perfect solution for me.
A basic example works as expected:
let inline divideByTwo value =
LanguagePrimitives.DivideByInt value 2
divideByTwo 1f |> ignore
divideByTwo 1m |> ignore
but a different scenario found me very surprised:
type Calculator () =
let divideByTwo value =
LanguagePrimitives.DivideByInt value 2
member this.DivideByTwo value =
LanguagePrimitives.DivideByInt value 2
member this.ValidateGeneric value =
match LanguagePrimitives.GenericGreaterThan value 0m with
| true -> "ok"
| _ -> "error"
//let half = Calculator().DivideByTwo(1) // DivideByInt does not support int !!
// cannot use both the following, the first one will "force" the type, and the other will not work
let a_half = Calculator().DivideByTwo(1f) // ok if used before the "decimal" version
let b_half = Calculator().DivideByTwo(1m) // ok only if comment the previous one
It seems not to work when I want to use more than one type for the passing value.
More than that, the function I need (GenericGreaterThan) seems to have another "limitation", explained below.
The example in the article use DivideByInt and, as the name said, it divide the passed value by an int, a well defined type.
LanguagePrimitives.GenericGreaterThan needs 2 parameters, a passed value and a fixed one to compare to. The signature of the function as only one generic type for both, so if you pass a type 'T it expect the second one to be 'T too.
I just wants to compare with zero without passing it, but using "0" forced my value
to be an int and using "0m" force the value to be a decimal.
There is a simple way to have a function that check if a "numeric" value is greater than "zero" ?
Should I use obj and box it .... or use cast ... or stop trying and just use a different function for every type I need ?
[UPDATE]
I tried to use the LanguagePrimitives.GenericZero as suggested but still not able to have a working solution for my particular scenario.
I created a new issue here: F# - Compare LanguagePrimitives.GenericZero with a value passed on the class contructor .
Comparing against zero generically is actually quite simple. The following function should work for any numeric type:
let inline isPositive x =
x > LanguagePrimitives.GenericZero
isPositive 1.0 |> printfn "%A" // true
isPositive 1m |> printfn "%A" // true
Dividing by two generically is also pretty easy. You just have to define your own generic two, since it's not a built-in primitive:
let inline divideByTwo x =
let two =
LanguagePrimitives.GenericOne
+ LanguagePrimitives.GenericOne
x / two
divideByTwo 5.0 |> printfn "%A" // 2.5
divideByTwo 4m |> printfn "%A" // 2
there lots of things here.
your first example didn't work because you needed to wrap your number inside the type number (I assume you realise this? but didnt want it to work like that?)
type Checker () =
member this.Validate value =
match value with
| I x when x > 0 -> "ok"
| D x when x > 0m -> "ok"
| _ -> "error"
let a = I 1
let b = D 1m
let a_IsValid = Checker().Validate(a)
let b_IsValid = Checker().Validate(b)
your second example is that in doesnt support divide by int?
yes what is the value of 1/2? its not an int, so thats correct by design.
the third question seems to be that this code doesnt compile and run?
type Calculator () =
member inline _.DivideByTwo value =
LanguagePrimitives.DivideByInt value 2
let b_half = Calculator().DivideByTwo(1m) // ok for me
let a_half = Calculator().DivideByTwo(1f) // ok for me
but this works for me.
The fourth question appears to be the need to use static constraints to test if something is > 0?
but 0 (as in mathematics) is a different thing in different number systems, its generic too so you need LanguagePrimitives.GenericZero. putting that all together we get
type Calculator () =
member inline _.DivideByTwo value =
LanguagePrimitives.DivideByInt value 2
member inline _.ValidateGeneric value =
match LanguagePrimitives.GenericGreaterThan
value
LanguagePrimitives.GenericZero with
| true -> "ok"
| _ -> "error"
let b_half = Calculator().DivideByTwo(1m)
let a_half = Calculator().DivideByTwo(1f)
let y = Calculator().ValidateGeneric(1m)
let z = Calculator().ValidateGeneric(1f)
as for the divide by 1/2 question, you may need to think what you want it to do? really the input type is defined by what output type you want? decimal? float? etc

A function that accepts multiple types

I am fairly new to f#, but I want to know if it is possible to make a function that accepts multiple types of variables.
let add x y = x + y
let integer = add 1 2
let word = add "He" "llo"
Once a function use a type of variable it cannot accept another one.
You need to read about statically resolved type parameters and inline functions. It allows to create functions which may take any type that supports operation and/or have member. So your add function should be defined this way:
let inline add x y = x + y
Don't overuse inlined functions because their code inlined in call site and may increase assembly size, but may increase performance (test each case, don't make predictions!). Also inlined function are supported only by F# compiler and may not work with other languages (important when designing libraries).
Example of SRTP magic:
let inline (|Parsed|_|) (str: string) =
let mutable value = Unchecked.defaultof<_>
let parsed = ( ^a : (static member TryParse : string * byref< ^a> -> bool) (str, &value))
if parsed then
Some value
else
None
match "123.3" with
| Parsed 123 -> printfn "int 123"
| Parsed 123.4m -> printfn "decimal 123.4"
| Parsed 123.3 -> printfn "double 123.3"
// | Parsed "123.3" -> printfn "string 123.3" // compile error because string don't have TryParse static member
| s -> printfn "unmatched %s" s

Why are parentheses needed on this F# function?

Why are parentheses needed on read_rest_of_csv below?
let read_rest_of_csv() =
csv_data.Add(csv_fileH.ReadFields()) |> ignore
not csv_fileH.EndOfData
while read_rest_of_csv() do ignore None
Without the parentheses, the loop will not terminate.
open System
open System.Threading
open System.Collections.Generic
open System.Linq
open System.Text
open System.Threading.Tasks
open System.IO
open Microsoft.VisualBasic.FileIO
[<EntryPoint>]
let main argv =
let csv_fileH = new TextFieldParser("test1.csv")
csv_fileH.TextFieldType = FieldType.Delimited |> ignore
let x = csv_fileH.SetDelimiters(",")
let csv_data = new List<string[]>()
let eod = csv_fileH.EndOfData
if not eod then
let column_headings = csv_fileH.ReadFields()
csv_data.Add(column_headings) |> ignore
let read_rest_of_csv =
csv_data.Add(csv_fileH.ReadFields()) |> ignore
not csv_fileH.EndOfData
while read_rest_of_csv do ignore None
0
I apologize that I cannot remember where I saw this. I think it was in SO. It's a nice example.
Could this be that without parens I'm dealing with a function object of sorts?
I am indeed coming from not only a C, C++, and C# background, but also an intermediate Clojure background as well. In my case with F# syntax, reading my Haskell manual in a little more detail might have helped, because the syntaxes seem similar.
It seems that people coming from C-family languages (C#, Java, C, C++, JavaScript) are having problems understanding the use of brackets in F#. I certainly had, and it took me some years learning how things work.
In a nutshell, the most basic building block in F# is a value. Values can be let-bound:
let foo = bar
This means that foo is a value, which happens to be equal to bar.
Functions are also values:
// 'a -> 'a * 'a
let f = fun x -> x, x
Here, f is a function that takes some value (x) and returns a tuple with x as both the first and the second element.
That's a bit cumbersome to write, so there's a shorthand for that:
// 'a -> 'a * 'a
let f x = x, x
Notice that there are no brackets in these expressions.
Sometimes you need to adjust the precedence of operators. Just like in maths, 1 + 2 * 3 (which is equivalent to 1 + (2 * 3)) isn't the same as (1 + 2) * 3. In F#, you also use brackets to override precedence. Thus
// 'a -> string * 'a
let f x = someOtherFunction x, x
isn't the same as
// x:'a -> string
let f x = someOtherFunction (x, x)
(in this case, someOtherFunction is a function that returns a string.)
Notice that the brackets don't denote a function call; they're only there to control order of evaluation.
Sometimes, you want to define a function that doesn't take any input. You can't, however, define it like this:
let f = whatever
because that would make it a value that's immediately let-bound to whatever. Instead, you can let the function take a value of the built-in type unit. This type only has a single value, which is written ():
let f () = whatever
This means that f is a function that pattern matches its input against the only known value of unit.
Whenever you invoke f with (), the expression whatever is evaluated and returned.
Without the parentheses, the content executes once and never again. read_rest_of_csv has a type of bool: You are basically saying while true do ignore None.
The parentheses indicate that read_rest_of_csv has type unit -> bool, so every time you invoke it, it reads a row and moves the cursor. Otherwise, it will only do this once.
The answer to your question is that:
let read_rest_of_csv =
csv_data.Add(csv_fileH.ReadFields()) |> ignore
not csv_fileH.EndOfData
is not a function at all. This is no different from:
> let i = 1;;
val i : int = 1
This declares a binding with an integer value. If you want to declare a binding with a function value which takes no parameters, that looks like this:
> let i () = 1;;
val i : unit -> int
The exact same reasoning applies to read_rest_of_csv. Without the parenthesis, you are declaring a binding with type bool. With the parenthesis, you are declaring a binding with type unit->bool i.e. a binding with a function value where the function takes no inputs and returns a bool value.

type inference on abstract type with a tuple

Based on this kvb's answer, this code compiles (F#4) and runs :
type Untupler = abstract Apply : 'u * 'u -> 'u
let myotherFun arg1 arg2 =
printfn "myotherFun result is : %A %A" arg1 arg2
let myFunction tup1 tup2 (i:Untupler) =
myotherFun (i.Apply tup1) (i.Apply tup2)
let reskvb = myFunction (1,2) ("Hello","World") { new Untupler with member __.Apply (x,y) = snd (x,y) }
But if the last line is replaced by the initial answer :
let reskvb = myFunction (1,2) ("Hello","World") { new Untupler with member __.Apply x = fst x }
then the compiler complains with error FS0768 :
The member 'Apply' does not accept the correct number of arguments, 2 arguments are expected
I do not understand why the compiler seems to fail to infer that x is indeed a tuple. Or is there another issue I am missing ? Thx.
The reason for this is that when you start using interfaces, you move into F#'s support for Object-Oriented Programming, and in F#, all OOP interop methods are tupled by default.
Thus, the Apply method is interpreted as being a method that takes two method arguments, rather than a function that takes a single tuple as input.

Function to return another function's body

Is there a way in F# to create a function that takes any other function as its sole parameter and return that function's body text as the result?
For example:
let myFunc =
// Always equals 3!
let x = 1 + 2
// Print it to the console
printfn "x = %i" x
let extractFunctionText f =
???
extractFunctionText myFunc
extractFunctionText should have a signature of ('a -> 'b) -> string i.e. it will take any function as an input and returns a string. The string I'd like returned in the last line of specific example above is:
"""// Always equals 3!
let x = 1 + 2
// Print it to the console
printfn "x = %i" x"""
Apologies for any typos or naive questions: I'm a bit of a newb at this. I think that following links (SO Answer & MSDN) get me quite close but I don't understand things well enough to finish the job

Resources