The following function:
let twoInputs x y =
let sum = x + y
let product a = sum * a
product
Has the type:
val twoInputs : x:int -> y:int -> (int -> int)
That's perfectly reasonable, I see why it's coming. But why this function:
let oneInput = twoInputs 1
is of type val oneInput : (int -> int -> int) ?
Shouldn't it be int -> (int -> int) ?
Also, I think the functions above should comply with Associative property, so there should be no differences between int -> int -> (int -> int) and int -> int -> int -> int. If so, why not just specify the latter as the function type for twoInputs?
Parentheses mean "value of type FsharpFunc<_>", while the absence of parentheses means "true CLR method". In your example, twoInput is compiled to a true CLR method, but returns a value of type FSharpFunc<_>, hence its type. But your oneInput is compiled to a class field of type FSharpFunc<_>, and hence its type.
You can actually achieve same effect (i.e. turn true method into value) even without currying, very simply:
> let twoInputs x y =
> let sum = x + y
> let product a = sum * a
> product
> let twoInputsAgain = twoInputs
val twoInputs : x:int -> y:int -> (int -> int)
val twoInputsAgain : (int -> int -> int -> int)
This happens because CLR doesn't support the notion of "assigning a method", so F# has to compile this by declaring twoInputsAgain as a field of type FSharpFunc<_> and then assigning to it an instance of a class that inherits from FSharpFunc<_> and calls twoInputs when Invoked.
If you decompile it to C# (I use ILSpy), this is what you see:
static $Program()
{
$Program.twoInputsAgain#11 = new Program.twoInputsAgain#11();
}
internal class twoInputsAgain#11 : OptimizedClosures.FSharpFunc<int, int, FSharpFunc<int, int>>
{
public override FSharpFunc<int, int> Invoke(int x, int y)
{
return Program.twoInputs(x, y);
}
}
In conclusion, I want to note that this disctinction doesn't matter very much in practice, unless you practice some really dark magic, so you shouldn't worry about it.
Related
I am studying the clussures in swift but i dont really get the difference between these function types and what is the point of these defferences .I do understand the first and the second one somehow but the last one makes me commpletely confused . for example :
func performMagic (thingy : String ){
return thingy
}
performMagic("hello")
&
var newMagicFunction ={
(thingy : String) -> String in
return thingy
}
&
var addeFunction : (Int , Int) -> Int ={
(a : Int , b : Int) -> Int in
return a + b
}
addeFunction(1,3)
Thanks
the only real difference between the last one and the 2nd last one, is that the type of the var is being declared in the last one, and the type of the var is inferred from what is being assigned to it in the 2nd one. (besides the obvious functionality difference) eg, you could swap them around sort of
var newMagicFunction : String -> String = {
(thingy : String) -> String in
return thingy
}
var addeFunction = {
(a : Int , b : Int) -> Int in
return a + b
}
addeFunction(1,3)
which are equivalent to the above ones you posted
I am using Accord.NET in F# for the first time and I am having problems creating the function to calculate the distance for KNN.
Here is my code
static member RunKNN =
let inputs = MachineLearningEngine.TrainingInputClass
let outputs = MachineLearningEngine.TrainingOutputClass
let knn = new KNearestNeighbors<int*int*int*int>(1,inputs,outputs,null)
let input = 1,1,1,1
knn.Compute(input)
When I swap out the null for a function like this
let distanceFunction = fun (a:int,b:int,c:int,d:int)
(e:int,f:int,g:int,h:int)
(i:float) ->
0
I get an exception like this:
*Error 1 This expression was expected to have type
System.Func<(int * int * int * int),(int * int * int * int),float> but here has type
int * int * int * int -> int * int * int * int -> float -> int*
So far, the only article I found close to my problem is this one. Apparently, there is a problem with how F# and C# handle delegates?
I posted this same question on the Google group for Accord.NET here.
Thanks in advance
Declare the distance function like this:
let distanceFunction (a:int,b:int,c:int,d:int) (e:int,f:int,g:int,h:int) =
0.0
(it takes two tuples in input and returns a float), and then create a delegate from it:
let distanceDelegate =
System.Func<(int * int * int * int),(int * int * int * int),float>(distanceFunction)
Passing this delegate to Accord.NET should do the trick.
I would guess you should use the tuple form like so
let distanceFunction = fun ((a:int,b:int,c:int,d:int),
(e:int,f:int,g:int,h:int),
(i:float)) ->
I would like to define one of my parameters to be a C# out parameter in one of my interfaces. I realize that F# supports byref but how can I apply the System.Runtime.InteropServices.OutAttribute to one of my interface parameters?
C# Interface I am trying to replicate
public interface IStatisticalTests
{
void JohansenWrapper(
double[,] dat,
double alpha,
bool doAdfPreTests,
out double cointStatus,
out JohansenModelParameters[] johansenModelParameters);
}
Here's an example:
open System
open System.Runtime.InteropServices
[<Interface>]
type IPrimitiveParser =
//
abstract TryParseInt32 : str:string * [<Out>] value:byref<int> -> bool
[<EntryPoint>]
let main argv =
let parser =
{ new IPrimitiveParser with
member __.TryParseInt32 (str, value) =
let success, v = System.Int32.TryParse str
if success then value <- v
success
}
match parser.TryParseInt32 "123" with
| true, value ->
printfn "The parsed value is %i." value
| false, _ ->
printfn "The string could not be parsed."
0 // Success
Here's your interface, translated:
[<Interface>]
type IStatisticalTests =
//
abstract JohansenWrapper :
dat:float[,] *
alpha:float *
doAdfPreTests:bool *
[<Out>] cointStatus:byref<float> *
[<Out>] johansenModelParameters:byref<JohansenModelParameters[]>
-> unit
I'm working with an extern DLL that has a bunch of routines that return a ReturnCode enum, so I wrote the following helper function to log all the errors:
let mutable LastError = ReturnCode.OK
let mutable LastReturnCode = ReturnCode.OK
let mutable TotalErrors = 0
let Run (call: unit -> ReturnCode) =
LastReturnCode <- call()
if LastReturnCode <> ReturnCode.OK then
LastError <- LastReturnCode
TotalErrors <- TotalErrors + 1
Great, except some of the DLL's functions have out parameters. So now when I do something like
let CreateEvfImageRef (streamHandle: int) =
let mutable evfImageHandle = 0
Run (fun () -> Extern.EdsCreateEvfImageRef (streamHandle, &evfImageHandle))
evfImageHandle
the compiler gives me a "mutable variables cannot be captured by closures" error. Is there anything I can do beyond inlining Run everywhere? This worked fine in C#.
(Example extern declaration below)
[<DllImport(EDSDKPath)>]
extern ReturnCode EdsCreateEvfImageRef(int inStreamHandle, [<Out>] int& outEvfImageHandle);
You should still be able to use the ref type, but you do not need to write the & symbol when passing the reference to the function - the compiler will do this automatically:
let CreateEvfImageRef (streamHandle: int) =
let mutable evfImageHandle = ref 0
Run (fun () -> Extern.EdsCreateEvfImageRef (streamHandle, evfImageHandle))
!evfImageHandle
The standard solution is to use references - the code becomes
let CreateEvfImageRef (streamHandle: int) =
let evfImageHandle = ref 0
Run (fun () -> Extern.EdsCreateEvfImageRef (streamHandle, &(!evfImageHandle)))
!evfImageHandle
However this won't work as the compiler requires !evfImageHandle to be mutable, which it isn't.
I think the real solution here is to change your Run function so that it does not take a closure, rather have it take just the return value - which will at least have it work in this case. Then the code becomes
let Run (call: ReturnCode) =
LastReturnCode <- call
if LastReturnCode <> ReturnCode.OK then
LastError <- LastReturnCode
TotalErrors <- TotalErrors + 1
and the code changes to
let CreateEvfImageRef (streamHandle: int) =
let mutable evfImageHandle = 0
Extern.EdsCreateEvfImageRef (streamHandle, &evfImageHandle)) |> Run
evfImageHandle
Or the even more hackish solution. Use the fact that array members are mutable and can be captured by closures to do
let CreateEvfImageRef (streamHandle: int) =
let evfImageHandle = [|0|]
Run (fun () -> EdsCreateEvfImageRef (streamHandle, &(evfImageHandle.[0])) )
evfImageHandle.[0]
How do I go about using the TryTake method on a BlockingCollection<'a> passing in a timeout period in milliseconds?
Heres the signature:
BlockingCollection.TryTake(item: byref, millisecondsTimeout: int) : bool
is it possible to use the Tuple method of avoiding passing a ref type like on the Dictionary.TryGet methods?
i.e.
let success, item = myDictionary.TryGetValue(client)
Im struggling with this particular signature, any suggestions would be great.
Cheers!
I believe that you can only use that technique for byref parameters which occur at the end of the parameter list (this is similar to the rule for optional parameters). So if BlockingCollection.TryTake were defined with signature int * 'T byref -> bool it would work, but since it's defined as 'T byref * int -> bool it won't.
For example:
open System.Runtime.InteropServices
type T =
static member Meth1(a:int, [<Out>]b:string byref, [<Out>]c:bool byref) : char =
b <- sprintf "%i" a
c <- a % 2 = 0
char a
static member Meth2([<Out>]b:string byref, [<Out>]c:bool byref, a:int) : char =
b <- sprintf "%i" a
c <- a % 2 = 0
char a
// ok
let (r,b,c) = T.Meth1(5)
// ok
let (r,c) = T.Meth1(5,ref "test")
// ok
let r = T.Meth1(5, ref "test", ref true)
// doesn't compile
let (r,b,c) = T.Meth2(5)
// doesn't compile
let (r,c) = T.Meth2(ref "test", 5)
// ok
let r = T.Meth2(ref "test", ref true, 5)