Downcast using type object in F# - f#

let o1 = box SomeType()
let t = typeof<SomeType>
Is it possible to downcast (to SomeType) a boxed object (o1) using the Type information stored in other object (o1)?
The ultimate objective is to have a sort of dynamic invocation of functions.
I'm storing functions with signature FSharpFunc<'Pre,'Post> in a Map:
// Lack of Covariance/Contravariance force me to define it as obj:
let functions = Map<string,obj>
let invoke f (pre : 'Pre when 'Pre : comparison) (post : 'Post when 'Post : comparison) =
(unbox<FSharpFunc<'Pre,'Post>> f).Invoke(pre)
This dynamic invocation works whenever I pass the proper types objects in pre and post.
And know comes the issue. I also has the arguments of the invocation in a map of the form:
let data = Map<string,obj>
let conf = Map<string, Type>
where conf stores the type of each possible string key in data.
So given a function key and a proper configuration, I can retrieve the arguments from data in order to feed the function. But for these to work I should be able to downcast data values using conf Types.
I suspect that it is not possible and I'm aware that I am bypassing static type safety (I'm ok with that). In that case, Any workaround or alternative approach?

I'm not sure I understand what you are after here, so this is not a specific answer to your question, but rather a couple of suggestions that might help you.
Generally speaking it sounds like you want some sort of existential types. It sounds like
you have data of various types and
you have operations on that data and
you want to dynamically invoke those operations on the data.
To make such things safely, you should encapsulate the data (or ideally the type of the data) and the operations together rather than separately. At the point when you know the type of the data and the possible operations on the data, wrap them together so that other parts of your program cannot just take the data and try to unsafely perform arbitrary operations on the data. (To make such encapsulation general and safe, allowing type safe manipulation of data whose type is not know statically, you need something like first-class modules.)
As another suggestion, rather than boxing whole functions, you might rather want to box and unbox
the domains and ranges of functions. Consider the following wrap and unwrap functions:
let wrap (a2b: 'a -> 'b) : obj -> obj =
unbox<'a> >> a2b >> box<'b>
let unwrap (o2o: obj -> obj) : 'a -> 'b =
box<'a> >> o2o >> unbox<'b>
The function map would have the signature
val functions: Map<string, obj -> obj>
and would store wrapped functions. To invoke a function from the map, you would unwrap the previously wrapped o2o function with the desired type:
(unwrap o2o : 'a when 'a: comparison -> 'b when 'b: comparison)
This is not type safe as such, but allows for flexible invocations.

Related

Excel DNA UDF obtain unprocessed values as inputs

I have written several helper functions in F# that enable me to deal with the dynamic nature of Excel over the COM/PIA interface. However when I go to use these functions in an Excel-DNA UDF they do not work as expected as Excel-DNA is pre-processing the values in the array from excel.
e.g. null is turned into ExcelDna.Integration.ExcelEmpty
This interferes with my own validation code that was anticipating a null. I am able to work around this by adding an additional case to my pattern matching:
let (|XlEmpty|_|) (x: obj) =
match x with
| null -> Some XlEmpty
| :? ExcelDna.Integration.ExcelEmpty -> Some XlEmpty
| _ -> None
However it feels like a waste to convert and then convert again. Is there a way to tell Excel-DNA not to do additional processing of the range values in a UDF and supply them equivalent to the COM/PIA interface? i.e. Range.Value XlRangeValueDataType.xlRangeValueDefault
EDIT:
I declare my arguments as obj like this:
[<ExcelFunction(Description = "Validates a Test Table Row")>]
let isTestRow (headings: obj) (row: obj) =
let validator = TestTable.validator
let headingsList = TestTable.testHeadings
validateRow validator headingsList headings row
I have done some more digging and #Jim Foye's suggested question also confirms this. For UDF's, Excel-DNA works over the C API rather than COM and therefore has to do its own marshaling. The possible values are shown in this file:
https://github.com/Excel-DNA/ExcelDna/blob/2aa1bd9afaf76084c1d59e2330584edddb888eb1/Distribution/Reference.txt
The reason to use ExcelEmpty (the user supplied an empty cell) is that for a UDF, the argument can also be ExcelMissing (the user supplied no argument) which might both be reasonably null and there is a need to disambiguate.
I will adjust my pattern matching to be compatible with both the COM marshaling and the ExcelDNA marshaling.

