F# Async<_> to Async<obj> - powershell

I am working with F# to develop PowerShell tooling. I am currently running into a block because Async<_>is a generic type that is not derived from a non-generic type, so I can't request an Async<_> or Async as a parameter value - I have to specify the exact generic type parameter.
(For those unfamiliar with the interaction between these two languages, I can write a class in a .NET language such as F#, derive it from a class in the PowerShell library, and give it a specific attribute and when I run PowerShell and import my library, my class is exposed as a command. The command type can't be generic. Properties of the type are exposed as PowerShell parameters.)
As far as I'm aware I can't avoid this by having a generic member on a non-generic type, so ideally I'd have a transformation attribute (for non-PS users, transformation attributes effectively perform type conversion during runtime parameter binding) to turn Async<_> into Async<obj>. For the most part, this would work great for me. However, I can't figure out a way to check if a value is Async<_>, because the check computation :? Async<_> at compile time ends up as computation :? Async<obj>, which is not, unfortunately, the same, and returns false when passed Async<int>.
I ran into a similar issue in C# and was able to leverage the dynamic keyword after running a reflection test, and making the parameter be of the derived base type System.Threading.Tasks.Task, e.g.
const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHeirarchy;
var isTaskOf = task.GetType()
.GetProperty("GetAwaiter", flags)
.PropertyType
.GetMethod("GetResult", flags)
.ReturnType != typeof(void);
if (isTaskOf) {
var result = await (dynamic)task;
}
I am willing to do something like this in F# if possible, but:
I have not ben able to successfully get the dynamic lookup operator ? to compile. Specifically, "none of the types 'Async<'a>, string' support the '?' operator". Not sure what I'm doing wrong as the explanations look straightforward and I can't find any other reports of this message or requirements for that operator.
I don't know if that would even work or if that operator is only used to dynamically access a member of an object.
The solutions I have tried are:
/// Transform from Async<_> to Async<obj>
override _.Transform(_, item : obj) : obj =
match item with
// only matches Async<obj>. I get a compiler warning that _ is constrained to obj
| :? Async<_> as computation ->
let boxedComputation : Async<obj> = async { return! computation }
boxedComputation
// if the value is not an async computation, let it pass through. This will allow other transformation or type converters to try to convert the value
| _ -> item
override _.Transform(_, item) =
// no compiler warning about the type being constrained to obj, but the if test does not pass unless item is Async<obj>
if (item :? Async<_>) then async { return! item :?> Async<_> }
else item
The other thing I can think of is to use reflection entirely - get the async type, call all of the AsyncBuilder methods reflectively to create a computation expression, and then cast it to Async. As I'm fairly new to F# I'm not sure how well I'd be able to piece together a computation expression like that, and either way it seems a lot more complicated than it ought to be. I'm hoping there is some better way to identify the return type of an async computation and/or just box the result without caring what type it actually is.
EDIT
After trying something ridiculously complicated using reflection with the AsyncBuilder type I realized I could leverage it a little more simply. Here is my current working solution, but I'm still looking out for any better options.
static let boxAsyncReturnValue v = async { return v :> obj }
static let bindFunctionReflected = typeof<FSharpAsyncObjTransformationAttribute>.GetMethod(
nameof boxAsyncReturnValue,
BindingFlags.NonPublic ||| BindingFlags.Static
)
override _.Transform(engineIntrinsics, item) =
// I need to identify the current return type of the computation, and quit if "item" is not Async<_>
if item = null then item else
let itemType = item.GetType()
if not itemType.IsGenericType then item else
let genericItemType = itemType.GetGenericTypeDefinition()
if genericItemType <> typedefof<Async<_>> then item else
let returnType = itemType.GetGenericArguments()[0]
if returnType = typeof<obj> then item else
bindFunctionReflected.MakeGenericMethod(itemType).Invoke(null, [|item|])

This is how I would do it:
let convert (a: Async<_>) =
async {
let! x = a
return box x
}
And at compile time it behaves as you'd expect:
let a = async { return "hello" }
let o: Async<obj> = convert a
let res = Async.RunSynchronously o
printfn "%s" res // Error: expected type 'string' but is type 'obj'
printfn "%s" (unbox<string> res) // compiles, prints the string

Related

Swift short syntax of execution

I am looking for the way to write short syntax.
For instance. In JS, PHP and etc.
var a = 1 ;
function Foo ()-> void {}
a && Foo() ;
if a exists, run Foo.
a and Foo itself already mean exist or not, the syntax is away better looks....
However, in Swift, the typing checking is kinda of tough.
var a = 1 ;
func Foo ()-> Foid {} ;
a && Foo();
will generate neither are Bool returning error.
a != nil && Foo() ;
this can resolve and variable condition, but what if the better bypass for the function condition? I just dont want to write something like
if( a != nil ) { Foo() } ;
Yet what is the better syntax for Not Exist?
if ( !a ) or !a //is easy and better looks...
I found not similar thing in swift...
if( a == nil ) // will throws error when its not Optional Typing.
guard var b = xxx else {} // simply for Exist and very long syntax.
Thank you for your advice!
As mentioned by other contributors, Swift emphasizes readability and thus, explicit syntax. It would be sacrilege for the Swift standard library to support Python-style truth value testing.
That being said, Swift’s extensibility allows us to implement such functionality ourselves—if we really want to.
prefix func !<T>(value: T) -> Bool {
switch T.self {
case is Bool.Type:
return value as! Bool
default:
guard Double(String(describing: value)) != 0
else { return false }
return true
}
}
prefix func !<T>(value: T?) -> Bool {
guard let unwrappedValue = value
else { return false }
return !unwrappedValue
}
var a = 1
func foo() -> Void { }
!a && !foo()
Or even define our own custom operator:
prefix operator ✋
prefix func ✋<T>(value: T) -> Bool {
/// Same body as the previous example.
}
prefix func ✋<T>(value: T?) -> Bool {
guard let unwrappedValue = value
else { return false }
return ✋unwrappedValue
}
var a = 1
func foo() -> Void { }
✋a && ✋foo()
The expectations you've developed from dynamic languages like PHP and JS (and Ruby, Python for that matter) are almost universally inapplicable to static languages like Swift.
Swift is a statically compiled language. If you reference a variable that doesn't exist, it's not legal Swift code, and the compiler will fail your build. Given that, the question of "how do I check if a variable is undefined?" is completely moot in Swift. If you have a successfully compiling program that references a variable a, then a exists. There's absolutely no reason for a check, and so a mechanism for it doesn't even exist.
Static vs Dynamic typing
Static type systems are like mathematical proof systems. They produce rigerous proofs that certain aspects of your program are valid. This has trade-offs. The rigidity buys you many guarantees. For example, you'll never have a valid Swift program where you accidentally pass an Int where a Bool is expected. The static type system makes that class of error literally impossible, so it's not something you have to remember to check for yourself.
On the other hand, many truths are easier to intuit than to prove. Thus, there's great utility in scripting and dynamic languages, because they don't demand the rigorous proofs of your claims that static languages require. On the down side, their type systems "do" much less. For example, JS happily lets you reference an undefined variable. To remedy this, JS provides a way for you to do a run-time check to see whether a variable is defined or not. But this isn't a problem Swift has, so the "solution" is absent.
When static typing is too hard
Swift actually takes a middle ground position. If you find yourself with a statement that's obviously true, but hard to prove to the compiler, various "escape hatches" exist that allow you to leave the safety of the type system, and go into dynamic land. For example, if you look at an IBOutlet, and see that it's connected to an element in a storyboard, you can intuitively be sure that the IBOutlet is not nil. But that's not something you can prove to the compiler, and hence when you see implicitly unwrapped optionals being used for IBOutlets.
Implicitly unwrapped optionals are one such "escape hatch". The Any type is another, as is unsafeBitcast(_:to:), withoutActuallyEscaping(_:), as!, try!, etc.
Swift takes type safety very seriously. Unlike C or JS we can not use anything that doesn't resolve to Bool value type in If statement in Swift. So there won't be a short hand for that(at-least that I know of). Regarding below code
if( a == nil ) // will throws error when its not Optional Typing.
Swift doesn't allow you to set nil to non optional types. So there is no need to check for nil. By the way both Obj-C and Swift use verbose syntax, we need to get use to that.
In this case you are trying to force Swift to work in a way that you are used to with other languages like JavaScript or PHP, as you say in your comment. There are a few reasons why your code won't compile, but it mainly falls on the fact that Swift doesn't do the same truthy and falsy stuff JS does.
var a = 1
if a {
print("won't compile")
}
//'Int' is not convertible to 'Bool'
In Swift it's better to use an actual Bool value if that's what it's supposed to be, or if it's truly supposed to be an Int you're just going to have to check the value
var a = true
if a {
print("this compiles")
}
or
var a = 1
if a > 0 {
print("this compiles too")
}
Swift really isn't meant to be as loose as JS, so you should just embrace that and take advantage of the safety and readability.
Here is one way most similar to what you designed.
You may have to set the type of a to Int?:
var a: Int? = 1
func foo ()-> Void {}
a.map{_ in foo()}

How do I store a value of type Class<ClassImplementingProtocol> in a Dictionary of type [String:Class<Protocol>] in Swift?

I want to store a more specialized type in a Dictionary of type [String:SomeClass]. Here is some sample code illustrating my problem (also available to play with at https://swiftlang.ng.bluemix.net/#/repl/579756cf9966ba6275fc794a):
class Thing<T> {}
protocol Flavor {}
class Vanilla: Flavor {}
var dict = [String:Thing<Flavor>]()
dict["foo"] = Thing<Vanilla>()
It produces the error ERROR at line 9, col 28: cannot assign value of type 'Thing<Vanilla>' to type 'Thing<Any>?'.
I've tried casting Thing<Vanilla>() as Thing<Flavor> but that produces the error cannot convert value of type 'Thing<Vanilla>' to type 'Thing<Flavor>' in coercion.
I've also tried to define the Dictionary as type [String:Thing<Any>] but that doesn't change anything either.
How do I create a collection of different Things without resorting to plain [String:AnyObject]?
I should also mention that the class Thing is not defined by me (in fact it's about BoltsSwift Tasks), so the solution to create a base class of Thing without a type parameter doesn't work.
A Thing<Vanilla> is not a Thing<Flavor>. Thing is not covariant. There is no way in Swift to express that Thing is covariant. There are good reasons for this. If what you were asking for were allowed without careful rules around it, I would be allowed to write the following code:
func addElement(array: inout [Any], object: Any) {
array.append(object)
}
var intArray: [Int] = [1]
addElement(array: &intArray, object: "Stuff")
Int is a subtype of Any, so if [Int] were a subtype of [Any], I could use this function to append strings to an int array. That breaks the type system. Don't do that.
Depending on your exact situation, there are two solutions. If it is a value type, then repackage it:
let thing = Thing<Vanilla>(value: Vanilla())
dict["foo"] = Thing(value: thing.value)
If it is a reference type, box it with a type eraser. For example:
// struct unless you have to make this a class to fit into the system,
// but then it may be a bit more complicated
struct AnyThing {
let _value: () -> Flavor
var value: Flavor { return _value() }
init<T: Flavor>(thing: Thing<T>) {
_value = { return thing.value }
}
}
var dict = [String:AnyThing]()
dict["foo"] = AnyThing(thing: Thing<Vanilla>(value: Vanilla()))
The specifics of the type eraser may be different depending on your underlying type.
BTW: The diagnostics around this have gotten pretty good. If you try to call my addElement above in Xcode 9, you get this:
Cannot pass immutable value as inout argument: implicit conversion from '[Int]' to '[Any]' requires a temporary
What this is telling you is that Swift is willing to pass [Int] where you ask for [Any] as a special-case for Arrays (though this special treatment isn't extended to other generic types). But it will only allow it by making a temporary (immutable) copy of the array. (This is another example where it can be hard to reason about Swift performance. In situations that look like "casting" in other languages, Swift might make a copy. Or it might not. It's hard to be certain.)
One way to solve this is adding an initialiser to Thing and creating a Thing<Flavor> that will hold a Vanilla object.
It will look something like:
class Thing<T> {
init(thing : T) {
}
}
protocol Flavor {}
class Vanilla: Flavor {}
var dict = [String:Thing<Flavor>]()
dict["foo"] = Thing<Flavor>(thing: Vanilla())

Can a condition be used to determine the type of a generic?

I will first explain what I'm trying to do and how I got to where I got stuck before getting to the question.
As a learning exercise for myself, I took some problems that I had already solved in Objective-C to see how I can solve them differently with Swift. The specific case that I got stuck on is a small piece that captures a value before and after it changes and interpolates between the two to create keyframes for an animation.
For this I had an object Capture with properties for the object, the key path and two id properties for the values before and after. Later, when interpolating the captured values I made sure that they could be interpolated by wrapping each of them in a Value class that used a class cluster to return an appropriate class depending on the type of value it wrapped, or nil for types that wasn't supported.
This works, and I am able to make it work in Swift as well following the same pattern, but it doesn't feel Swift like.
What worked
Instead of wrapping the captured values as a way of enabling interpolation, I created a Mixable protocol that the types could conform to and used a protocol extension for when the type supported the necessary basic arithmetic:
protocol SimpleArithmeticType {
func +(lhs: Self, right: Self) -> Self
func *(lhs: Self, amount: Double) -> Self
}
protocol Mixable {
func mix(with other: Self, by amount: Double) -> Self
}
extension Mixable where Self: SimpleArithmeticType {
func mix(with other: Self, by amount: Double) -> Self {
return self * (1.0 - amount) + other * amount
}
}
This part worked really well and enforced homogeneous mixing (that a type could only be mixed with its own type), which wasn't enforced in the Objective-C implementation.
Where I got stuck
The next logical step, and this is where I got stuck, seemed to be to make each Capture instance (now a struct) hold two variables of the same mixable type instead of two AnyObject. I also changed the initializer argument from being an object and a key path to being a closure that returns an object ()->T
struct Capture<T: Mixable> {
typealias Evaluation = () -> T
let eval: Evaluation
let before: T
var after: T {
return eval()
}
init(eval: Evaluation) {
self.eval = eval
self.before = eval()
}
}
This works when the type can be inferred, for example:
let captureInt = Capture {
return 3.0
}
// > Capture<Double>
but not with key value coding, which return AnyObject:\
let captureAnyObject = Capture {
return myObject.valueForKeyPath("opacity")!
}
error: cannot invoke initializer for type 'Capture' with an argument list of type '(() -> _)'
AnyObject does not conform to the Mixable protocol, so I can understand why this doesn't work. But I can check what type the object really is, and since I'm only covering a handful of mixable types, I though I could cover all the cases and return the correct type of Capture. Too see if this could even work I made an even simpler example
A simpler example
struct Foo<T> {
let x: T
init(eval: ()->T) {
x = eval()
}
}
which works when type inference is guaranteed:
let fooInt = Foo {
return 3
}
// > Foo<Int>
let fooDouble = Foo {
return 3.0
}
// > Foo<Double>
But not when the closure can return different types
let condition = true
let foo = Foo {
if condition {
return 3
} else {
return 3.0
}
}
error: cannot invoke initializer for type 'Foo' with an argument list of type '(() -> _)'
I'm not even able to define such a closure on its own.
let condition = true // as simple as it could be
let evaluation = {
if condition {
return 3
} else {
return 3.0
}
}
error: unable to infer closure type in the current context
My Question
Is this something that can be done at all? Can a condition be used to determine the type of a generic? Or is there another way to hold two variables of the same type, where the type was decided based on a condition?
Edit
What I really want is to:
capture the values before and after a change and save the pair (old + new) for later (a heterogeneous collection of homogeneous pairs).
go through all the collected values and get rid of the ones that can't be interpolated (unless this step could be integrated with the collection step)
interpolate each homogeneous pair individually (mixing old + new).
But it seems like this direction is a dead end when it comes to solving that problem. I'll have to take a couple of steps back and try a different approach (and probably ask a different question if I get stuck again).
As discussed on Twitter, the type must be known at compile time. Nevertheless, for the simple example at the end of the question you could just explicitly type
let evaluation: Foo<Double> = { ... }
and it would work.
So in the case of Capture and valueForKeyPath: IMHO you should cast (either safely or with a forced cast) the value to the Mixable type you expect the value to be and it should work fine. Afterall, I'm not sure valueForKeyPath: is supposed to return different types depending on a condition.
What is the exact case where you would like to return 2 totally different types (that can't be implicitly casted as in the simple case of Int and Double above) in the same evaluation closure?
in my full example I also have cases for CGPoint, CGSize, CGRect, CATransform3D
The limitations are just as you have stated, because of Swift's strict typing. All types must be definitely known at compile time, and each thing can be of only one type - even a generic (it is resolved by the way it is called at compile time). Thus, the only thing you can do is turn your type into into an umbrella type that is much more like Objective-C itself:
let condition = true
let evaluation = {
() -> NSObject in // *
if condition {
return 3
} else {
return NSValue(CGPoint:CGPointMake(0,1))
}
}

What is the reason for which a function's return type cannot be var?

e.g.
public var SomeMethod()
{
return "hello";
}
error:
The contextual keyword var may only appear within a local variable declaration
Thanks
C# only supports type inference for local variables. It doesn't support it for the return type of a non-anonymous function. This is a design decision. It's possible that they change it in the future. Languages like F# do in fact support return type inference so there's no inherent impossibility involved here. Of course, sometimes, the inferred return type may be ambiguous and requires further clarification in the languages that support it:
// not real C#:
public var Method(bool returnInt) {
if (returnInt) return 42; else return true;
}
// what's the return type of Method is going to be? ValueType? object? ...?
I would recommend that you read Why no var on fields?:
In my recent request for things that make you go hmmm, a reader notes that you cannot use "var" on fields.
Now you don't want to use var for a field but you do want to use it for another purpose other than how it is specified. That article should give you a little insight into the compiler implementation around the var feature (and why, perhaps, var is not a valid return type).
Now, all that being said, it would be perfectly valid for the return type of a method to be inferred by the type of the return expression.
Consider a potentially ambiguous situation, a slight enhancement of your question:
public var SomeMethod() {
return DateTime.Now.Second % 2 == 0 ? "hello" : 3;
}
Should the compiler raise an error or infer type System.Object?
Only at runtime can the correct type be resolved between int and string.
var must be used on the left side of an initialization statement because its type is inferred by the C# compiler from the resulting data type on the right side.
var thing = 3;
// infers System.Int32 from right side.
var thing = 3L;
// infers System.Int64 from right side.
// This also applies to methods and things that have a defined type on the right side:
var thing = obj.AnyMethod();
If you could use var in place of the method return type, how could the C# compiler easily infer that type from all the logic inside the method?
var MyCall() { // ??? could be various things really
// lots of logic...
}
Available C# alternative
However, what you might be looking for in the C# language is to allow an interchangeable return type from your method via a Type Parameter and Generics like so:
T MyCall<T>() {
// lots of logic...
The caller can then specify the type that will be returned. Example:
An int.
var result = MyCall<int>();
// var will infer System.Int32
A string.
var result = MyCall<string>();
// var will infer System.String

F# Class with Generics : 'constructor deprecated' error

I am trying to create a a class that will store a time series of data - organized by groups, but I had some compile errors so I stripped down to the basics (just a simple instantiation) and still can't overcome the compile error. I was hoping some one may have seen this issue before. Clas is defined as:
type TimeSeriesQueue<'V, 'K when 'K: comparison> = class
val private m_daysInCache: int
val private m_cache: Map<'K, 'V list ref > ref;
val private m_getKey: ('V -> 'K) ;
private new(getKey) = {
m_cache = ref Map.empty
m_daysInCache = 7 ;
m_getKey = getKey ;
}
end
So that looks OK to me (it may not be, but doesnt have any errors or warnings) - the instantiation gets the error:
type tempRec = {
someKey: string ;
someVal1: int ;
someVal2: int ;
}
let keyFunc r:tempRec = r.someKey
// error occurs on the following line
let q = new TimeSeriesQueue<tempRec, string> keyFunc
This construct is deprecated: The use
of the type syntax 'int C' and 'C
' is not permitted here. Consider
adjusting this type to be written in
the form 'C'
NOTE This may be simple stupidity - I am just getting back from holiday and my brain is still on time zone lag...
The compiler is just saying that you need to enclose parameters of the constructor in parentheses:
// the following should work fine
let q = new TimeSeriesQueue<tempRec, string>(keyFunc)
There are some other issues though - the constructor needs to be public (otherwise you cannot call it) and the parameter of keyFunc should be also in parentheses (otherwise, the compiler will think that the type annotation is for the result of the function):
let keyFunc (r:tempRec) = r.someKey
You may also consider using implicit constructor syntax which makes class declarations a lot simpler in F#. Parameters of the constructor automatically become available in the body of the class and you can declare (private) fields simply using let:
type TimeSeriesQueue<'V, 'K when 'K: comparison>(getKey : 'V -> 'K) =
let daysInCache = 7
let cache = ref Map.empty
member x.Foo() = ()