Type of union of disjunct functions? - type-theory

Given two functions:
f :: EvenInteger -> {0}
g :: OddInteger -> {1}
consider the function
h = (x :: Integer) => {
if(x is even)return f(x);
return g(x);
}
What the smallest type T such that
h :: T
I was thinking that it is simply
h :: (typeof f) & (typeof g)
But then I would also think that a function call distributes over conjunction i.e., that
x :: EvenInteger
h(x) :: (typeof f(x)) & (typeof g(x))
which begs another question:
What is
(OddInteger -> {1})(EvenInteger)

Related

How to simplify and extend verified algorithm?

I implemented and verified a quicksort function based on the implementation here on page 22.
It verifies (hurray!) but I'm not too happy with the proof, quicksortSorted, that the quicksort function is sorted for a couple reasons that lead to the following questions.
For whatever reason it seems like the proof will not verify because of the two recursive calls needed by the lemma. I got around this by setting the quicksort function to opaque and using another helping lemma quicksortDef when I needed to assert something about its definition. I feel like making the function opaque shouldn't be required. Is there another way to call the recursive subcases that doesn't explode? (better inductive setup?)
Following from above I saw the {:fuel} attribute exists, can it be used to improve this situation?
Although I was able to verify the lemma that quicksort ensures the result is sorted. It would be nice if that fact was part of the ensure conditions of the quicksort function, but my attempts to add it there always seemed to trigger endless recursion. Is there a better way to define quicksort or to prove it which allows this?
When I tried to set filter and quicksort to be function methods I got an error about filters parameter being a ghost variable. Why is a generic predicate function parameter a ghost variable?
Finally the quicksortSorted lemma feels a bit over-complicated, any suggestion on how to simplify it?
Whole implementation on github:
function {:opaque} quicksort(xs: seq<int>): seq<int>
// ensures sortedRec(quicksort(xs))
ensures multiset(xs) == multiset(quicksort(xs))
ensures xs == [] ==> quicksort(xs) == []
ensures xs == [] ==> quicksort(xs) == []
decreases multiset(xs)
{
if xs == [] then [] else
assert xs == [xs[0]] + xs[1..];
filterPreservesMultiset(xs);
// var ln := y => y < xs[0];
// var gn := y => y >= xs[0];
var ln := lessThanFirst(xs);
var gn := greaterOrEqualFirst(xs);
filterMultiSetSlice(xs, xs[1..], ln);
filterMultiSetSlice(xs, xs[1..], gn);
quicksort(filter(xs[1..], ln)) + [xs[0]] + quicksort(filter(xs[1..], gn))
}
lemma quicksortDef(xs: seq<int>)
requires |xs| > 0
ensures quicksort(xs) == quicksort(filter(xs[1..], lessThanFirst(xs))) + [xs[0]] + quicksort(filter(xs[1..], greaterOrEqualFirst(xs)))
{
reveal quicksort();
}
lemma quicksortSorted(xs: seq<int>)
ensures sortedRec(quicksort(xs))
decreases multiset(xs)
{
if xs == [] {
assert quicksort(xs) == [];
assert sortedRec(quicksort(xs));
}else{
assert xs == [xs[0]] + xs[1..];
var ln := lessThanFirst(xs);
var gn := greaterOrEqualFirst(xs);
if xs[1..] == [] {
assert xs == [xs[0]];
assert sortedRec([xs[0]]);
}else{
// filterPreservesMultiset(xs[1..]);
filterMultiSetSlice(xs, xs[1..], ln);
filterMultiSetSlice(xs, xs[1..], gn);
var lessThan := filter(xs[1..], ln);
var greaterThan := filter(xs[1..], gn);
var sortedLt := quicksort(lessThan);
var sortedGt := quicksort(greaterThan);
// assert multiset(lessThan) == multiset(sortedLt);
assert multiset(greaterThan) == multiset(sortedGt);
assert forall y :: y in multiset(sortedGt) ==> y in multiset(greaterThan) && y in sortedGt && y in greaterThan;
assert listPartition(lessThan, [xs[0]]);
quicksortPreservesRelations(lessThan, [xs[0]]);
assert listPartition(sortedLt, [xs[0]]);
assert forall x :: x in sortedLt ==> forall y :: y in [xs[0]] ==> x < y ==> x < xs[0];
forall x | x in sortedLt + [xs[0]]
ensures forall y :: y in sortedGt ==> x <= y
{
forall y | y in sortedGt
ensures x <= y
{
assert y in greaterThan;
assert y >= xs[0];
if x in sortedLt {
assert forall z :: z in [xs[0]] ==> x < z ==> x < xs[0];
}else if x in [xs[0]] {
assert x == xs[0];
assert y >= xs[0];
}
}
}
quicksortSorted(lessThan);
quicksortSorted(greaterThan);
assert listPartition(sortedLt + [xs[0]], sortedGt);
// assert sortedRec(sortedLt);
// assert sortedRec(sortedGt);
sortedConcat(sortedLt, [xs[0]]);
assert sortedRec(sortedLt+[xs[0]]);
sortedConcat(sortedLt + [xs[0]], sortedGt);
assert sortedRec((sortedLt + [xs[0]]) + sortedGt);
quicksortDef(xs);
assert quicksort(xs) == sortedLt + [xs[0]] + sortedGt;
assert sortedRec(quicksort(xs));
}
}
}
predicate listPartition(xs: seq<int>, ys: seq<int>)
{
forall x :: x in xs ==> forall y :: y in ys ==> x <= y
}
predicate sortedRec(list: seq<int>) {
if list == [] then true else (forall y :: y in list[1..] ==> list[0] <= y) && sortedRec(list[1..])
}
lemma sortedConcat(xs: seq<int>, ys: seq<int>)
requires sortedRec(xs)
requires sortedRec(ys)
requires listPartition(xs,ys)
ensures sortedRec(xs + ys)
{
if xs == [] || ys == [] {
if xs == [] {
assert xs + ys == ys;
assert sortedRec(xs + ys);
} else if ys == [] {
assert xs + ys == xs;
assert sortedRec(xs+ys);
}
}else{
assert sortedRec([xs[0]]);
assert sortedRec([ys[0]]);
var sum := xs + ys;
assert xs == [xs[0]] + xs[1..];
assert ys == [ys[0]] + ys[1..];
assert xs[0] in xs;
assert forall y :: y in ys ==> xs[0] <= y;
assert forall xz :: xz in xs[1..] ==> xz in xs && forall y :: y in ys ==> xz <= y;
sortedConcat(xs[1..], ys);
assert xs+ys == [xs[0]] + (xs[1..]+ys);
assert sortedRec(xs + ys );
}
}

