This is related to this question.
I'd like to create a generic wrapper class:
public abstract class Wrapper<T>
{
internal protected T Wrapped { get; set; }
}
With the following extensions:
public static class WrapperExtensions
{
public static W Wrap<W,T>(this T wrapped) where W:Wrapper<T>,new()
{
return new W {Wrapped = wrapped};
}
public static T Unwrap<T>(this Wrapper<T> w)
{
return w.Wrapped;
}
}
Now assume a concrete Wrapper:
public class MyIntWrapper : Wrapper<int>
{
public override string ToString()
{
return "I am wrapping an integer with value " + Wrapped;
}
}
I would like to call the Wrap
extension like this:
MyIntWrapper wrapped = 42.Wrap<MyIntWrapper>();
This is not possible because in c# we need to provide both type arguments to the Wrap
extension.
(it's all or nothing)
Apparently partial inference is possible in F#.
How would the above code look in F#?
Would it be possible to use it from C#?
Apparently partial inference is possible in F#.
Yes, only W would need to be specified in your example. T will be inferred.
How would the above code look in F#?
[<AbstractClass>]
type Wrapper<'a>() =
[<DefaultValue>]
val mutable internal Wrapped : 'a
let Wrap<'W,'T when 'W :> Wrapper<'T> and 'W: (new: unit -> 'W)> (wrapped: 'T): 'W =
let instance = new 'W()
instance.Wrapped <- wrapped
instance
let Unwrap (w: Wrapper<_>) = w.Wrapped
type MyIntWrapper() =
inherit Wrapper<int>()
override this.ToString() =
sprintf "I'm wrapping an integer with value %d" this.Wrapped
And you can call Wrap from F# interactive this way
> let wrapped = Wrap<MyIntWrapper,_> 5;;
val wrapped : MyIntWrapper = I'm wrapping an integer with value 5
In my opinion this is not very idiomatic in F#, I would rather use Discriminated Unions and Pattern Matching for wrapping/unwrapping but I don't know exactly what's your specific case.
Would it be possible to use it from C#?
Sure, but if you call Wrap
from C# you're back to C# type inference and will have to specify the second type parameter.
Implement custom implicit conversion:
MSDN sample
struct MyIntWrapper
{
public MyIntWrapper(int value)
{
this.value = value;
}
static public implicit operator MyIntWrapper(int value)
{
return new MyIntWrapper(value);
}
static public explicit operator int(MyIntWrapper wrapper)
{
return wrapper.value;
}
private int value;
}
You can then write:
MyIntWrapper wrapped = 42;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With