How to deal with this error? - error-handling

I'm dealing with very long lists, and large trees.
Sometimes I would find this error:
surgery a;;
Characters 8-9:
surgery a;;
^
Error: This expression has type int t/1044
but an expression was expected of type 'a t/1810
# type 'a t = | Leaf of ('a -> 'a -> int)
| Node of 'a * 'a t * 'a t * ('a -> 'a -> int)
I'm not sure about what type is that kind of error, but I guess it's some kind of an overflow. The type matches correctly but there are large numbers after the backslash that follows the type. In this case 1044 and 1810.
This time I have run some code before surgery a. If I kill the current top-level and start over, surgery a would run.
My questions are:
1. What is this error exactly?
2. When and how does it occur?
3. Why rerunning it from a new top-level would make it work?
4. How should I deal with it?

This is a type error, not a runtime error. It does not "cost" anything and is not in any way related to the size of the structures you have in memory.
It happens if you're not careful in the toplevel, and mix two different types with the same name. Compare:
type t = int;;
let f (x : t) = ();;
type u = bool;;
let g (y : u) = f y;;
^
Error: This expression has type u = bool
but an expression was expected of type t = int
with
type t = int;;
let f (x : t) = ();;
type t = bool;;
let g (y : t) = f y;;
^
Error: This expression has type t/1047 = bool
but an expression was expected of type t/1044 = int
This is the exact same typing error happening in both cases: you mixed different types. But in the second case, both have the same name t. The type-system tries to be helpful and tells you about the unique integers it internally assign to names, to make sure there are really unique throughout the program.
This kind of error cannot happen outside the toplevel (when compiling a program the usual way), as it is not possible to define two types with the same name at the exact same path.
How to fix it: if you redefine a type with a new definition that is not equivalent to the previous one, you must be careful to also redefine the operations on this previous type previously recorded in the toplevel. Indeed, they are still typed as expecting the old type, and using them with the new type will result in such errors.

Related

Where is the Idris == operator useful?

As a beginner in type-driven programming, I'm curious about the use of the == operator. Examples demonstrate that it's not sufficient to prove equality between two values of a certain type, and special equality checking types are introduced for the particular data types. In that case, where is == useful at all?
(==) (as the single constituent function of the Eq interface) is a function from a type T to Bool, and is good for equational reasoning. Whereas x = y (where x : T and y : T) AKA "intensional equality" is itself a type and therefore a proposition. You can and often will want to bounce back and forth between the two different ways of expressing equality for a particular type.
x == y = True is also a proposition, and is often an intermediate step between reasoning about (==) and reasoning about =.
The exact relationship between the two types of equality is rather complex, and you can read https://github.com/pdorrell/learning-idris/blob/9d3454a77f6e21cd476bd17c0bfd2a8a41f382b7/finished/EqFromEquality.idr for my own attempt to understand some aspects of it. (One thing to note is that even though an inductively defined type will have decideable intensional equality, you still have to go through a few hoops to prove that, and a few more hoops to define a corresponding implementation of Eq.)
One particular handy code snippet is this:
-- for rel x y, provide both the computed value, and the proposition that it is equal to the value (as a dependent pair)
has_value_dpair : (rel : t -> t -> Bool) -> (x : t) -> (y : t) -> (value: Bool ** rel x y = value)
has_value_dpair rel x y = (rel x y ** Refl)
You can use it with the with construct when you have a value returned from rel x y and you want to reason about the proposition rel x y = True or rel x y = False (and rel is some function that might represent a notion of equality between x and y).
(In this answer I assume the case where (==) corresponds to =, but you are entirely free to define a (==) function that doesn't correspond to =, eg when defining a Setoid. So that's another reason to use (==) instead of =.)
You still need good old equality because sometimes you can't prove things. Sometimes you don't even need to prove. Consider next example:
countEquals : Eq a => a -> List a -> Nat
countEquals x = length . filter (== x)
You might want to just count number of equal elements to show some statistics to user. Another example: tests. Yes, even with strong type system and dependent types you might want to perform good old unit tests. So you want to check for expectations and this is rather convenient to do with (==) operator.
I'm not going to write full list of cases where you might need (==). Equality operator is not enough for proving but you don't always need proofs.

Perl 6 reports "Cannot unbox a type object" when typing an array