API for handling polymothinc records

It is a little bit custom issue, is not contrived, but just simplified as possible.
-- this record that has fn that handles both x and y,
-- x and y supposed to be Functors, a arbitrary param for x/y, r is arbitrary result param
type R0 a x y r =
{ fn :: x a -> y a -> r
}
-- this record that has fn that handles only x
type R1 a x r =
{ fn :: x a -> r
}
What I want is a common API (function) that could handle values of R0 and R1 types.
So I do a sum type
data T a x y r
= T0 (R0 a x y r)
| T1 (R1 a x r)
And I declare this function, there is a constraint that x and y have to be Functors.
some :: ∀ a x y r.
Functor x =>
Functor y =>
T a x y r -> a
some = unsafeCoerce -- just stub
Then try to use it.
data X a = X { x :: a}
data Y a = Y { y :: a }
-- make X type functor
instance functorX :: Functor X where
map fn (X val) = X { x: fn val.x }
-- make Y type functor
instance functorY :: Functor Y where
map fn (Y val) = Y { y: fn val.y }
-- declare functions
fn0 :: ∀ a. X a -> Y a -> Unit
fn0 = unsafeCoerce
fn1 :: ∀ a. X a -> Unit
fn1 = unsafeCoerce
Trying to apply some:
someRes0 = some $ T0 { fn: fn0 } -- works
someRes1 = some $ T1 { fn: fn1 } -- error becase it can not infer Y which should be functor but is not present in f1.
So the question is: Is it possible to make such API work somehow in a sensible/ergonomic way (that would not require some addition type annotations from a user of this API)?
I could apparently implement different functions some0 and some1 for handling both cases, but I wonder if the way with a single function (which makes API surface simpler) is possilbe.
And what would be other suggestions for implementing such requirements(good API handling such polymorphic record types that differ in a way described above, when one of the records has exessive params)?
You should make T1 and T0 separate types and then make function some itself overloaded to work with them both:
data T0 x y r a = T0 (R0 a x y r)
data T1 x r a = T1 (R1 a x r)
class Some t where
some :: forall a. t a -> a
instance someT0 :: (Functor x, Functor y) => Some (T0 x y r) where
some = unsafeCoerce
instance someT1 :: Functor x => Some (T1 x r) where
some = unsafeCoerce
An alternative, though much less elegant, solution would be to have the caller of some explicitly specify the y type with a type signature. This is the default approach in situations when a type can't be inferred by the compiler:
someRes1 :: forall a. a
someRes1 = some (T1 { fn: fn1 } :: T a X Y Unit)
Note that I had to add a type signature for someRes1 in order to have the type variable a in scope. Otherwise I couldn't use it in the type signature T a X Y Unit.
An even more alternative way to specify y would be to introduce a dummy parameter of type FProxy:
some :: ∀ a x y r.
Functor x =>
Functor y =>
FProxy y -> T a x y r -> a
some _ = unsafeCoerce
someRes0 = some FProxy $ T0 { fn: fn0 }
someRes1 = some (FProxy :: FProxy Maybe) $ T1 { fn: fn1 }
This way you don't have to spell out all parameters of T.
I provided the latter two solutions just for context, but I believe the first one is what you're looking for, based on your description of the problem mentioning "polymorphic methods". This is what type classes are for: they introduce ad-hoc polymorphism.
And speaking of "methods": based on this word, I'm guessing those fn functions are coming from some JavaScript library, right? If that's the case, I believe you're doing it wrong. It's bad practice to leak PureScript-land types into JS code. First of all JS code might accidentally corrupt them (e.g. by mutating), and second, PureScript compiler might change internal representations of those types from version to version, which will break your bindings.
A better way is to always specify FFI bindings in terms of primitives (or in terms of types specifically intended for FFI interactions, such as the FnX family), and then have a layer of PureScript functions that transform PureScript-typed parameters to those primitives and pass them to the FFI functions.

