In appendix B: Alloy Language Reference of Software Abstractions it is stated that
all x: X, y: Y | F
is short for
all x: X | all y: Y | F
but
one x: X, y: Y | F
is not short for
one x: X | one y: Y | F
I can't quite see clearly what is going on here and it occurs to me i am perhaps not reading this correctly at all..
my attempt would be "this is true if there is one instance, comprised of one x from X and one y from Y for which F is true".
Intuitively, one x: X, y: Y | F means "there is exactly one pair (x,y) in XxY s.t. F", while one x: X | one y: Y | F means "there is exactly one x in X s.t: there is exactly one y in Y s.t. F". In the latter case, the unique y s.t. F may depend on the given x.
To see what happens formally, you could translate one in terms of all and some; and then recast your example this way.
Related
I want to sort the first three elements of a list, yet keep the other elements untouched. And I don't want to use any library functions because I am new to Haskell.
This is what I have so far:
{-# OPTIONS_GHC -Wincomplete-patterns #-}
sort2 (x, y) = if x > y then (y,x) else (x,y)
sort3 (x,y,z)
| x > y && y > z = (z,y,x)
| x > z && z > y = (y,z,x)
| y > x && x > z = (z,x,y)
| y > z && z > x = (x,z,y)
| z > x && x > y = (y,x,z)
| z > y && y > x = (x,y,z)
| otherwise = (0,0,0)
--sortfirst3 :: [Int] -> [Int]
sortfirst3 (x:y:z:v:xs) = sort3(x,y,z) : sortfirst3 (v:xs)
I'm trying to sort the first three elements, put them in a list, and then put the other elements in another list and then concatenate them with each other. However, this generates an error because of the type difference a tuple and a list. Is there another way I should be doing this?
You don't need to involve tuples. You can write what you wrote for tuples as patterns to match instead.
sortFirst3 [x, y] = if x > y then [y, x] else [x, y]
sortFirst3 [x, y, z]
| x >= y && y >= z = [z, y, x]
| x >= z && z >= y = [y, z, x]
| y >= x && x >= z = [z, x, y]
| y >= z && z >= x = [x, z, y]
| z >= x && x >= y = [y, x, z]
| z >= y && y >= x = [x, y, z]
sortFirst3 (x : y : z : ws) = sortFirst3 [x, y, z] ++ ws
sortFirst3 xs = xs
The last line catches what has not been matched, which are the singletons and empty lists, which remain the same when sorted. You should not have strict inequalities in your guards since elements may repeat. Also note that, in your code, even if you didn't have the type mismatch, the recursive call to sortFirst3 would be erroneous, since after sorting the first three terms, the first three of the rest would be sorted, and so on.
sortfirst3 (x:y:z:v:xs) = sort3(x,y,z) : sortfirst3 (v:xs)
This definition says, take the first 4 elements off the list, sort the first 3 into a tuple, then cons it onto the (recursive) result on the fourth element of the list with the rest of the list.
This reveals three changes to be made.
First, we only need to match the first 3 elements, not the first 4, but we should also probably deal with cases for when the list is <3 elements long. I've just made it an error, but you can use eg. sort2 instead.
sortfirst3 (x:y:z:xs) = sort3 (x,y,z) : sortfirst3 xs
sortfirst3 _ = error "Can't sort first 3 elements of list shorter than 3 elements"
Second, we intend to sort the first 3 elements ie. resulting in a 3 element list. (:) :: a -> [a] -> [a] ie. takes an element (not a list) in the first argument, what we want instead is concatentation (++) :: [a] -> [a] -> [a].
sortfirst3 (x:y:z:xs) = sort3 (x,y,z) ++ sortfirst3 xs
Third, we intend to leave the elements after the first 3 untouched, so we shouldn't actually make a recursive call on the rest of the list - otherwise we'll instead be sorting the list in 3 element chunks.
sortfirst3 (x:y:z:xs) = sort3 (x,y,z) ++ xs
This is now almost correct, but for sort3, which as you identified incorrectly returns a tuple rather than a 3-element list. kuoytfouy's answer helps with that.
All:
How can I write the following in the "Curry" syntax:
let y = 2 in
let f x = x + y in
let f x = let y = 3 in f y in
f 5
I at first tried something like this:
(y -> (f -> ((f x -> f 5) (y -> f y) 3)) x + y) 2
However this does not seem evaluate properly.
Even better yet would be a Lambda-expression to see binding.
Thanks!
let v = e1 in e2 translates to lambda calculus as (\v.e2)(e1) (where I use the backslash to denote a lambda). So, your example would be
(\y1.(\f1.(\f2.f2 5)(\x2.(\y2.f1(y2))(3)))(\x1.x1+y1))(2)
I used alpha conversion to differentiate between variables that otherwise would have the same name. Observe that the f in the middle has become f1, that is the f in f y in the third line of your example uses the f defined in the second line, not the one which is about to be defined in the third line. In other words, your definition is not recursive; you have used let, not let rec.
Digression: Translating let rec into the lambda calculus requires a fixed point combinator Y (or some like technique). Y is characterized by the property that Y(f) reduces to f(Y(f)). Then, let rec v = e1 in e2 roughly translates to (\v.e2)(Y(\v.e1)).
f x zero = Nothing
f x y = Just $ x / y
where zero = 0
The literal-bound identifier zero simply matches all after the warning Pattern match(es) are overlapped.
That's how Haskell's syntax works; every lowercase-initial variable name in a pattern (re)binds that name. Any existing binding will be shadowed.
But even if that weren't the case, the binding for zero would not be visible to the first alternative, because of how Haskell's syntax works. A similar thing happens in the following version:
f = \v1 v2 -> case (v1, v2) of
(x, zero) -> Nothing
(x, y) -> Just $ x / y
where zero = 0
The where clause only applies to the one alternative that it's part of, not to the whole list of alternatives. That code is pretty much the same thing as
f = \v1 v2 -> case (v1, v2) of
(x, zero) -> Nothing
(x, y) -> let zero = 0 in Just $ x / y
If bound identifiers had different semantics than unbound identifiers in a pattern match, that could be quite error prone as binding a new identifier could mess up pattern matches anywhere that identifier is in scope.
For example let's say you're importing some module Foo (unqualified). And now the module Foo is changed to add the binding x = 42 for some reason. Now in your pattern match you'd suddenly be comparing the first argument against 42 rather than binding it to x. That's a pretty hard to find bug.
So to avoid this kind of scenario, identifier patterns have the same semantics regardless of whether they're already bound somewhere.
Because they are very fragile. What does this compute?
f x y z = 2*x + 3*y + z
Would you expect this to be equal to
f x 3 z = 2*x + 9 + z
f _ _ _ = error "non-exhaustive patterns!"
only because there's a y = 3 defined somewhere in the same 1000+ line module?
Also consider this:
import SomeLibrary
f x y z = 2*x + 3*y + z
What if in a future release SomeLibrary defines y? We don't want that to suddenly stop working.
Finally, what if there is no Eq instance for y?
y :: a -> a
y = id
f :: a -> (a -> a) -> a
f x y = y x
f x w = w (w x)
Sure, it is a contrived example, but there's no way the runtime can compare the input function to check whether it is equal to y or not.
To disambiguate this, some new languages like Swift uses two different syntaxes. E.g. (pseudo-code)
switch someValue {
case .a(x) : ... // compare by equality using the outer x
case .b(let x) : ... // redefine x as a new local variable, shadowing the outer one
}
zero is just a variable that occurs inside a pattern, just like y does in the second line. There is no difference between the two. When a variable that occurs inside a pattern, this introduces a new variable. If there was a binding for that variable already, the new variable shadows the old one.
So you cannot use an already bound variable inside a pattern. Instead, you should do something like that:
f x y | y == zero = Nothing
where zero = 0
f x y = Just $ x / y
Notice that I also moved the where clause to bring it in scope for the first line.
I am really confused over why there is always a counter example to my following assertion.
//assertions must NEVER by wrong
assert Symmetric{
all r: univ -> univ | some ~r iff (some x, y: univ | x not in y and y not in x and
(x->y in r) and (y->x in r))
}
check Symmetric
The counter-example always shows 1 element in univ set. However, this should not be the case since I specified that there will be some ~r iff x not in y and y not in x. The only element should not satisfy this statement.
Yet why does the model keep showing a counterexample to my assertion?
---INSTANCE---
integers={}
univ={Univ$0}
Int={}
seq/Int={}
String={}
none={}
this/Univ={Univ$0}
skolem $Symmetric_r={Univ$0->Univ$0}
Would really appreciate some guidance!
In Alloy, assertions are used to check the correctness of logic sentences (properties of your model), not to specify properties that should always hold in your model. So you didn't specify that
there will be some ~r iff x not in y and y not in x
you instead asked Alloy whether it is true that for all binary relations r, some ~r iff x not in y and y not in x [...], and Alloy answered that it is not true, and gave you a concrete example (counterexample) in which that property doesn't hold.
A couple other points
some ~r doesn't mean "r is symmetric"; it simply means that the transpose of r is non-empty, which is not the same. A binary relation is symmetric if it is equal to its transpose, so you can write r = ~r to express that;
instead of some x, y: univ | x not in y and y not in x and [...] you can equivalently write some disj x, y: univ | [...];
however, that some expression doesn't really express the symmetry property, because all it says is that "there are some x, y such that both x->y and y->x are in r"; instead, you want to say something like "for all x, y, if x->y is in r, then y->x is in r too".
I have a graph like this:
As part of a homework assignment I want to find the triangle (1->2->5). I have no idea how to find this.
In my case, I defined my graph:
type Graph = (Int, Int -> Int -> Bool)
g 2 3 = True
g 3 2 = True
g 1 2 = True
g 2 1 = True
g 1 1 = True
g n m = False
Answer to 2 comment.
I did this and it works, I think.
triangles :: [(Int, Int, Int)]
triangles = [(x, y, z) | x <- [1..3], y <- [1..x], z <- [1..y], isTriangle (x, y, z)]
isTriangle :: (Int, Int, Int) -> Bool
isTriangle (x, y, z) = g x y && g y z && g x z
I removed (_,g) and (n,g) (I dont understand why we need them :)
I call trinagles and it return (1,1,1) (2,1,1) (in my case). Is it right?
I guess the first Int of Graph is a bound for your nodes (like, 6 if the nodes are in [1..6]).
Therefore, you would like a function that returns the triangles of a graph, so the type might be:
triangles :: Graph -> [(Int, Int, Int)]
Now, a triangle exists whenever, for 3 nodes, say x y and z, all the combinations return True through g.
So, you might want to consider generating all these combinations (possibly avoiding the ones that are equivalent via re-ordering), and filter out only those that validate the criterion:
isTriangle :: Graph -> (Int, Int, Int) -> Bool
isTriangle (_, g) (x, y, z) == g x y && g y z && g x z
For this, you could use a list comprehension, or the function filter which has type (a -> Bool) -> [a] -> [a]
Answer to your first comment:
First, you would need to implement the triangles function, which is the reason of the error. But, as you have done in test, you could simply generate these triangles on the fly.
Now, you wrote:
test = filter (isTriangle) [(x,y,z) | x <- [1..3], y <- [1..3], z <- [1..3]]
Two things about this:
First, you wouldn't need the parentheses around isTriangle for what you wrote, but it is incorrect, since isTriangle expects a graph as its first parameter
Second, you are going to obtain a lot of duplicates, and if you want, you can prevent this by not generating them in the first place:
test = filter (isTriangle) [(x,y,z) | x <- [1..3], y <- [1..x], z <- [1..y]]
Alternatively, you can dismiss the filter function by providing a guard in the list comprehension syntax, as this:
[(x, y, z) | x <- [1..3], y <- [1..x], z <- [1..y], isTriangle yourGraph (x, y, z)]
Now, I'll let you go on with the details. You will want to make this a function that takes a graph, and to replace this 3 by the number of nodes in the graph, and yourGraph by said graph.
Since you chose to use list comprehension, forget about the generating function that I wrote about earlier, its purpose was just to generate input for filter, but with the list comprehension approach you won't necessarily need it.
Answer to your second comment:
You want to write a function:
triangles :: Graph -> [(Int, Int, Int)]
triangles (n, g) = [(x, y, z) | ...]
The ... are to be replaced with the correct things, from earlier (ranges for x, y and z, as well as the predicate isTriangle).
Alternatively, you can cut this in two functions:
allTriangles :: Int -> [(Int, Int, Int)]
allTriangles n = [(x, y, z) | ...]
graphTriangles :: Graph -> [(Int, Int, Int)]
graphTriangles (n, g) = [t | t <- allTriangles n, isGraphTriangle t]
where isGraphTriangle (x, y, z) = ...
This way, you could potentially reuse allTriangles for something else. If you don't feel the need, you can stay with the one-shot big comprehension triangles, since it's a homework you probably won't build up on it.
I try not to fill all the ... so that you can do it yourself and hopefully understand :)
Correcting your solution:
First, my mistake on the ranges, it should be x <- [1..n], y <- [x+1..n], z <- [y+1..n] where n denotes the number of nodes in your graph. This way, you only capture triples where x < y < z, which ensures that you only see one occurence of each set of three points.
Second, the reason why I put the graph as a parameter to the functions is that you might want to reuse the same function for another graph. By hardcoding g and 6 in your functions, you make them really specific to the particular graph you described, but if you want to compute triangles on a certain number of graphs, you do not want to write one function per graph!
I don’t really like your graph type but whatever. Here’s the algorithm we will use:
First find a Node x of the graph.
For every other node y see if it connects to x
If y does connect to x then for each node z, see if it connects to x and y
If so then return it.
To avoid duplicates, we require z<x<y
nodes (n,_) = [1..n]
nodesBefore (n,_) k = [1..min n (k - 1)]
edge (_,e) x y = e x y
neighboursBefore g x = [ y | y <- nodesBefore g x, edge g x y]
triangles g = [(x,y,z) | x <- nodes g, y <- neighboursBefore g x, z <- neighboursBefore g y, edge g x z]