How to properly type a generator function in Hack - hhvm

I'm playing around with Hack for a bit and tried to create a generator function using the yield keyword. The documentation states that the return type of such a function should be the Continuation interface. However, when running hh_client on the source code example of the generator function I get the following output:
./test.php:4:3,7: Invalid yield (Typing[4110])
./test.php:3:17,28: This is an object of type Continuation
./test.php:4:3,7: It is incompatible with an object of type Generator (result of function with 'yield' in the body)
This is test.php:
<?hh
function gen(): Generator<int> {
yield 1;
yield 2;
yield 3;
}
function foo(): void {
foreach (gen() as $x) {
echo $x, "\n";
}
}
foo();
Changing the result type to Generator gives even more warnings. What is the correct way of typing a generator function?

Any mention of Continuation in the docs is outdated and wrong. There's an open issue about it.
The correct type is Generator<Tk, Tv, Ts> -- there are actually three type parameters there. Here's an example of what they mean:
$r = yield $k => $v;
The type of that generator is Generator<Tk, Tv, Ts>, where Tk is the type of $k, Tv is the type of $v, and Ts is the type of $r.
For your code, this should work:
function gen(): Generator<int, int, void> {
yield 1;
yield 2;
yield 3;
}
The first int because there is implicitly an integer key; the second int because you are yielding ints, and the void since you don't care what values are sent into the generator.

Related

dart function - arrow syntax confliction

