How F# returns booleans from AND operation? - f#

I am rather new to F# and just curious about the complexity of my solution to a task. I am not going to explain the whole task I am solving, but the idea is that I would like to return a boolean based on whether all elements of some list satisfy some filter. I am going through the list recursively and checking whether the element satisfies the filter or not and then just return the result AND the next result I get from calling the same function on tail.
When doing so, I got curious whether I should check for false on each step, as the result of AND operation is false as soon as any member of the operation is false. Or does F# return false as soon as it gets false from some element in AND operation itself?
Example:
// I have a function check : int -> bool
// check 1 returns false
check 1 && check 2
Does check 2 get executed or is the value returned instantly after check 1, as it returns false?

&& short circuits. If check 1 returns false, then check 2 is never executed.
You can see this in action if you allow check x to have a side effect:
let check n =
printfn "Checking %i" n
n = 1
check 2 && check 1 // Just prints 'Checking 2'

If you want to test if all members in a list satisfy a predicate, there exists already the built in function List.forall.
Example
List.forall (fun x -> x < 10) [1..10] //false

Related

This expression was expected to have type bool but here has type unit error

getting an error when I try to run this line of code and I can't figure out why
let validCol column value : bool =
for i in 0..8 do
if sudokuBoard.[i,column] = value then
false
else true
As Tyler Hartwig says a for loop cannot return a value except unit.
On the other hand, inside a list comprehension or a seq Computation Expression you can use for to yield the values and then test if the one you are looking for exists:
let validCol column value : bool =
seq { for i in 0..8 do yield sudokuBoard.[i,column] }
|> Seq.exists value
|> not
In F#, the last call made is what is returned, you have explicitly declared you are returning a bool.
The for loop is unable to return or aggregate multiple values, bun instead, returns unit.
let validCol column value : bool =
for i in 0..8 do
if sudokuBoard.[i,column] = value then
false
else
true
Here, you'll need to figure out how to aggregate all the bool to get your final result. I'm not quite sure what this is supposed to return, or I'd give an example.
It looks like you are looking for a short-cut out of the loop like in C# you can use continue, break or return to exit a loop.
In F# the way to accomplish that with performance is to use tail-recursion. You could achieve it with while loops but that requires mutable variables which tail-recursion doesn't need (although we sometimes uses it).
A tail-recursive function is one that calls itself at the very end and doesn't look at the result:
So this is tail-recursive
let rec loop acc i = if i > 0 then loop (acc + i) (i - 1) else acc
Where this isn't
let rec loop fib i = if i < 1 then 1 else fib (i - 1) + fib (i - 2)
If F# compiler determines a function is tail-recursive the compiler applies tail-recursion optimization (TCO) on the function, basically it unrolls it into an efficient for loop that looks a lot like the loop would like in C#.
So here is one way to write validCol using tail-recursion:
let validCol column value : bool =
// loops is tail-recursive
let rec loop column value i =
if i < 9 then
if sudokuBoard.[i,column] = value then
false // The value already exists in the column, not valid
else
loop column value (i + 1) // Check next row.
else
true // Reach the end, the value is valid
loop column value 0
Unfortunately; F# compiler doesn't have an attribute to force TCO (like Scala or kotlin does) and therefore if you make a slight mistake you might end up with a function that isn't TCO. I think I saw GitHub issue about adding such an attribute.
PS. seq comprehensions are nice in many cases but for a sudoku solver I assume you are looking for something that is as fast as possible. seq comprehensions (and LINQ) I think adds too much overhead for a sudoku solver whereas tail-recursion is about as quick as you can get in F#.
PS. In .NET 2D arrays are slower than 1D arrays, just FYI. Unsure if it has improved with dotnet core.

exception error: no match of right hand side value []

