How to use propositional logic on a list of values in sml - sml

I am trying to use propositional logic on a list of values. I will have a list of true or false values. I have a logical expression and I am trying to apply it to a list of values. For example, the logical expression T ^ F v T ^ T will be applied to a list of values(true and false).I will be substituting my values with the T and F in the logical expression. So a list of [true ,true ,false , false] when the expression is applied to it will be like "true ^ true v false ^ false". I will have different combination of the list of values.
fun take(a::b::c::d::rest) =
(a andalso b) orelse (c andalso not d);
(*Test *)
take([false , false , true, false]);
val it = true : bool
The function works but I am wondering if I can use recursion instead to apply the logical expression to the list.

Related

Can we construct an infinite list that satisfies a given bit predicate?

If we have a given predicate p :: [Bool] -> Bool that take an infinite list as parameter and return True or False based on some unknown conditions, and we have no idea what this predicate is.
Can we work out a function f :: ([Bool] -> Bool) -> [Bool] that take such predicate and return an infinite list l where p l == True, assuming that the predicate is satisfiable.
You can think of an infinite list [Bool] as being a binary number with the least significant bit first:
0 = repeat False
1 = True : repeat False
2 = False : True : repeat False
3 = True : True : repeat False
and so on to infinity.
So if you construct a function like this:
intToBools :: Integer -> [Bool]
then you can write
f p = head $ filter p $ map intToBools [0..]
Will this work for every predicate p? Well, if we restrict ourselves to total functions then the p must inspect a finite prefix of its argument, and if any finite prefix is acceptable then that prefix must be reached eventually.
If p is not total but can return True for at least one argument (e.g. the predicate "argument contains at least one True"), then this problem cannot be solved as written because we can't know if p x will ever terminate. However if p could be expressed as a state machine:
newtype BoolPredicate = BoolPredicate (Bool -> Either Bool BoolPredicate)
then you could enumerate every possible input by recursively applying True and False to the output of the previous step in a breadth-first search until you find Left True.

Checking whether a given value exists in a binary tree

I am new to SML. I am trying to check whether a given value exist in the binary tree or not. Below is the snippet of the code. Upon execution it gives
Warning : match nonexhaustive (n,Node (t1, j, t2)) => ...
I cannot understand why it is showing this way. I guess I have covered all possible case. Can anyone give me hint or link which will be helpful to remove this warning.
datatype inttree = Empty | Node of inttree * int * inttree;
(*find(n,K) here n is the key that we have to find in inttree K*)
val rec find = fn(n, Node(t1,j,t2)) =>
let
val t = Node(t1, j, t2)
val compare = fn(i,j) => i = j
val find' =
fn (n,Empty) => false (* if we have reached the empty node then we are not able to find the key therefore return false *)
| (n,Node(t1,j,t2)) =>
if compare(n,j)
then true (* if value n and j are equal we have found the key n in the tree*)
else find(n,t1) orelse find(n,t2) (* if the value is not equal check in left subtree if found return true else check in the right subtree*)
in
find'(n,t)
end;
Given your datatype declaration, a fairly direct recursive approach is possible. Since this seems to be homework, I don't want to give a complete solution, but here is a function which has a similar flavor:
fun allEven Empty = true
| allEven (Node(t1,i,t2)) =
if i mod 2 = 1 then false
else allEven t1 andalso allEven t2;
This function returns true or false depending on whether or not all integers in the tree are even. It has a basis case
allEven Empty = true
(true since there are no odd numbers in an empty tree to serve as counter-examples) and a recursive case
allEven (Node(t1,i,t2)) =
if i mod 2 = 1 then false
else allEven t1 andalso allEven t2;
If the integer at the node is odd, return false -- otherwise return true if the recursive call to both branches evaluate to true.
Typical runs:
- allEven (Node(Node(Empty,3,Empty),5,Node(Node(Empty,6,Empty),7,Empty)));
val it = false : bool
- allEven (Node(Node(Empty,4,Empty),2,Node(Node(Empty,6,Empty),8,Empty)));
val it = true : bool
Your function should be about this long and follow the same basic recursive pattern.
Besides val rec, you can also write fun and specify the arguments on the left-hand side of the =.
The helper function compare is largely redundant. You might as well use =. Also, what one would call a compare function in ML is usually one that returns the type order, having the values LESS, EQUALS and GREATER:
- ​Int.compare (3, 5);
> val it = LESS : order
When writing an if ... then true else ... or similar statement that returns the type bool, you might as well just use the combinators orelse and andalso. For example, you can replace the following:
if compare(n,j)
then true
else find(n,t1) orelse find(n,t2)
with:
n = j orelse find (n, t1) orelse find (n, t2)
Much like the built-in functions List.exists and List.all take a function as predicate and scans a list in the attempt to prove either that at least one element exists for which this is true, or that it is true for all elements, you can make functions treeExists and treeForall:
datatype intTree = Empty | Node of inttree * int * inttree;
fun treeExists f Empty = false
| treeExists f (Node (leftTree, x, rightTree)) =
f x orelse treeExists f leftTree orelse treeExists f rightTree
fun treeForall f Empty = true
| treeForall f (Node (leftTree, x, rightTree)) =
f x andalso treeForall f leftTree andalso treeExists f rightTree
Making functions find and allEven has now become simpler:
fun find (x, tree) = treeExists (fn y => x = y) tree
fun allEven tree = treeForall (fn x => x mod 2 = 0) tree
since all the recursion has been left to new library functions.
In a similar way, you can make treeMap and treeFold:
fun treeMap f Empty = Empty
| treeMap f (Node (leftTree, x, rightTree)) = ...
fun treeFold f e Empty = e
| treeFold f e (Node (leftTree, x, rightTree)) = ...
They could be used to find the largest absolute value in a tree:
fun maxAbsTree tree =
treeFold Int.max 0 (treeMap Int.abs tree)