1. There is confliction on Dart Language tour
In Functions section, it says
The => expr syntax is a shorthand for { return expr; }.
Note: Only an expression—not a statement—can appear between the arrow (=>) and the semicolon (;). For example, you can’t put an if statement there, but you can use a conditional expression.
But in the Anonymous functions section, it says
If the function contains only one statement, you can shorten it using arrow notation
Does it mean I can use statement which is not an expression (such as if statement) in anonymous functions?
var fun = () => return 3; // However, this doesn't work.
var gun = () {
return 3; // this works.
}
Or am I confusing concept of expression and statement? I thought
expression : can be evaluated to a value ( 2 + 3 , print('') also falls into an expression )
statement : code that can be executed. all expressions can be statement. if statement and return statement are examples of statement which is not expression.
2. Is this expression or statement
void foo() => true; // this works.
void goo() {
return true; // this doesn't work.
}
void hoo() {
true; // this works.
}
If true is understood as expression, then it will mean return true and I believe it should not work because foo's return type is void.
Then does it mean true in foo is understood as a statement? But this conclusion contradicts with dart language tour. (They are top-level named functions). Also, this means we can use statement with arrow syntax.
I use VSCode and Dart from flutter: 1.22.5. I tell code that works from code that doesn't work based on VSCode error message.
Because this is my first question, I apologize for my short English and ill-formed question.
It must be an expression. The text is misleading.
For the second part, the error you see with
void foo() {
return 0;
}
and not with
void bar() => 0;
is a special case for => in functions returning void. Normally, you can't return a value from a function with return type void, so no return exp;, only return;.
(There are exceptions if exp has type void, null or dynamic, but yours doesn't).
Because people like the short-hand notation of void foo() => anything; so much, you are allowed to do that no matter what the type of anything is. That's why there is a distinction between void foo() { return 0; } and void foo() => 0;. They still mean the same thing, but the type-based error of the former is deliberately suppressed in the latter.
I'm guessing that the author of that section under Anonymous functions was a bit confused. File an issue against it, and get it corrected!
Yeah, even in their example they use a print() function, which they might be confusing as a print "statement", which it clearly is not.

TypeScript const assertions: how to use Array.prototype.includes?

I am trying to use an array of elements as union type, something that became easy with const assertions in TS 3.4, so I can do this:
const CAPITAL_LETTERS = ['A', 'B', 'C', ..., 'Z'] as const;
type CapitalLetter = typeof CAPITAL_LETTERS[string];
Now I want to test whether a string is a capital letter, but the following fails with "not assignable to parameter of type":
let str: string;
...
CAPITAL_LETTERS.includes(str);
Is there any better way to fix this rather than casting CAPITAL_LETTERS to unknown and then to Array<string>?
The standard library signature for Array<T>.includes(u) assumes that the value to be checked is of the same or narrower type than the array's elements T. But in your case you are doing the opposite, checking against a value which is of a wider type. In fact, the only time you would say that Array<T>.includes<U>(x: U) is a mistake and must be prohibited is if there is no overlap between T and U (i.e., when T & U is never).
Now, if you're not going to be doing this sort of "opposite" use of includes() very often, and you want zero runtime efects, you should just widen CAPITAL_LETTERS to ReadonlyArray<string> via type assertion:
(CAPITAL_LETTERS as ReadonlyArray<string>).includes(str); // okay
If, on the other hand, you feel seriously enough that this use of includes() should be accepted with no type assertions, and you want it to happen in all of your code, you could merge in a custom declaration:
// global augmentation needed if your code is in a module
// if your code is not in a module, get rid of "declare global":
declare global {
interface ReadonlyArray<T> {
includes<U>(x: U & ((T & U) extends never ? never : unknown)): boolean;
}
}
That will make it so that an array (well, a readonly array, but that's what you have in this example) will allow any parameter for .includes() as long as there is some overlap between the array element type and the parameter type. Since string & CapitalLetter is not never, it will allow the call. It will still forbid CAPITAL_LETTERS.includes(123), though.
Okay, hope that helps; good luck!
Another way to solve it is with a type guard
https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards
const myConstArray = ["foo", "bar", "baz"] as const
function myFunc(x: string) {
//Argument of type 'string' is not assignable to parameter of type '"foo" | "bar" | "baz"'.
if (myConstArray.includes(x)) {
//Hey, a string could totally be one of those values! What gives, TS?
}
}
//get the string union type
type TMyConstArrayValue = typeof myConstArray[number]
//Make a type guard
//Here the "x is TMyConstArrayValue" tells TS that if this fn returns true then x is of that type
function isInMyConstArray(x: string): x is TMyConstArrayValue {
return myConstArray.includes(x as TMyConstArrayValue)
//Note the cast here, we're doing something TS things is unsafe but being explicit about it
//I like to this of type guards as saying to TS:
//"I promise that if this fn returns true then the variable is of the following type"
}
function myFunc2(x: string) {
if (isInMyConstArray(x)) {
//x is now "foo" | "bar" | "baz" as originally intended!
}
}
While you have to introduce another "unnecessary" function this ends up looking clean and working perfectly. In your case you would add
const CAPITAL_LETTERS = ['A', 'B', 'C', ..., 'Z'] as const;
type CapitalLetter = typeof CAPITAL_LETTERS[string];
function isCapitalLetter(x: string): x is CapitalLetter {
return CAPITAL_LETTERS.includes(x as CapitalLetter)
}
let str: string;
isCapitalLetter(str) //Now you have your comparison
//Not any more verbose than writing .includes inline
if(isCapitalLetter(str)){
//now str is of type CapitalLetter
}
Here's a solution that works well for strings & string literals using TypeScript 4.1 Template Literal Types that doesn't break anything else, and also narrows the type for convenience when used in conditions:
declare global {
interface ReadonlyArray<T> {
includes<S, R extends `${Extract<S, string>}`>(
this: ReadonlyArray<R>,
searchElement: S,
fromIndex?: number
): searchElement is R & S;
}
}
Originally posted by noppa in a TypeScript github issue related to this.
Adding to #imagio's answer, you can make the genetic type guard (thanks to #wprl for simplification)
function isIn<T>(values: readonly T[], x: any): x is T {
return values.includes(x);
}
And use it with any as const array:
const specialNumbers = [0, 1, 2, 3] as const;
function foo(n: number) {
if (isIn(specialNumbers, n)) {
//TypeScript will say that `s` has type `0 | 1 | 2 | 3` here
}
}
You can also create a curried version of Array.prototype.includes which works with tuples:
const PROPS = ['a', 'b', 'c'] as const;
const withTuple = <
List extends string[]
>(list: readonly [...List]) =>
(prop: string): prop is List[number] =>
list.includes(prop)
const includes = withTuple(PROPS);
const result = includes('d')
declare let str: string
if (includes(str)) {
str // "a" | "b" | "c"
}
Playground
Higher order function with list argument created for inference.
You can also check my article
Reassignment using a wider type annotation is potentially the simplest solution, if a little untidy due to adding an extraneous variable.
const CAPITAL_LETTERS = ['A', 'B', 'C', ..., 'Z'] as const;
const widenedCapitalLetters: string[] = CAPITAL_LETTERS
widenedCapitalLetters.includes("hello")
This allows you to keep the const assertion on the base array so you get the type narrowing you need.
using lodash
const CAPITAL_LETTERS = ['A', 'B', 'C', 'Z'] as const;
_.includes(CAPITAL_LETTERS, 'A');

what does 'T', 'f', 'E', 'e', '→' stand for in dart/flutter docs?

i`m learning the flutter, but i do not understand those letters meaning.
map<T>(T f(E e)) → Iterable<T>
Returns a new lazy Iterable with elements that are created by
calling f on each element of this Iterable in iteration order. [...]
so,what do they stand for?
T:
f:
E:
e:
→:
Iterable.map<T>:
map<T>(T f(E e)) → Iterable<T>
Returns a new lazy Iterable with elements that are created by calling
f on each element of this Iterable in iteration order. [...]
T is a language Type in this case the Type of the items of the iterable and is also the type that function f must return.
→ tells you the return type of the whole function (map) in this case an Iterable of T
f is the function applied to the Element e that is passed as the parameter to the function so that the function could do some operation with this current value and then return a new value of type T based on the value of the element e.
If you navigate the Iterable map function definition you will see that:
Iterable<T> map <T>(
T f(
E e
)
)
So I wanna sharpen my answer starting with the exact map<T> function of the OP and then swich to a more complex example.
Just to clarify all these let's take a concrete class of the Iterable class, the Set class choosing a Set of type String in such a scenario:
Set<String> mySet = Set();
for (int i=0; i++<5;) {
mySet.add(i.toString());
}
var myNewSet = mySet.map((currentValue) => (return "new" + currentValue));
for (var newValue in myNewSet) {
debugPrint(newValue);
}
Here I've got a Set of String Set<String> and I want another Set of String Set<String> so that the value is the same value of the original map, but sorrounded with a prefix of "new:". And for that we could easily use the map<T> along with the closure it wants as paraemters.
The function passed as closure is
(currentValue) => ("new:" + currentValue)
And if we want we could write it also like that:
(currentValue) {
return "new:" + currentValue;
}
or even pass a function like that:
String modifySetElement(String currentValue) {
return "new:" + currentValue;
}
var myNewSet = mySet.map((value) => ("new:" + value));
var myNewSet = mySet.map((value) {return "new:" + value;});
var myNewSet = mySet.map((value) => modifySetElement("new:" + value));
And this means that the parameter of the function (closure) is the String value of the element E of the Set we're modifying.
We don't even have to specify the type because its inferred by method definition, that's one of the power of generics.
The function (closure) will be applied to all the Set's elements once at a time, but you write it once as a closure.
So summarising:
T is String
E is the element we are dealing with inside of the function
f is our closure
Let's go deeper with a more complex example. We'll now deal with the Dart Map class.
Its map function is define like that:
map<K2, V2>(MapEntry<K2, V2> f(K key, V value)) → Map<K2, V2>
So in this case the previous first and third T is (K2, V2) and the return type of the function f (closure), that takes as element E parameter the pair K and V (that are the key and value of the current MapEntry element of the iteration), is a type of MapEntry<K2, V2> and is the previous second T.
The whole function then return a new Map<K2, V2>
The following is an actual example with Map:
Map<int, String> myMap = Map();
for (int i=0; i++<5;) {
myMap[i] = i.toString();
}
var myNewMap = myMap.map((key, value) => (MapEntry(key, "new:" + value)));
for (var mapNewEntry in myNewMap.entries) {
debugPrint(mapNewEntry.value);
}
In this example I've got a Map<int, String> and I want another Map<int, String> so that (like before) the value is the same value of the original map, but sorrounded with a prefix of "new:".
Again you could write the closure (your f function) also in this way (maybe it highlights better the fact that it's a fanction that create a brand new MapEntry based on the current map entry value).
var myNewMap = myMap.map((key, value) {
String newString = "new:" + value;
return MapEntry(key, newString);
});
All these symbols are called Generics because they are generic placeholder that correspond to a type or another based on the context you are using them.
That's an extract from the above link:
Using generic methods
Initially, Dart’s generic support was limited to classes. A newer syntax, called generic methods, allows
type arguments on methods and functions:
T first<T>(List<T> ts) {
// Do some initial work or error checking, then...
T tmp = ts[0];
// Do some additional checking or processing...
return tmp;
}
Here the generic type parameter on first () allows you to use the
type argument T in several places:
In the function’s return type (T). In the type of an argument
(List<T>). In the type of a local variable (T tmp).
Follow this link for Generics name conventions.

How to do 'function pointers' in Rascal?

Does Rascal support function pointers or something like this to do this like Java Interfaces?
Essentially I want to extract specific (changing) logic from a common logic block as separate functions. The to be used function is passed to the common block, which then call this function. In C we can do this with function pointers or with Interfaces in Java.
First I want to know how this general concept is called in the language design world.
I checked the Rascal Function Helppage, but this provide no clarification on this aspect.
So e.g. I have:
int getValue(str input) {
.... }
int getValue2(str input){
... }
Now I want to say:
WhatDatatype? func = getValue2; // how to do this?
Now I can pass this to an another function and then:
int val = invoke_function(func,"Hello"); // how to invoke?, and pass parameters and get ret value
Tx,
Jos
This page in the tutor has an example of using higher-order functions, which are the Rascal feature closest to function pointers:
http://tutor.rascal-mpl.org/Rascal/Rascal.html#/Rascal/Concepts/Functions/Functions.html
You can define anonymous (unnamed) functions, called closures in Java; assign them to variables; pass them as arguments to functions (higher-order functions); etc. Here is an example:
rascal>myfun = int(int x) { return x + 1; };
int (int): int (int);
rascal>myfun;
int (int): int (int);
rascal>myfun(3);
int: 4
rascal>int applyIntFun(int(int) f, int x) { return f(x); }
int (int (int), int): int applyIntFun(int (int), int);
rascal>applyIntFun(myfun,10);
int: 11
The first command defines an increment function, int(int x) { return x + 1; }, and assigns this to variable myfun. The rest of the code would work the same if instead this was
int myfun(int x) { return x + 1; }
The second command just shows the type, which is a function that takes and returns int. The third command calls the function with value 3, returning 4. The fourth command then shows a function which takes a function as a parameter. This function parameter, f, will then be called with argument x. The final command just shows an example of using it.

How does F# compile functions that can take multiple different parameter types into IL?

I know virtually nothing about F#. I don’t even know the syntax, so I can’t give examples.
It was mentioned in a comment thread that F# can declare functions that can take parameters of multiple possible types, for example a string or an integer. This would be similar to method overloads in C#:
public void Method(string str) { /* ... */ }
public void Method(int integer) { /* ... */ }
However, in CIL you cannot declare a delegate of this form. Each delegate must have a single, specific list of parameter types. Since functions in F# are first-class citizens, however, it would seem that you should be able to pass such a function around, and the only way to compile that into CIL is to use delegates.
So how does F# compile this into CIL?
This question is a little ambiguous, so I'll just ramble about what's true of F#.
In F#, methods can be overloaded, just like C#. Methods are always accessed by a qualified name of the form someObj.MethodName or someType.MethodName. There must be context which can statically resolve the overload at compile-time, just as in C#. Examples:
type T() =
member this.M(x:int) = ()
member this.M(x:string) = ()
let t = new T()
// these are all ok, just like C#
t.M(3)
t.M("foo")
let f : int -> unit = t.M
let g : string-> unit = t.M
// this fails, just like C#
let h = t.M // A unique overload for method 'M' could not be determined
// based on type information prior to this program point.
In F#, let-bound function values cannot be overloaded. So:
let foo(x:int) = ()
let foo(x:string) = () // Duplicate definition of value 'foo'
This means you can never have an "unqualified" identifier foo that has overloaded meaning. Each such name has a single unambiguous type.
Finally, the crazy case which is probably the one that prompts the question. F# can define inline functions which have "static member constraints" which can be bound to e.g. "all types T that have a member property named Bar" or whatnot. This kind of genericity cannot be encoded into CIL. Which is why the functions that leverage this feature must be inline, so that at each call site, the code specific-to-the-type-used-at-that-callsite is generated inline.
let inline crazy(x) = x.Qux(3) // elided: type syntax to constrain x to
// require a Qux member that can take an int
// suppose unrelated types U and V have such a Qux method
let u = new U()
crazy(u) // is expanded here into "u.Qux(3)" and then compiled
let v = new V()
crazy(v) // is expanded here into "v.Qux(3)" and then compiled
So this stuff is all handled by the compiler, and by the time we need to generate code, once again, we've statically resolved which specific type we're using at this callsite. The "type" of crazy is not a type that can be expressed in CIL, the F# type system just checks each callsite to ensure the necessary conditions are met and inlines the code into that callsite, a lot like how C++ templates work.
(The main purpose/justification for the crazy stuff is for overloaded math operators. Without the inline feature, the + operator, for instance, being a let-bound function type, could either "only work on ints" or "only work on floats" or whatnot. Some ML flavors (F# is a relative of OCaml) do exactly that, where e.g. the + operator only works on ints, and a separate operator, usually named +., works on floats. Whereas in F#, + is an inline function defined in the F# library that works on any type with a + operator member or any of the primitive numeric types. Inlining can also have some potential run-time performance benefits, which is also appealing for some math-y/computational domains.)
When you're writing C# and you need a function that can take multiple different parameter sets, you just create method overloads:
string f(int x)
{
return "int " + x;
}
string f(string x)
{
return "string " + x;
}
void callF()
{
Console.WriteLine(f(12));
Console.WriteLine(f("12"));
}
// there's no way to write a function like this:
void call(Func<int|string, string> func)
{
Console.WriteLine(func(12));
Console.WriteLine(func("12"));
}
The callF function is trivial, but my made-up syntax for the call function doesn't work.
When you're writing F# and you need a function that can take multiple different parameter sets, you create a discriminated union that can contain all the different parameter sets and you make a single function that takes that union:
type Either = Int of int
| String of string
let f = function Int x -> "int " + string x
| String x -> "string " + x
let callF =
printfn "%s" (f (Int 12))
printfn "%s" (f (String "12"))
let call func =
printfn "%s" (func (Int 12))
printfn "%s" (func (String "12"))
Being a single function, f can be used like any other value, so in F# we can write callF and call f, and both do the same thing.
So how does F# implement the Either type I created above? Essentially like this:
public abstract class Either
{
public class Int : Test.Either
{
internal readonly int item;
internal Int(int item);
public int Item { get; }
}
public class String : Test.Either
{
internal readonly string item;
internal String(string item);
public string Item { get; }
}
}
The signature of the call function is:
public static void call(FSharpFunc<Either, string> f);
And f looks something like this:
public static string f(Either _arg1)
{
if (_arg1 is Either.Int)
return "int " + ((Either.Int)_arg1).Item;
return "string " + ((Either.String)_arg1).Item;
}
Of course you could implement the same Either type in C# (duh!), but it's not idiomatic, which is why it wasn't the obvious answer to the previous question.
Assuming I understand the question, in F# you can define expressions which depend on the availability of members with particular signatures. For instance
let inline f x a = (^t : (member Method : ^a -> unit)(x,a))
This defines a function f which takes a value x of type ^t and a value a of type ^a where ^t has a method Method taking an ^a to unit (void in C#), and which calls that method. Because this function is defined as inline, the definition is inlined at the point of use, which is the only reason that it can be given such a type. Thus, although you can pass f as a first class function, you can only do so when the types ^t and ^a are statically known so that the method call can be statically resolved and inserted in place (and this is why the type parameters have the funny ^ sigil instead of the normal ' sigil).
Here's an example of passing f as a first-class function:
type T() =
member x.Method(i) = printfn "Method called with int: %i" i
List.iter (f (new T())) [1; 2; 3]
This runs the method Method against the three values in the list. Because f is inlined, this is basically equivalent to
List.iter ((fun (x:T) a -> x.Method(a)) (new T())) [1; 2; 3]
EDIT
Given the context that seems to have led to this question (C# - How can I “overload” a delegate?), I appear not to have addressed your real question at all. Instead, what Gabe appears to be talking about is the ease with which one can define and use discriminated unions. So the question posed on that other thread might be answered like this using F#:
type FunctionType =
| NoArgument of (unit -> unit)
| ArrayArgument of (obj[] -> unit)
let doNothing (arr:obj[]) = ()
let doSomething () = printfn "'doSomething' was called"
let mutable someFunction = ArrayArgument doNothing
someFunction <- NoArgument doSomething
//now call someFunction, regardless of what type of argument it's supposed to take
match someFunction with
| NoArgument f -> f()
| ArrayArgument f -> f [| |] // pass in empty array
At a low level, there's no CIL magic going on here; it's just that NoArgument and ArrayArgument are subclasses of FunctionType which are easy to construct and to deconstruct via pattern matching. The branches of the pattern matching expression are morally equivalent to a type test followed by property accesses, but the compiler makes sure that the cases have 100% coverage and don't overlap. You could encode the exact same operations in C# without any problem, but it would be much more verbose and the compiler wouldn't help you out with exhaustiveness checking, etc.
Also, there is nothing here which is particular to functions; F# discriminated unions make it easy to define types which have a fixed number of named alternatives, each one of which can have data of whatever type you'd like.
I'm not quite sure that understand your question correctly... F# compiler uses FSharpFunc type to represent functions. Usually in F# code you don't deal with this type directly, using fancy syntactic representation instead, but if you expose any members that returns or accepts function and use them from another language, line C# - you will see it.
So instead of using delegates - F# utilizes its special type with concrete or generic parameters.
If your question was about things like add something-i-don't-know-what-exactly-but-it-has-addition-operator then you need to use inline keyword and compiler will emit function body in the call site. #kvb's answer was describing exactly this case.

Resources