"The type of pattern could not be computed" when iterating over aliased rel[loc,str,int,int] - rascal

I have a rel[loc, str, int, int] which I aliased as ECCModel
Iterating over it in a function results in an error "Type of pattern could not be computed" when elements of the pattern are called location. When named anything other than location, the errors disappear. Is "location" a reserved word in Rascal? Regardless of the errors, it will compile and run just fine.
The error can be produced with the following method
alias ECCModel = rel[loc, str, int, int]
map[str,int] Foo(ECCModel bar)
{
return (y : z | <location, y, z, _> <- bar);
}
Is this expected behavior?

This is not expected behavior and location is not a reserved word, but loc is.
I think this is a glitch of the current compiler.
For your clarification: we currently have three implementations of Rascal:
The Rascal interpreter.
The current (also already sometimes called "old") compiler.
The new compiler we are working on that is not yet released.
Your example runs fine with the interpreter and new compiler. So the problem you are reporting will disappear over time.

Related

I don't understand this map tuple key compilation error, in F#

Here is a function:
let newPositions : PositionData list =
positions
|> List.filter (fun x ->
let key = (x.Instrument, x.Side)
match brain.Positions.TryGetValue key with
| false, _ ->
// if we don't know the position, it's new
true
| true, p when x.UpdateTime > p.UpdateTime ->
// it's newer than the version we have, it's new
true
| _ ->
false
)
it compiles at expected.
let's focus on two lines:
let key = (x.Instrument, x.Side)
match brain.Positions.TryGetValue key with
brain.Positions is a Map<Instrument * Side, PositionData> type
if I modify the second line to:
match brain.Positions.TryGetValue (x.Instrument, x.Side) with
then the code will not compile, with error:
[FS0001] This expression was expected to have type
'Instrument * Side'
but here has type
'Instrument'
but:
match brain.Positions.TryGetValue ((x.Instrument, x.Side)) with
will compile...
why is that?
This is due to method call syntax.
TryGetValue is not a function, but a method. A very different thing, and a much worse thing in general. And subject to some special syntactic rules.
This method, you see, actually has two parameters, not one. The first parameter is a key, as you expect. And the second parameter is what's known in C# as out parameter - i.e. kind of a second return value. The way it was originally meant to be called in C# is something like this:
Dictionary<int, string> map = ...
string val;
if (map.TryGetValue(42, out val)) { ... }
The "regular" return value of TryGetValue is a boolean signifying whether the key was even found. And the "extra" return value, denoted here out val, is the value corresponding to the key.
This is, of course, extremely awkward, but it did not stop the early .NET libraries from using this pattern very widely. So F# has special syntactic sugar for this pattern: if you pass just one parameter, then the result becomes a tuple consisting of the "actual" return value and the out parameter. Which is what you're matching against in your code.
But of course, F# cannot prevent you from using the method exactly as designed, so you're free to pass two parameters as well - the first one being the key and the second one being a byref cell (which is F# equivalent of out).
And here is where this clashes with the method call syntax. You see, in .NET all methods are uncurried, meaning their arguments are all effectively tupled. So when you call a method, you're passing a tuple.
And this is what happens in this case: as soon as you add parentheses, the compiler interprets that as an attempt to call a .NET method with tupled arguments:
brain.Positions.TryGetValue (x.Instrument, x.Side)
^ ^
first arg |
second arg
And in this case it expects the first argument to be of type Instrument * Side, but you're clearly passing just an Instrument. Which is exactly what the error message tells you: "expected to have type 'Instrument * Side'
but here has type 'Instrument'".
But when you add a second pair of parens, the meaning changes: now the outer parens are interpreted as "method call syntax", and the inner parens are interpreted as "denoting a tuple". So now the compiler interprets the whole thing as just a single argument, and all works as before.
Incidentally, the following will also work:
brain.Positions.TryGetValue <| (x.Instrument, x.Side)
This works because now it's no longer a "method call" syntax, because the parens do not immediately follow the method name.
But a much better solution is, as always, do not use methods, use functions instead!
In this particular example, instead of .TryGetValue, use Map.tryFind. It's the same thing, but in proper function form. Not a method. A function.
brain.Positions |> Map.tryFind (x.Instrument, x.Side)
Q: But why does this confusing method even exist?
Compatibility. As always with awkward and nonsensical things, the answer is: compatibility.
The standard .NET library has this interface System.Collections.Generic.IDictionary, and it's on that interface that the TryGetValue method is defined. And every dictionary-like type, including Map, is generally expected to implement that interface. So here you go.
In future, please consider the Stack Overflow guidelines provided under How to create a Minimal, Reproducible Example. Well, minimal and reproducible the code in your question is, but it shall also be complete...
…Complete – Provide all parts someone else needs to reproduce your
problem in the question itself
That being said, when given the following definitions, your code will compile:
type Instrument() = class end
type Side() = class end
type PositionData = { Instrument : Instrument; Side : Side; }
with member __.UpdateTime = 0
module brain =
let Positions = dict[(Instrument(), Side()), {Instrument = Instrument(); Side = Side()}]
let positions = []
Now, why is that? Technically, it is because of the mechanism described in the F# 4.1 Language Specification under §14.4 Method Application Resolution, 4. c., 2nd bullet point:
If all formal parameters in the suffix are “out” arguments with byref
type, remove the suffix from UnnamedFormalArgs and call it
ImplicitlyReturnedFormalArgs.
This is supported by the signature of the method call in question:
System.Collections.Generic.IDictionary.TryGetValue(key: Instrument * Side, value: byref<PositionData>)
Here, if the second argument is not provided, the compiler does the implicit conversion to a tuple return type as described in §14.4 5. g.
You are obviously familiar with this behaviour, but maybe not with the fact that if you specify two arguments, the compiler will see the second of them as the explicit byref "out" argument, and complains accordingly with its next error message:
Error 2 This expression was expected to have type
PositionData ref
but here has type
Side
This misunderstanding changes the return type of the method call from bool * PositionData to bool, which consequently elicits a third error:
Error 3 This expression was expected to have type
bool
but here has type
'a * 'b
In short, your self-discovered workaround with double parentheses is indeed the way to tell the compiler: No, I am giving you only one argument (a tuple), so that you can implicitly convert the byref "out" argument to a tuple return type.