let val declarations in SML NJ

I'm having a mental roadblock in understanding how this works and hoping I can get some guidance. The function f below will sort a list of ints (f [1,2,3]). The part I'm stuck on is the val declaration and what is occurring in recursion. I know the val declaration will allow me to compare the second value in the list to the first but I'm getting confused with the list concatenation. It seems like the function would just compare the first two values and then tack on the rest of the list (ie x :: y :: ys). I'm not sure how f ls is actually working. Is it that...
1) The first two values are compared and added to the list
2) then f ls is recursively called?
Seems like that is the case but then I'm confused about the "ys" - seems like the end of the list is tacked on with each call. I know the sort works but not sure how it's actually working.
fun f ([x]) = [x]
| f(x :: ls) =
let
val (y :: ys) = f ls
in
if y > x then x :: y :: ys
else
y :: x :: ys
end
EDIT - Thought about this some more, is it that y::ys within in the in / end body is actually what is being called recursively? If so, SML is smart enough to know that it should use x::ys in y::ys place if it hits else?
First and foremost, the sort doesn't work when the list is very random, e.g. f [2,3,4,1,2,4,6,0,6,7]
Secondly, to answer your question as to how this particular function works,
you can visualize it easily with following print additions to your code:
fun f ([x]) = [x]
| f(x :: ls) = (print( (Int.toString (x)) ^ "\n");
let
val (y :: ys) = f ls
val x_str = Int.toString (x)
val y_str = Int.toString (y)
val ys_str = concat (map Int.toString ys);
val y_gt_x = if y > x then " ---> this one applies " else ""
val x_gt_y = if x >= y then " ---> this one applies " else ""
in
(print ("if " ^ y_str ^ " > " ^ x_str ^
"\n then " ^ x_str ^ " :: " ^ y_str ^ ys_str ^ y_gt_x ^
"\n else " ^ y_str ^ " :: " ^ x_str ^ ys_str ^ x_gt_y ^ "\n");
if y > x then x :: y :: ys
else
y :: x :: ys)
end)
which for the above random list outputs the following:
- f [2,3,4,1,2,4,6,0,6,7];
2
3
4
1
2
4
6
0
6
if 7 > 6
then 6 :: 7 ---> this one applies
else 7 :: 6
if 6 > 0
then 0 :: 67 ---> this one applies
else 6 :: 07
if 0 > 6
then 6 :: 067
else 0 :: 667 ---> this one applies
if 0 > 4
then 4 :: 0667
else 0 :: 4667 ---> this one applies
if 0 > 2
then 2 :: 04667
else 0 :: 24667 ---> this one applies
if 0 > 1
then 1 :: 024667
else 0 :: 124667 ---> this one applies
if 0 > 4
then 4 :: 0124667
else 0 :: 4124667 ---> this one applies
if 0 > 3
then 3 :: 04124667
else 0 :: 34124667 ---> this one applies
if 0 > 2
then 2 :: 034124667
else 0 :: 234124667 ---> this one applies
val it = [0,2,3,4,1,2,4,6,6,7] : int list
-
As you can see, the function f recursively calls itself in the let binding section. (check the code:
let
val (y :: ys) = f ls
as you can see, f ls is the recursive call of the function f, so your analysis of y :: ys being the recursive call within the in body is incorrect as that is merely an operation of prepending the element y to the list ys)
The in body does not get evaluated except all the way at the end of the list. So the in body will first evaluate the last two elements of the list, e.g. 7 > 6 and grow the list ys accordingly.
Thirdly, to answer point number one as to why the sort function f doesn't work properly is because it keeps on adding new elements to ys without seeing if the new elements are placed in order in ys with respect to the remainder elements. Yes, the first element of the list ys gets compared with the new element to be prepended and accordingly the biggest of the two will get prepended first to the remainder of ys, but that doesn't guarantee the correct placement with regards to the second and third and so on element of ys.