I suspect this may be a bug in Rakudo, but I just started playing with Perl 6 today, so there's a good chance I'm just making a mistake. In this simple program, declaring a typed array inside a sub appears to make the Perl 6 compiler angry. Removing the type annotation on the array gets rid of the compiler error.
Here's a simple prime number finding program:
#!/usr/bin/env perl6
use v6;
sub primes(int $max) {
my int #vals = ^$max; # forcing a type on vals causes compiler error (bug?)
for 2..floor(sqrt($max)) -> $i {
next if not #vals[$i];
#vals[2*$i, 3*$i ... $max-1] = 0;
}
return ($_ if .Bool for #vals)[1..*];
}
say primes(1000);
On Rakudo Star 2016.07.1 (from the Fedora 24 repos), this program gives the following error:
[sultan#localhost p6test]$ perl6 primes.p6
Cannot unbox a type object
in sub primes at primes.p6 line 8
in block <unit> at primes.p6 line 13
If I remove the type annotation on the vals array, the program works correctly:
...
my #vals = ^$max; # I removed the int type
...
Am I making a mistake in my usage of Perl 6, or is this a bug in Rakudo?
There's a potential error in your code that's caught by type checking
The error message you got draws attention to line 8:
#vals[2*$i, 3*$i ... $max-1] = 0;
This line assigns the list of values on the right of the = to the list of elements on the left.
The first element in the list on the left, #vals[2*$i], gets a zero.
You didn't define any more values on the right so the rest of the elements on the left are assigned a Mu. Mus work nicely as placeholders for elements that do not have a specific type and do not have a specific value. Think of a Mu as being, among other things, like a Null, except that it's type safe.
You get the same scenario with this golfed version:
my #vals;
#vals[0,1] = 0; # assigns 0 to #vals[0], Mu to #vals[1]
As you've seen, everything works fine when you do not specify an explicit type constraint for the elements of the #vals array.
This is because the default type constraint for array elements is Mu. So assigning a Mu to an element is fine.
If you felt it tightened up your code you could explicitly assign zeroes:
#vals[2*$i, 3*$i ... $max-1] = 0 xx Inf;
This generates a (lazy) infinite list of zeroes on the RHS so that zero is assigned to each of the list of elements on the LHS.
With just this change your code will work even if you specify a type constraint for #vals.
If you don't introduce the xx Inf but do specify an element type constraint for #vals that isn't Mu, then your code will fail a type check if you attempt to assign a Mu to an element of #vals.
The type check failure will come in one of two flavors depending on whether you're using object types or native types.
If you specify an object type constraint (eg Int):
my Int #vals;
#vals[0,1] = 0;
then you get an error something like this:
Type check failed in assignment to #vals; expected Int but got Mu (Mu)
If you specify a native type constraint (eg int rather than Int):
my int #vals;
#vals[0,1] = 0;
then the compiler first tries to produce a suitable native value from the object value (this is called "unboxing") before attempting a type check. But there is no suitable native value corresponding to the object value (Mu). So the compiler complains that it can not even unbox the value. Finally, as hinted at at the start, while Mu works great as a type safe Null, that's just one facet of Mu. Another is that it's a "type object". So the error message is Cannot unbox a type object.

Example of a `Type 1` that is neither `Type` nor an inhabitant of `Type`

What is an example of an inhabitant of Type 1 that is neither Type nor an inhabitant of Type? I wasn't able to come up with anything while exploring in the Idris REPL.
To be more precise, I'm looking for some x other than Type that yields the following:
Idris> :t x
x : Type 1
I'm not a type theory specialist, but here is my understanding. In the Idris tutorial there is a section 12.8 Cumulativity. It says that there is an internal hierarchy of type universes:
Type : Type 1 : Type 2 : Type 3 : ...
And for any x : Type n implies x : Type m for any m > n. There is also an example demonstrating how it prevents possible cycles in the type inference.
But I think that this hierarchy is only for internal use and there is no possibility to create a value of Type (n+1) which is not in Type n.
See also articles in nLab about universes in type theory and about type of types.
Maybe this issue in the idris-dev repository can be useful too. Edwin Brady refers there to the Design and Implementation paper (see section 3.2.2).
I'm not an Idris expert, but I'd expect that
Type -> Type
is also in Type 1.
I'd also expect
Nat -> Type
and if you're very lucky (not so sure about this one)
List Type
to be that large.
The idea is that you can do all type-building operations at every level. Each time you use types from one level as values, the types of those structures live one level up.

Test.QuickCheck: speed up testing multiple properties for the same type

I am testing a random generator generating instances of my own type. For that I have a custom instance of Arbitrary:
complexGenerator :: (RandomGen g) => g -> (MyType, g)
instance Arbitrary MyType where
arbitrary = liftM (fst . complexGenerator . mkStdGen) arbitrary
This works well with Test.QuickCheck (actually, Test.Framework) for testing that the generated values hold certain properties. However, there are quite a few properties I want to check, and the more I add, the more time it takes to verify them all.
Is there a way to use the same generated values for testing every property, instead of generating them anew each time? I obviously still want to see, on failures, which property did not hold, so making one giant property with and is not optimal.
I obviously still want to see, on failures, which property did not hold, so making one giant property with and is not optimal.
You could label each property using printTestCase before making a giant property with conjoin.
e.g. you were thinking this would be a bad idea:
prop_giant :: MyType -> Bool
prop_giant x = and [prop_one x, prop_two x, prop_three x]
this would be as efficient yet give you better output:
prop_giant :: MyType -> Property
prop_giant x = conjoin [printTestCase "one" $ prop_one x,
printTestCase "two" $ prop_two x,
printTestCase "three" $ prop_three x]
(Having said that, I've never used this method myself and am only assuming it will work; conjoin is probably marked as experimental in the documentation for a reason.)
In combination with the voted answer, what I've found helpful is using a Reader transformer with the Writer monad:
type Predicate r = ReaderT r (Writer String) Bool
The Reader "shared environment" is the tested input in this case. Then you can compose properties like this:
inv_even :: Predicate Int
inv_even = do
lift . tell $ "this is the even invariant"
(==) 0 . flip mod 2 <$> ask
toLabeledProp :: r -> Predicate r -> Property
toLabeledProp cause r =
let (effect, msg) = runWriter . (runReaderT r) $ cause in
printTestCase ("inv: " ++ msg) . property $ effect
and combining:
fromPredicates :: [Predicate r] -> r -> Property
fromPredicates predicates cause =
conjoin . map (toLabeledProp cause) $ predicates
I suspect there is another approach involving something similar to Either or a WriterT here- which would concisely compose predicates on different types into one result. But at the least, this allows for documenting properties which impose different post-conditions dependent on the the value of the input.
Edit: This idea spawned a library:
http://github.com/jfeltz/quickcheck-property-comb

First and follow of the non-terminals in two grammars

Given the following grammar:
S -> L=L
s -> L
L -> *L
L -> id
What are the first and follow for the non-terminals?
If the grammar is changed into:
S -> L=R
S -> R
L -> *R
L -> id
R -> L
What will be the first and follow ?
When I took a compiler course in college I didn't understand FIRST and FOLLOWS at all. I implemented the algorithms described in the Dragon book, but I had no clue what was going on. I think I do now.
I assume you have some book that gives a formal definition of these two sets, and the book is completely incomprehensible. I'll try to give an informal description of them, and hopefully that will help you make sense of what's in your book.
The FIRST set is the set of terminals you could possibly see as the first part of the expansion of a non-terminal. The FOLLOWS set is the set of terminals you could possibly see following the expansion of a non-terminal.
In your first grammar, there are only three kinds of terminals: =, *, and id. (You might also consider $, the end-of-input symbol, to be a terminal.) The only non-terminals are S (a statement) and L (an Lvalue -- a "thing" you can assign to).
Think of FIRST(S) as the set of non-terminals that could possibly start a statement. Intuitively, you know you do not start a statement with =. So you wouldn't expect that to show up in FIRST(S).
So how does a statement start? There are two production rules that define what an S looks like, and they both start with L. So to figure out what's in FIRST(S), you really have to look at what's in FIRST(L). There are two production rules that define what an Lvalue looks like: it either starts with a * or with an id. So FIRST(S) = FIRST(L) = { *, id }.
FOLLOWS(S) is easy. Nothing follows S because it is the start symbol. So the only thing in FOLLOWS(S) is $, the end-of-input symbol.
FOLLOWS(L) is a little trickier. You have to look at every production rule where L appears, and see what comes after it. In the first rule, you see that = may follow L. So = is in FOLLOWS(L). But you also notice in that rule that there is another L at the end of the production rule. So another thing that could follow L is anything that could follow that production. We already figured out that the only thing that can follow the S production is the end-of-input. So FOLLOWS(L) = { =, $ }. (If you look at the other production rules, L always appears at the end of them, so you just get $ from those.)
Take a look at this Easy Explanation, and for now ignore all the stuff about ϵ, because you don't have any productions which contain the empty-string. Under "Rules for First Sets", rules #1, #3, and #4.1 should make sense. Under "Rules for Follows Sets", rules #1, #2, and #3 should make sense.
Things get more complicated when you have ϵ in your production rules. Suppose you have something like this:
D -> S C T id = V // Declaration is [Static] [Const] Type id = Value
S -> static | ϵ // The 'static' keyword is optional
C -> const | ϵ // The 'const' keyword is optional
T -> int | float // The Type is mandatory and is either 'int' or 'float'
V -> ... // The Value gets complicated, not important here.
Now if you want to compute FIRST(D) you can't just look at FIRST(S), because S may be "empty". You know intuitively that FIRST(D) is { static, const, int, float }. That intuition is codified in rule #4.2. Think of SCT in this example as Y1Y2Y3 in the "Easy Explanation" rules.
If you want to compute FOLLOWS(S), you can't just look at FIRST(C), because that may be empty, so you also have to look at FIRST(T). So FOLLOWS(S) = { const, int, float }. You get that by applying "Rules for follow sets" #2 and #4 (more or less).
I hope that helps and that you can figure out FIRST and FOLLOWS for the second grammar on your own.
If it helps, R represents an Rvalue -- a "thing" you can't assign to, such as a constant or a literal. An Lvalue can also act as an Rvalue (but not the other way around).
a = 2; // a is an lvalue, 2 is an rvalue
a = b; // a is an lvalue, b is an lvalue, but in this context it's an rvalue
2 = a; // invalid because 2 cannot be an lvalue
2 = 3; // invalid, same reason.
*4 = b; // Valid! You would almost never write code like this, but it is
// grammatically correct: dereferencing an Rvalue gives you an Lvalue.