F# Deedle accessing a row

this is a basic question but i could not find the simple answer reading the tutorial
suppose i have this simple frame
type Person =
{ Name:string; Age:int; Countries:string list; }
let peopleRecds =
[ { Name = "Joe"; Age = 51; Countries = [ "UK"; "US"; "UK"] }
{ Name = "Tomas"; Age = 28; Countries = [ "CZ"; "UK"; "US"; "CZ" ] }
{ Name = "Eve"; Age = 2; Countries = [ "FR" ] }
{ Name = "Suzanne"; Age = 15; Countries = [ "US" ] } ]
// Turn the list of records into data frame
let peopleList = Frame.ofRecords peopleRecds
// Use the 'Name' column as a key (of type string)
let people = peopleList |> Frame.indexRowsString "Name"
How do i access the value the row for Joe ? (as a record, tuple or whatever format)
i tried this
getRow "Joe" people;;
 
Stopped due to error  System.Exception: Operation could not be
completed due to earlier error  Value restriction. The value 'it' has
been inferred to have generic type
  val it : Series  Either define 'it' as a simple data term, make it a function with explicit arguments or, if you do
not intend for it to be generic, add a type annotation. at 3,0
EDIT: thanks for the answer, still i would like to know why my syntax is incorrect because i think i respected the signature
val it :
  ('a -> Frame<'a,'b> -> Series<'b,'c>) when 'a : equality and 'b : equality
I'll answer the second half of your question, why you got a "value restriction" error. If you search for [f#] value restriction on Stack Overflow you'll find lots of answers, which may or may not confuse you. But the really short version is: F# is built on top of the .Net framework, and .Net imposes certain limitations. Specifically, functions are allowed to be generic, but values cannot be generic. So you can do this:
let f<'TData> (a:'TData) = printfn "%A" a
but you cannot do this:
let (a:'TData) = Unchecked.defaultof<'TData>
The function definition is fine, because the underlying .Net framework knows how to handle generic functions. But you're not allowed to have generic values in .Net; any value must be a specific type.
(Note: I wrote the <'TData> in the f definition explicitly, but I didn't have to: I could have just written let f (a:'TData) = printfn "%A" a and the genericness of f would have still been understood. I could even have just written let f a = printfn "%A" a, and it would have done the same thing).
Now let's look at the error you got: "the value "it" has been inferred to have generic type val it : Series<string,obj>". If you look at the function signature of getRow that you posted, it looks like this:
('a -> Frame<'a,'b> -> Series<'b,'c>)
When you called it as getRow "Joe" people, the F# compiler was able to infer that the type 'a was string (because the parameter "Joe" is a string). And because the second argument people is a Frame<string,string>, the F# compiler was able to infer that the type 'b was also string. But the result of that function call is a Series<'b,'c>, and so far the F# compiler doesn't know anything about what 'c will be. And since you ran getRow "Joe" people at the F# interactive REPL, it tried to store the result of what you typed as the value of the name it (the F# interactive REPL always provides the value of the previous expression as it) -- but since the only type it knew so far was Series<string,'c>, F# couldn't figure out what specific type to assign to the value it. I know from looking at your code that the type 'c was the Person record, but the F# compiler couldn't know that from just that one call to getRow, because of how the getRow function is typed.
There are two ways you could have solved this value restriction error:
One way to solve this would have been to pipe the result of getRow into another function, which would have allowed the F# compiler to infer the specific type of its result. Unfortunately, since I don't know Deedle that well, I can't give you a good example here. Maybe someone else will come up with one and comment on this answer, and I'll edit it in. It would look like:
getRow "Joe" people |> (some Deedle function)
But I don't know which Deedle function to use in my example: it would have to be a function that takes a Series and does some specific calculation with it, in a way that would allow F# to infer that this is a Series<string,Person>. Sorry this isn't a great example, but I'll leave it in anyway in case it helps.
The second way you could have solved the error would have been to specify the type of the value you were getting. In F#, you do that with the : (type) syntax, e.g.:
getRow "Joe" people : Series<string,Person>
Or, since the F# compiler has enough information to infer the string part of that type, you could also have written:
getRow "Joe" people : Series<_,Person>
When you write _ in a type signature, you're telling the F# compiler "You figure out what type this is". This only works when the F# compiler has enough information to infer that type correctly, but it's often a handy shorthand when type signatures would be large and unwieldy.
Both of these approaches would have solved your immediate problem, gotten rid of the "value restriction" error, and allowed you to continue working.
I hope this answer helps you. If it hopelessly confuses you instead, let me know and I'll see if I can explain whatever has you confused.
EDIT: In the comments, Soldalma asks whether the F# compiler (which is a one-pass compiler that works top to bottom and left to right) can infer the type from a forward pipe. The answer is yes, because the expression isn't finished yet. As long as an expression isn't finished, F#'s type inference (which is based on the Hindley-Milner type system*) is fine with carrying around a set of not-yet-resolved types. And if the types are resolved before the expression is complete, then the expression can resolve to a specific value (or a specific function). If the types are not yet resolved when the expression is complete, then it has to resolve to a generic value or function. And generic functions are allowed in .Net, but not generic values, hence the "value restriction" error.
To see this in practice, let's look at some example code. Copy and paste the following code into an F# editor that lets you hover over a variable (or function) name to see its type. I recommend VS Code with the Ionide-fsharp extension since it's cross-platform, but Visual Studio will work just as well.
open System.Collections.Generic
let mkDict (key:'K) = new Dictionary<'K,'V>() // Legal
let getValueOrDefault (key:'a) (defaultVal:'b) (dict:Dictionary<'a,'b>) =
match dict.TryGetValue key with
| true,v -> v
| false,_ -> defaultVal
let d = mkDict "foo" // Error: value restriction
let bar = mkDict "foo" |> getValueOrDefault "foo" "bar" // Legal: type string
let five = mkDict "foo" |> getValueOrDefault "foo" 5 // Legal: type int
Go ahead and hover your cursor over each function and variable name to see its type, or else hit Alt+Enter to send each function or variable declaration to F# Interactive. (And once you've seen that the let d line gives a "value restriction" error, comment it out so the rest of the code will compile).
What's happening here is a good demonstration of how this all works. The mkDict function has two unresolved types, 'K and 'V, so it has to be generic. But that's fine, because .Net has no problem with generic functions. (mkDict isn't actually very useful, since it actually "throws away" the data of its argument and does nothing to it. But it's supposed to be a trivial example, so just ignore the fact that it's kind of useless.) Likewise, getValueOrDefault has two unresolved types, 'a and 'b, so it's also a generic function.
However, let d = mkDict "foo" is not legal. Here, the generic type 'K has been resolved to be the specific type string, but 'V has not yet been resolved by the time the expression is complete so d would have to be generic (it would look like d<'V> in explicitly-generic syntax). But d is not a function (since it has no parameters), it's the name of a value, and .Net doesn't allow generic values.
But in the next two lines, the expression is not complete by the time the compiler has parsed mkDict "foo", so it doesn't yet have to "lock in" the unknown types. It can quite happily carry the unresolved type 'V into the next part of the expression. And there, the getValueOrDefault function has two specific types, string and string in the first line, and string and int in the second line. Because its 'b type corresponds to the 'V type from mkDict, therefore F# can resolve 'V in both lines. And so bar has type string, and five has type int.
* Scott Wlaschin says that it should "more accurately ... be called "Damas-Milner's Algorithm W" ". Since I haven't studied it in detail myself, I'll take his word for it -- but if you're interested in learning more, the Wikipedia link I provided is probably a halfway decent starting point.
I'll be very short, promoting my comment to an answer.
You need to use syntax reverse to the one you have tried:
people.Rows.["Joe"]

.fsx script ignoring a function call when I add a parameter to it

Alright, so I'm a happy fsx-script programmer, because I love how I can have the compiler shout at me when I do mistakes before they show up at runtime.
However I've found a case which really bothers me because I was expecting that by doing some refactoring (i.e.: adding an argument to a function) I was going to be warned by the compiler about all the places where I need to put the new argument. But, not only this did not happen, fsharpi ran my script and ignored the function call completely!! :(
How can I expect to refactor my scripts if this happens?
Here is my code:
let Foo (bar: string) =
Console.WriteLine("I received " + bar)
Foo("hey")
It works.
Now, later, I decide to add a second argument to the function (but I forget to add the argument to all the calls to it):
let Foo (bar: string) (baz: bool) =
Console.WriteLine("I received " + bar)
Foo("hey")
The result of this is: instead of the compiler telling me that I'm missing an argument, it is fsharpi running the script and ignoring the call to Foo! Why?
PS: I know the difference between currying and tuples, so I know Foo("hey") becomes a function (instead of a function call), because of partial application. But I want to understand better why the compiler is not expecting a function evaluation here, instead of seeing a function and ignoring it. Can I enable a warningAsError somehow? I would like to avoid resorting to using tuples in order to workaround this problem.
The fsharpi (or fsi if you're on Windows) interpreter makes no distinction between running a script and typing code at the interactive prompt (or, most often, submitting code from your editor via a select-and-hit-Alt-Enter keyboard shortcut).
Therefore, if you got what you're asking for -- fsharpi issuing a warning whenever a script line has a return value that isn't () -- it would ruin the value of fsharpi for the most common use case, which is people using an interactive fsharpi session to test their code, and rapidly iterate through non-working prototypes to get to one that works correctly. This is one of F#'s great strengths, and giving you what you're asking for would eliminate that strength. It is therefore never going to happen.
BUT... that doesn't mean that you're sunk. If you have functions that return unit, and you want fsharpi to give you a compile-time error when you refactor them to take more arguments, you can do it this way. Replace all occurrences of:
Foo("hey")
with:
() = Foo("hey")
As long as the function Foo has only one argument (and returns null), this will evaluate to true; the true value will be happily ignored by fsharpi, and your script will run. However, if you then change Foo to take two arguments, so that Foo("hey") now returns a function, the () = Foo("hey") line will no longer compile, and you'll get an error like:
error FS0001: This expression was expected to have type
unit
but here has type
'a -> unit
So if you want fsharpi to refuse to compile your script when you refactor a function, go through and change your calls to () = myfunc arg1 arg2. For functions that don't return unit, make the value you're testing against a value of that function's return type. For example, given this function:
let f x = x * 2
You could do
0 = f 5
This will be false, of course, but it will compile. But if you refactor f:
let f x y = x * 2 + y
Now the line 0 = f 5 will not compile, but will give you the error message:
error FS0001: This expression was expected to have type
int
but here has type
int -> int
To summarize: you won't ever get the feature you're looking for, because it would harm the language. But with a bit of work, you can do something that fits your needs.
Or in other words, as the famous philosopher Mick Jagger once put it:
You can't always get what you want. But if you try, sometimes you might find you get what you need.

Erlang Dialyzer: only accept certain integers?

Say I have a function,foo/1, whose spec is -spec foo(atom()) -> #r{}., where #r{} is a record defined as -record(r, {a :: 1..789})., however, I have foo(a) -> 800. in my code, when I run dialyzer against it, it didn't warn me about this, (800 is not a "valid" return value for function foo/1), can I make dialyzer warn me about this?
Edit
Learn You Some Erlang says:
Dialyzer reserves the right to expand this range into a bigger one.
But I couldn't find how to disable this.
As of Erlang 18, the handling of integer ranges is done by erl_types:t_from_range/2. As you can see, there are a lot of generalizations happening to get a "safe" overapproximation of a range.
If you tried to ?USE_UNSAFE_RANGES (see the code) it is likely that your particular error would be caught, but at a terrible cost: native compilation and dialyzing of recursive integer functions would not ever finish!
The reason is that the type analysis for recursive functions uses a simple fixpoint approach, where the initial types accept the base cases and are repeatedly expanded using the recursive cases to include more values. At some point overapproximations must happen if the process is to terminate. Here is a concrete example:
fact(1) -> 1;
fact(N) -> N * fact(N - 1).
Initially fact/1 is assumed to have type fun(none()) -> none(). Using that to analyse the code, the second clause is 'failing' and only the first one is ok. Therefore after the first iteration the new type is fun(1) -> 1. Using the new type the second clause can succeed, expanding the type to fun(1|2) -> 1|2. Then fun(1|2|3) -> 1|2|6 this continues until the ?SET_LIMIT is reached in which case t_from_range stops using the individual values and type becomes fun(1..255) -> pos_integer(). The next iteration expands 1..255 to pos_integer() and then fun(pos_integer()) -> pos_integer() is a fixpoint!
Incorrect answer follows (explains the first comment below):
You should get a warning for this code if you use the -Woverspecs option. This option is not enabled by default, since Dialyzer operates under the assumption that it is 'ok' to over-approximate the return values of a function. In your particular case, however, you actually want any extra values to produce warnings.

Why F# compiler gets into twist with seq{0L..-5L..-10L}?

I'm having a bit of trouble declaring a descending sequence of int64.
What I want is this:
seq{0L..-5L..-10L};;
However, I get an error:
seq{0L..-5L..-10L};;
---^^^^^^^^^^^^^^^
stdin(5,4): error FS0739: Invalid object, sequence or record expression
Interestingly, it works with plain int:
> seq{0..-5..-10};;
val it : seq<int> = seq [0; -5; -10]
Even more interestingly, if I put spaces between .., it starts working with int64 too:
> seq{0L .. -5L .. -10L};;
val it : seq<int64> = seq [0L; -5L; -10L]
Can someone explain why the compiler gets into the twist with seq{0L..-5L..-10L}?
I agree that this is a bit odd behavior. It is generally recommended (although this is not strictly required by the specification) to write spaces around .. and it works correctly in that case. So I'd recommend using:
seq { 0 .. -5 .. -10 }
seq { 0L .. -5L .. -10L }
Why is this behaving differently for int and int64? You may notice that when you write 1..-2 and 1L..-2, Visual Studio colorizes the text differently (in the first case .. has the same color as numbers, in the other case, it has the same color as .. with spaces).
The problem is that when the compiler sees 1., it may mean a floating point value (1.0) or it may be a start of 1.., so this case is handled specially. For 1L., this is not a problem - 1L. has to be the beginning of 1L...
So, if you write 1..-5..-10, the compiler uses the special handling and generates a sequence. If you write 1L..-5..-10, then the compiler parses ..- as a unary operator that is applied to 5L. Writing the spaces resolves the ambiguity between unary operator and .. followed by a negative number.
For reference, here is a screenshot from my Visual Studio (which shows 10.. in green, but .. on the second line in yellow - not particularly noticeable difference, but they are different :-))

Resources