In F#, is it possible to pass a reference to a mutable, defaulted value as a parameter?

For the Froto project (Google Protobuf in F#), I am trying to update the deserialization code from using 'a ref objects to passing values byref<'a>, for performance.
However, the code below fails on the hydrator &element field line:
type Field = TypeA | TypeB | Etc
let hydrateRepeated
(hydrator:byref<'a> -> Field -> unit)
(result:byref<'a list>)
(field:Field) =
let mutable element = Unchecked.defaultof<'a>
hydrator &element field
result <- element :: result
error FS0421: The address of the variable 'element' cannot be used at this point
Is there anything I can do to get this code to work without changing the signature of the hydrator parameter?
I'm very aware that I could use hydrator:'a ref -> Field -> unit and get things to work. However, the goal is to support deserializing into record types without needing to create a bunch of ref objects on the heap every time a record is deserialize.
Note that the following code is perfectly legal and has the same signature as the hydrator function declaration, above, so I'm unclear on what the problem is.
let assign (result:byref<'a>) (x:'a) =
result <- x
let thisWorks() =
let mutable v = Unchecked.defaultof<int>
assign &v 5
printfn "%A" v
I'll try to clarify what I was saying in my comments. You're right that your definition of assign is perfectly fine, and it appears to have the signature byref<'a> -> 'a -> unit. However, if you look at the resulting assembly, you'll find that the way it's compiled at the .NET representation level is:
Void assign[a](a ByRef, a)
(that is, it's a method that takes two arguments and doesn't return anything, not a function value that takes one argument and returns a function that takes the next argument and returns a value of type unit - the compiler uses some additional metadata to determine how the method was actually declared).
The same is true of function definitions that don't involve byref. For instance, assume you've got the following definition:
let someFunc (x:int) (y:string) = ()
Then the compiler actually creates a method with the signature
Void someFunc(Int32, System.String)
The compiler is smart enough to do the right thing when you try to use a function like someFunc as a first class value - if you use it in a context where it isn't applied to any arguments, the compiler will generate a subtype of int -> string -> unit (which is FSharpFunc<int, FSharpFunc<string, unit>> at the .NET representation level), and everything works seamlessly.
However, if you try to do the same thing with assign, it won't work (or shouldn't work, but there are several compiler bugs that may make it seem like certain variations work when really they don't - you might not get a compiler error but you may get an output assembly that is malformed instead) - it's not legal for .NET type instantiations to use byref types as generic type arguments, so FSharpFunc<int byref, FSharpFunc<int, unit>> is not a valid .NET type. The fundamental way that F# represents function values just doesn't work when there are byref arguments.
So the workaround is to create your own type with a method taking a byref argument and then create subtypes/instances that have the behavior you want, sort of like doing manually what the compiler does automatically in the non-byref case. You could do this with a named type
type MyByrefFunc2<'a,'b> =
abstract Invoke : 'a byref * 'b -> unit
let assign = {
new MyByrefFunc2<_,_> with
member this.Invoke(result, x) =
result <- x }
or with a delegate type
type MyByrefDelegate2<'a,'b> = delegate of 'a byref * 'b -> unit
let assign = MyByrefDelegate2(fun result x -> result <- x)
Note that when calling methods like Invoke on the delegate or nominal type, no actual tuple is created, so you shouldn't be concerned about any extra overhead there (it's a .NET method that takes two arguments and is treated as such by the compiler). There is the cost of a virtual method call or delegate call, but in most cases similar costs exist when using function values in a first class way too. And in general, if you're worried about performance then you should set a target and measure against it rather than trying to optimize prematurely.

IEnumerator in F# continued

This is the question about the earlier Persistence class that I was trying to expose as an enumerator. I realized that I need to pass by reference really to change the value of of the object that I am trying to populate. I guess I am going about this in a C++ way (As most may have guessed I am an F# beginner). However, I want to be as efficient in terms of memory foot print as I can. Ideally I would like to reuse the same object over and over again when I read from a file.
I am having a problem with this code where it does not allow me to pass by reference in the call to the function serialize. I am again reproducing the code here. I thank you in advance for your help.
The error I get:
error FS0001: This expression was expected to have type byref<'T> but here has type 'T
If I change the call to serialize(& current_, reader_) I get the following error:
persistence.fs(71,6): error FS0437: A type would store a byref typed value. This is not permitted by Common IL.
persistence.fs(100,29): error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
persistence.fs(100,30): error FS0423: The address of the field current_ cannot be used at this point
The CODE:
type BinaryPersistenceIn<'T when 'T: (new : unit -> 'T)>(fn: string, serializer: ('T byref * BinaryReader) -> unit) =
let stream_ = File.Open(fn, FileMode.Open, FileAccess.Read)
let reader_ = new BinaryReader(stream_)
let mutable current_ = new 'T()
let eof() =
stream_.Position = stream_.Length
interface IEnumerator<'T> with
member this.Current
with get() = current_
member this.Dispose() =
stream_.Close()
reader_.Close()
interface System.Collections.IEnumerator with
member this.Current
with get() = current_ :> obj
member this.Reset() =
stream_.Seek((int64) 0., SeekOrigin.Begin) |> ignore
member this.MoveNext() =
let mutable ret = eof()
if stream_.CanRead && ret then
serializer( current_, reader_)
ret
You can circumvent this by introducing a mutable local, passing it to serialize, and then assigning back to current_:
member this.MoveNext() =
let mutable ret = eof()
if stream_.CanRead && ret then
let mutable deserialized = Unchecked.defaultof<_>
serializer( &deserialized, reader_)
current_ <- deserialized
ret
But now this is becoming really, really unsettling. Notice the use of Unchecked.defaultof<_>? There is no other way to initialize a value of unknown type, and it's called "unchecked" for a reason: the compiler can't guarantee safety of this code.
I strongly advise that you explore other ways of achieving your initial goal, such as using a seq computation expression instead, as I have suggested in your other question.
With respect to memory footprint, let's analyze the sequence option:
You have an instance of the seq. That's going to be some class implementing IEnumerable<'T>. This one will be held until you no longer need the seq, i.e. not reallocated each time.
You hold a Stream as part of the seq, with the same lifetime.
You hold a BinaryReader as part of the seq, with the same lifetime.
eof : unit -> bool is a compiler-generated function class as part of the seq, with the same lifetime.
The loop will use a bool for the while loop and the if condition. Both of which are stack-allocated structs and needed for the branching logic.
And finally, you yield an instance that you already got from the serializer.
Conceptually, that's as little memory consumption as you can have for a lazily evaluated seq. Once an element is consumed, it can be garbage collected. Multiple evaluations will do the same thing again.
The only thing you can actually play with, is what the serializer returns.
If you have your serializer return a struct, it is copied and stack-allocated. And it should not be mutable. Mutable structs discouraged. Why are mutable structs “evil”?
Structs are good with respect to the garbage collector as they avoid garbage collection. But they are typically to be used with very small objects, in the order of say 16-24 bytes max.
Classes are heap-allocated and are passed by reference always. So if your serializer returns a class, say a string, then you just pass that around by reference and overhead of copying will be very small as you only ever copy the reference, not the content.
If you want your serializer side-effecting, i.e. overwriting the same object (class, i.e. reference type is to be used for this), then the whole approach of IEnumerable<'T> and consequently seq is wrong. IEnumerables always give you new objects as result and should never modify any pre-existing object. The only state with them should be the information, at what place in the enumeration they are.
So if you need a side-effecting version, you could do something like (pseudo-code).
let readAndOverwrite stream target =
let position = // do something here to know the state
fun target ->
target.MyProp1 <- stream.ReadInt()
target.MyProp2 <- stream.ReadFloat()
Passing as byref does not seem very reasonable to me, as you then anyway allocate and garbage collect the object. So you can just as well do that in an immutable way. What you can do, is just modifying properties on your object instead.

Call a function from its name as a string in f#

I thought that I might be able to do this with quotations - but I can't see how.
Should I just use a table of the functions with their names - or is their a way of doing this?
Thanks.
For more info......
I'm calling a lot of f# functions from excel and I wondered if I could write a f# function
let fs_wrapper (f_name:string) (f_params:list double) =
this bit calls fname with f_params
and then use
=fs_wrapper("my_func", 3.14, 2.71)
in the sheet rather than wrap all the functions separately.
You'll need to use standard .NET Reflection to do this. Quotations aren't going to help, because they represent function calls using standard .NET MethodInfo, so you'll need to use reflection anyway. The only benefit of quotations (compared to naive reflection) is that you can compile them, which could give you better performance (but the compilation isn't perfect).
Depending on your specific scenario (e.g. where are the functions located), you'd have to do something like:
module Functions =
let sin x = sin(x)
let sqrt y = sqrt(y)
open System.Reflection
let moduleInfo =
Assembly.GetExecutingAssembly().GetTypes()
|> Seq.find (fun t -> t.Name = "Functions")
let name = "sin"
moduleInfo.GetMethod(name).Invoke(null, [| box 3.1415 |])
Unless you need some extensibility or have a large number of functions, using a dictionary containing string as a key and function value as the value may be an easier option:
let funcs =
dict [ "sin", Functions.sin;
"sqrt", Functions.sqrt ]
funcs.[name](3.1415)
There are many methods but one way is to use Reflection, for instance:
typeof<int>.GetMethod("ToString", System.Type.EmptyTypes).Invoke(1, null)
typeof<int>.GetMethod("Parse", [|typeof<string>|]).Invoke(null, [|"112"|])
GetMethod optionally takes an array of types that define the signature, but you can skip that if your method is unambiguous.
Following up on what Thomas alluded to, have a look at Using and Abusing the F# Dynamic Lookup Operator by Matthew Podwysocki. It offers a syntactically clean way for doing dynamic lookup in F#.

How to create a type that implement IDictionary<'K, 'V> and IEnumerable<'V>

I want to create a read-only keyed collection that implements IDictionary<'K, 'V> and IEnumerable<'V>. Taking the obvious approach I get the following error:
This type implements or inherits the same interface at different generic instantiations 'IEnumerable<'V>' and 'IEnumerable<KeyValuePair<'K,'V>>'. This is not permitted in this version of F#.
Is there a different way of achieving this?
EDIT - Since this seems to be an insurmountable limitation of F#, what would be an idiomatic way of achieving this? One thought that comes to mind is providing members that return the desired view of the data, e.g., member x.List : IList<'V> and member x.Dict : IDictionary<'K, 'V>. Object expressions could be used to provide the implementations. Any other ideas?
One relatively easy approach is to expose the implementation of the two interfaces as members of the type you are writing. This can be done quite nicely using object expressions or just by writing a piece of code that constructs some type and returns it as the result. The second approach would look like this:
type MyCollection<'K, 'V when 'K : equality>(keys:list<'K>, values:list<'V>) = //'
member x.Dictionary =
Seq.zip keys values |> dict
member x.Enumerable =
values |> List.toSeq
The first approach (if you want to implement methods of the interfaces directly would look roughly like this:
type MyCollection<'K, 'V when 'K : equality>(keys:list<'K>, values:list<'V>) = //'
member x.Dictionary =
{ new IDictionary<'K, 'V> with
member d.Add(k, v) = ... }
member x.Enumerable =
// Similarly for IEnumerable
values |> List.toSeq
Exposing the implementations as functions in a module as mentioned by kvb is also a great option - I think that many of the standard F# library types actually do both of the options (so that the user can choose the style he/she prefers). This can be added like this:
module MyCollection =
let toDict (a:MyCollection<_, _>) = a.Dictionary
I'm afraid not. The CLR allows implementation of multiple interfaces of course (even of the same base type), but not the F# language. I believe you won't have any problems if you write the class in C#, but F# is going to give you problems in the current version.
As Noldorin says, this is not possible. One idiomatic approach is to provide toSeq and toDict functions on a module with the same name as your type (like List.toSeq, Array.toSeq, etc.).

Resources