I am trying to see if a letter exists in a list, i am currently doing like the following
sortedlist(Text)-> freq(lists:sort(Text)).
freq(List) -> freq (List, [], []).
freq(List, Freq, CheckedLetters) when length(List) > 0 ->
[CurrHead|T]= List,
Checked = lists:member(CurrHead,CheckedLetters),
case Checked of
false -> CheckedLetters++[CurrHead],
freq(T,Freq++[{CurrHead,count(CurrHead, List)}],CheckedLetters);
true -> freq(T,Freq,CheckedLetters)
end;
freq([],Freq,CheckedLetters)-> Freq.
List contains user entered letters
CheckedLetters is an empty list, that will keep track of the already examined letters
But I am receiving the following erlang exception at the case-statement line (the lines with **).
error: no match of right hand side value []
What is the problem here? I am been blindy staring at those lines.
The end condition is missing in your recursive function. So when list become empty (each time you recall the function with the tail it is getting smaller), the match [CurrHead|T]= List, fails with error.
You have to add a clause to manage the end of recursion:
freq([], Freq, CheckedLetters) when length(List) > 0 ->
{Freq, CheckedLetters};
freq(List, Freq, CheckedLetters) when length(List) > 0 ->
[CurrHead|T]= List,
Checked = lists:member(CurrHead,CheckedLetters),
case Checked of
true -> CheckedLetters++[CurrHead],
freq(T,Freq++[{CurrHead,count(CurrHead, List)}],CheckedLetters);
false -> freq(T,Freq,CheckedLetters)
end;
I think you will have also to review the inside operation, I doubt it is doing what you expect. in particular the line CheckedLetters++[CurrHead], has no effect.
[edit]
Don't forget that variables are not mutable in erlang. So the line CheckedLetters++[CurrHead] simply evaluates a new list and forget the result (in fact I am not sure it does anything since you do not bound this evaluation to any variable, and the compiler knows it).
I guess that what you want to do is:
case Checked of
true ->
freq(T,Freq++[{CurrHead,count(CurrHead, List)}],CheckedLetters++[CurrHead]);
false ->
freq(T,Freq,CheckedLetters)
end;
Next you should have a look at Freq++[{CurrHead,count(CurrHead, List)}], I think it isn't correct.
The only piece of code in that block that could error: no match of right hand side value [] is [CurrHead|T]= List, as Steve Vinoski said. Likely there is some scenario where List is an empty list instead of a list of letters.
Also, the last line in the code block you shared:
case Checked == false of
...
end
Can be simplified to:
case Checked of
true ->
...
false ->
...
end
Since Checked is the return value of lists:member/2, and lists:member/2 is guaranteed to return a boolean, you can safely match directly on the true and false atoms.
lists:member/2 documentation: http://erlang.org/doc/man/lists.html#member-2

Finding if Integer is Even or Odd