Prolog (SWI): Conjunction over a list?

Say I have a predicate eval(A) that just evaluates to true/false depending on some input
Now the thing is, I want another predicate
and(List, R)
that succeeds iff List is empty/the conjunction of the eval of every element in List is R. Where R is just true/false.
So if List had the items [a, b, c], then return [eval(a) ^ eval(b) ^ eval(c)] == R
My attempt:
and([], true).
and([H|T], R) :- eval(H), and(T, R).
and([H|T], R) :- eval(H) = R.
But i don't know how to compare to R properly.
Prolog has a relational data model, predicates don't carry values. You must add an argument to eval/1, holding the 'return value'.
and([], true).
and([H|T], R) :-
eval(H, X), % could 'shortcircuit' to false here if X is false
and(T, And),
( X == true, And == true -> R = true ; R = false ).
edit better could be, without changing eval/1:
and(L, R) :-
maplist(eval, L) -> R = true ; R = false.

Using fold_left to search for an element in OCaml

I'm wondering how can I build a function in Ocaml that uses List.fold_left to find out if an element exists in a list.
Example:
exists 3 [1;2;3;4;5]
=> true
The type of this function is: a -> bool -> 'a list -> bool
My idea how to do it is as follows:
let exists k l = List.fold_left( fun a x-> a=x) k l
but obviously is wrong. Any suggestion how to do it?
let exists k l =
List.fold_left (fun b x -> b || x = k) false l
Two comments on #tonio's answer:
Use || instead of superfluous if ... then true else ....
Use structural equality (=) instead of reference equality (==) for comparing values.
Moreover, exists is available in List module. The built-in function is more efficient since it doesn't have to go through the whole list every time.
You should use something like
let exists k l =
List.fold_left(
fun a x -> if x == k then true else a)
false l
;;
You have an initial value of false, and pass it while iterating over the list. Once the searched element is found, set the value to true, and pass it along. If the element in the list is not what you search, pass the value you had as input: it is either the initial false, or true if the element you search for has already been found.
after the hints taken by the answers i could be able to improve it more.
Here is my solution
let exists' f l =List.fold_left(fun a b-> f b || a ) false l;;
Like this, this function is more abstract and can be used for any predicate f.

OCaml boolean expression [[]] == [[]]

I have a function that return [[]], and I want to test the result as unit test.
But I found that the expression [[]] == [[]] return false.
Here a simple test code:
# [[]] == [[]];;
- : bool = false
Can someone explain me why this expression is evaluated as false?
Thanks.
Use = since you have structural equality for comparing two values:
# [[]] = [[]];;
- : bool = true
Because == is reference equality, it only returns true if you refer to the same memory location:
let a = [[]]
let b = a
# b == a;;
- : bool = true
The == operator in OCaml means "physical equality". However, you have two (physically) different lists. Probably, you want "structural equality", which is tested by =.