Implementing map for an intensionally-defined set in Scala

type Set = Int => Boolean
/**
* Returns whether all bounded integers within `s` satisfy `p`.
*/
def forall(s: Set, p: Int => Boolean): Boolean = {
def iter(a: Int): Boolean = {
if (a > bound) true
else if (contains(s, a) && !p(a)) false
else iter(a + 1)
}
iter(-bound)
}
/**
* Returns whether there exists a bounded integer within `s`
* that satisfies `p`.
*/
def exists(s: Set, p: Int => Boolean): Boolean = !forall(s, (x => !p(x)))
/**
* Returns a set transformed by applying `f` to each element of `s`.
*/
def map(s: Set, f: Int => Int): Set = (x => exists(s, (y: Int) => f(y) ==
x))
so for this piece of code. I don't understand function map.
I see its input are 2 arguments, which are set and method f. But the "body" part, I tried so hard but still don't get it. And what is that "y", and why using f(y) == x makes it apply method f to set elemtns?
need some explanation for me.
thank you!
To be succinct:
If you say: val set2 = map(set1, f),
then set2(x) will returns true if and only if there exits y in set1 such as f(y) == x
That's exactly what exists(set1, y => f(y) == x) is checking.
To put it an other way, an integer is in set2 only if you can obtain it by applying f to an element of set1.
We can try to understand this piece of code by applying it backwards.
The map method here would return true for every given x and function f, if x is a result of the function f applied to the elements of the original set.
It is done by checking that if we go over the original map and apply f to every element of this map, at least one of them will be equal to x (that is what the part (x => exists(s, (y: Int) => f(y) == x)) does).
Regarding exists itself, it is a statement that if we go over all elements of the set (using forall method) with a given predicate p, for at least one of the elements this predicate will not be false (this is the part !forall(s, (x => !p(x)))).
And what is that "y"
exists takes a function Int => Boolean as its second argument. This function is (y: Int) => f(y) == x, and y is simply the name we give to its argument, same as x in x => !p(x).
and why using f(y) == x makes it apply method f to set elemtns?
This definition says "x is a member of map(s, f) when exists(s, y => f(y) == x). Now consider a simple case: s is the set {1, 2} represented by a function x => (x == 1) || (x == 2), and f = z => z + 1 over it. Then we have
s2 = map(s, z => z + 1) = x => exists(s, y => y + 1 == x)
by inlining f into definition of map. You can check that:
2 is a member of s2, i.e. s2(2) is exists(s, y => y + 1 == 2) is exists(s, y => y == 1) is true.
0 is not a member of s2, i.e. s2(2) is exists(s, y => y + 1 == 0) is exists(s, y => y == -1) is false.
Thinking a bit more, you should be able to list all members of s2, and then to generalize to any s and f.

syntax explanation for pattern matching a list in scala

I was reading this blog post and i was not able to understand a part of the code.
object O {
def maximum(x: List[Int]): Int = x match {
case Nil => error("maximum undefined for empty list")
case x :: y :: ys => maximum((if(x > y) x else y) :: ys)
case x :: _ => x
}
}
Please explain the code maximum((if(x > y) x else y) :: ys)
How the if condition can be a part of the method maximum ?
I understand that if condition is not exactly a parameter.
In Scala, if is an expression, not a statement.
Try this in the REPL:
scala> val x=1; val y=0
x: Int = 1
y: Int = 0
scala> val test=if(x > y) x else y
test: Int = 1
if evaluates to 1 and 1 is assigned to test. In Java if could be expressed with the conditional operator (x > y) ? x : y
Now, you have a function called maximum that takes a List[Int] as a parameter.
maximum((if(x > y) x else y) :: ys) calls maximum (recursively) with a list obtained prepending one between x and y (depending on what the if evaluates to) to ys.