I am learning Erlang and one of the problems as per Joe's book states
The function even(X) should return true if X is an even integer and
otherwise false. odd(X) should return true if X is an odd integer.
The way I solve this is
-module(math_functions).
%% API
-export([even/1, odd/1]).
even(Integer) -> (Integer >= 0) and (Integer rem 2 =:= 0).
odd(Integer) -> (Integer >= 1) and (Integer rem 2 =/= 0).
and run this as
Eshell V6.2 (abort with ^G)
1> math_functions:odd(13).
true
2> math_functions:odd(-13).
false
3> math_functions:odd(1).
true
4> math_functions:even(1).
false
5> math_functions:even(2).
true
6> math_functions:even(-2).
false
7>
The question I have is if there are better ways to do this
Thanks
You could use guards to limit yourself to integers greater than or equal to zero, and then simply check the least-significant bit as suggested in the comment to your question. You can also define odd/1 in terms of even/1:
even(X) when X >= 0 -> (X band 1) == 0.
odd(X) when X > 0 -> not even(X).
The guards are part of the function-head, so if you call even(-1) it will fail to match in exactly the same way as if you called even(1, 2) (i.e. with the wrong number of arguments).
Answer to Daydreamer comment about Steve answer.
When you write a function, a frequent usage in erlang is to code only the "success" cases and let crash the unsuccessful cases (I'll come back later to explain why it is important).
Another criteria, valid for any language, is to avoid surprise when someone use or read your code.
In one of your comment you say that the odd and even functions you want to write are limited to positive or null integers (I won't discuss this choice, and at least the odd and even functions are limited to integers). This means that you have to ask yourself a first question: what is the behavior of my function if it is called with a bad parameter.
First choice: let it crash this the Steve proposition: the function works only with the correct arguments. I always prefer this solution. The only exception is if I do not master the input parameters, for example if they come directly from a file, a user interface ... Then I prefer the third choice.
Second choice: return a result this is your choice: you return false. From a logic point of view, for odd and even function, returning false is valid: is something is not true, it is false :o). I don't like this solution for 2 reasons. The first one is that it is not something you can generalize easily to something else than boolean answer. The second and more important to me, is that it may surprise the user. When the function odd(N) return false, it is reasonable to think that N is even, while in this case odd(-2) and even(-2) will both return false.
third choice: return a tagged result this is something you see very often in erlang: a function return either {ok,Value} or {Error,Term}. doing this you let the choice to the calling function to manage or not a bad arguments errors. the Error variable allows you to have explicit error messages, useful for debug and also user interface. In your example the code becomes:
even(X) when is_integer(X), X >= 0 -> {ok,(X band 1) == 0};
even(X) -> {illegal_param,X}.
odd(X) when is_integer(X), X >= 0 -> {ok,(X band 1) == 1};
odd(X) -> {illegal_param,X}.
When programming, it is important to detect error as soon as possible, in erlang it is even more important. If one process does not detect (and the simplest detection is crash) and error and propagate some invalid information through messages, it may be very difficult to find the root cause of a problem, ignoring which process (maybe died) issued this message. Coding only the success cases is an easy way to detect problems as soon as possible.
Find the no if even
%functions that manipulate functions are called higher-order %functions, and the data type that represents a function in Erlang is %called a fun. here in below example you see FUNCTIONS THAT HAVE %FUNCTIONS AS THEIR ARGUMENTS
% K is an example list
1> K=[4,5,6,8,10].
[4,5,6,8,10]
% Use lisst:filter to perform no/2 and filter if rem=0
2> lists:filter(fun(J)->(J rem 2)=:=0 end, K).
[4,6,8,10]
Another way:
% Function to check even
22> Checkeven=fun(U)->(U rem 2)=:=0 end.
#Fun<erl_eval.7.126501267>
23> Checkeven(5).
false
% Define a test list
25> K=[1,2,3,4,5].
[1,2,3,4,5]
% Use lists filter to apply Checkeven func to all elements of k
26> lists:filter(Checkeven,K).
[2,4]
%Using List comprehension
42> K.
[1,2,3,4,5]
% For all elements of K check remainder of elem/2 is zero
43> [(S rem 2=:=0) || S<-K].
[false,true,false,true,false]

Erlang list comprehension, once again

I'm trying to get a list comprehension working, which intention is to verify that each element X in List is followed by X+Incr (or an empty list). Later, I shall use that list and compare it with a list generated with lists:seq(From,To,Incr).
The purpose is to practice writing test cases and finding test properties.
I've done the following steps:
1> List.
[1,3,5,8,9,11,13]
2> Incr.
2
3> List2=[X || X <- List, (tl(List) == []) orelse (hd(tl(List)) == X + Incr)].
[1]
To me, it seem that my list comprehension only takes the first element in List, running that through the filter/guards, and stops, but it should do the same for EACH element in List, right?
I would like line 3 returning a list, looking like: [1,2,9,11,13].
Any ideas of how to modify current comprehension, or change my approach totally?
PS. I'm using eqc-quickcheck, distributed via Quviq's webpage, if that might change how to solve this.
The problem with your list comprehension is that List always refers to the entire list. Thus this condition allows only those X that are equal to the second element of List minus Incr:
(hd(tl(List)) == X + Incr)
The second element is always 3, so this condition only holds for X = 1.
A list comprehension cannot "look ahead" to other list elements, so this should probably be written as a recursive function:
check_incr([], _Incr) ->
true;
check_incr([_], _Incr) ->
true;
check_incr([A, B | Rest], Incr) ->
A + Incr == B andalso check_incr([B | Rest], Incr).
Maybe I'm misunderstanding you, but a list comprehension is supposed to be "creating a list based on existing lists". Here's one way to generate your list using a list comprehension without using lists:seq:
> Start = 1, Inc = 2, N = 6.
6
> [Start + X*Inc || X <- lists:seq(0,N)].
[1,3,5,7,9,11,13]
You could do something like this:
> lists:zipwith(fun (X, Y) -> Y - X end, [0 | List], List ++ [0]).
[1,2,2,2,2,2,2,-13]
Then check that all elements are equal to Incr, except the first that should be equal to From and the last that should be greater or equal than -To.
One quick comment is that the value List does NOT change when in the comprehension is evaluated, it always refers to the initial list. It is X which steps over all the elements in the list. This means that your tests will always refer to the first elements of the list. As a list comprehension gives you element of a list at a time it is generally not a good tool to use when you want to compare elements in the list.
There is no way with a list comprehension to look at successive sublists which is what you would need (like MAPLIST in Common Lisp).

What does this Erlang statement do?

I have this Erlang code:
not lists:any(fun(Condition) ->Condition(Message) end, Conditions).
Can anyone please explain the entire statement in layman's terms? For your information Condition is a function, Conditions is an array. What does fun(Condition) ->Condition(Message) end mean? As well as meaning of not lists:any.
fun(Condition) ->Condition(Message) end
is a lambda function that applies the function Condition to the value of Message (taken as a closure on the surrounding code).
lists:any
is a function that takes a predicate and a list of values, and calls the predicate on each value in turn, and returns the atom true if any of the predicate calls do.
Overall, the result is the atom true if none of the Condition functions in the list Conditions return true for the Message value.
EDIT -- add documentation for lists:any
any(Pred, List) -> bool()
Types:
Pred = fun(Elem) -> bool()
Elem = term()
List = [term()]
Returns true if Pred(Elem) returns true for at least one element Elem in List.
Condition is something that takes a message and returns a boolean if it meets some criteria.
The code goes through the list of conditions and if any of them say true then it returns false, and if all of them say false it says true.
Roughly translated to verbose pseudo-Python:
def not_lists_any(Message,Conditions):
for Condition in Conditions:
if Condition(Message):
return False
return True
One step behind syntax and stdlib description which you have in other answers:
This code looks very much like an Erlang implementation of chain-of-responsibility design pattern. The message (in OOP sense of the word) "traverses" all possible handlers (functions from Conditions array) until someone can handle it. By the author's convention, the one which handles the message returns true (otherwise false), so if nobody could handle the message the result of your expression as a whole is true:
% this is your code wrapped in a function
dispatch(Message, Handlers) ->
not lists:any(fun(Condition) ->Condition(Message) end, Handlers).
It may be used like this:
CantHandle = dispatch(Event, Handlers),
if CantHandle->throw(cannot_handle); true->ok end.

Resources