I'm trying to write a function that receives a list, finds the highest value integer in the list, and then divides all the other integers in the list by that value.
Unfortunately, my code gets stuck somewhere. If this were python for example I could easily write a couple different "print"s and see where it gets stuck. But how do you do that in Erlang?
Here is the code.
highest_value([], N) ->
if
N =:= 0 ->
'Error! No positive values.'
end,
N;
highest_value([H|T], N) when H > N, H > 0 ->
highest_value([T], H);
highest_value([_|T], N) ->
highest_value([T], N).
divide(_L) -> [X / highest_value(_L, 0) || X <- _L].
For prints you could just use io:format/2. Same thing.
highest_value([H|T], N) when H > N, H > 0 ->
io:format(">>> when H bigger than N~n"),
io:format(">>> H: ~p, T: ~p, N: ~p ~n", [H, T, N]),
highest_value([T], H);
highest_value(List) ->
highest_value(List, 0).
EDIT
One thing you are getting wrong is [H | T] syntax. H, or head, is the first element in the list. T stands for tail, or "rest of the list". And like the name suggests, tail is a list (could be an empty list, but a list nonetheless). So when you are doing you recursion you don't need to put T inside a new list.
highest_value([H|T], N) when H > N ->
highest_value(T, H);
highest_value([_|T], N) ->
highest_value(T, N).
In your old code you called:
highest_value([T], N).
which created a new list with one element, like [[2,3,4,5]]. If you head-tail this, you get this only-element-list as the head, and an empty list as the tail.
Also, in your first function clause you have an atom 'Error! No positive values.' (singe quotes means this is just a long atom, and not a string) which is never returned (you will always return N). If you would like to return either some atom, or N, depending on value of N you could just extend your use of function clauses
highest_value([], 0) ->
'Error! No positive values.'
highest_value([], N) ->
N;
[...]
And you have to initialize your function with 0, which could be considered a bad pattern. You could write and use highest_value/1 which does that for you
highest_value(List) ->
highest_value(List, 0).
Or even use a modification of this algorithm: since the largest number will be one of the numbers in the list, you could use the first element as the function initialization.
highest_value(_List = [First|T]) when First > 0 ->
highest_value(T, First).
This assumes that handling negative numbers is something you don't care about right now.
While debugging via print statements is common and even sometimes useful, and io:format can be used for this purpose in Erlang as already noted, Erlang provides powerful built-in tracing capabilities you should use instead.
Let's say your highest_value/2 and divide/1 functions reside in a module named hv. First, we compile hv in the Erlang shell:
1> c(hv).
{ok,hv}
Next, we use Erlang's dbg module to enable tracing on the hv functions:
2> dbg:tracer().
{ok,<0.41.0>}
3> dbg:p(self(),call).
{ok,[{matched,nonode#nohost,26}]}
4> dbg:tpl(hv,c).
{ok,[{matched,nonode#nohost,5},{saved,c}]}
In command 2 we enable debug tracing and in command 3 we indicate that we want to trace function calls in our current process (returned by self()). In command 4 we create a call trace, using the built-in c trace specification, on all functions in the hv module.
Once debug tracing is enabled, we call hv:divide/1 and the trace output begins:
5> hv:divide([4,8,12,16]).
(<0.34.0>) call hv:divide([4,8,12,16]) ({erl_eval,do_apply,6})
(<0.34.0>) call hv:'-divide/1-lc$^0/1-0-'([4,8,12,16],[4,8,12,16]) ({erl_eval,
do_apply,
6})
(<0.34.0>) call hv:highest_value([4,8,12,16],0) ({hv,'-divide/1-lc$^0/1-0-',2})
(<0.34.0>) call hv:highest_value([[8,12,16]],4) ({hv,'-divide/1-lc$^0/1-0-',2})
(<0.34.0>) call hv:highest_value([[]],[8,12,16]) ({hv,'-divide/1-lc$^0/1-0-',2})
(<0.34.0>) call hv:highest_value([[]],[8,12,16]) ({hv,'-divide/1-lc$^0/1-0-',2})
...
First, note that I abbreviated the trace output because at the ... point it's already in an infinite loop, and the remainder of the trace is identical to the two statements prior to the ....
What does the trace output tell us? The first line shows the invocation of the divide/1 function, and the second line shows the call to the list comprehension inside divide/1. We then see calls to highest_value/2, first with the full list and N set to 0. The next call is where it gets interesting: because your code passes [T] rather than T as the first argument in the recursive invocation of highest_value/2, H has the value [8,12,16], which Erlang treats as being greater than the current N value of 4, so the next recursive call is:
highest_value([T], [8,12,16]).
and because T is [], this turns into:
highest_value([[]], [8,12,16]).
Here, H is [], and T is also []. H is not greater than [8,12,16], so all remaining recursive invocations after this point are identical to this one, and the recursion is infinite.
To fix this, you need to pass T correctly as already noted:
highest_value([H|T], N) when H > N, H > 0 ->
highest_value(T, H);
highest_value([_|T], N) ->
highest_value(T, N).
Then recompile, which also reloads your module, and because of that you'll also need to set up your debug tracing again:
5> c(hv).
{ok,hv}
6> dbg:tpl(hv,c).
{ok,[{matched,nonode#nohost,5},{saved,c}]}
7> hv:divide([4,8,12,16]).
(<0.34.0>) call hv:divide([4,8,12,16]) ({erl_eval,do_apply,6})
(<0.34.0>) call hv:'-divide/1-lc$^0/1-0-'([4,8,12,16],[4,8,12,16]) ({erl_eval,
do_apply,
6})
(<0.34.0>) call hv:highest_value([4,8,12,16],0) ({hv,'-divide/1-lc$^0/1-0-',2})
(<0.34.0>) call hv:highest_value([8,12,16],4) ({hv,'-divide/1-lc$^0/1-0-',2})
(<0.34.0>) call hv:highest_value([12,16],8) ({hv,'-divide/1-lc$^0/1-0-',2})
(<0.34.0>) call hv:highest_value([16],12) ({hv,'-divide/1-lc$^0/1-0-',2})
(<0.34.0>) call hv:highest_value([],16) ({hv,'-divide/1-lc$^0/1-0-',2})
** exception error: no true branch found when evaluating an if expression
in function hv:highest_value/2 (/tmp/hv.erl, line 5)
in call from hv:'-divide/1-lc$^0/1-0-'/2 (/tmp/hv.erl, line 15)
Tracing now shows that highest_value/2 is working as expected, but we now hit a new problem with the if statement, and the fix for this is already explained in another answer so I won't repeat it here.
As you can see, Erlang's tracing is far more powerful than using "print debugging".
It can be turned on and off interactively in the Erlang shell as needed.
Unlike debugging in other languages, debug tracing requires no special compilation flags for your modules.
Unlike with debug print statements, you need not change your code and recompile repeatedly.
What I've shown here barely scratches the surface as far as Erlang's tracing capabilities go, but it was more than enough to find and fix the problems.
And finally, note that using the lists:max/1 standard library call you can more easily achieve what your module is trying to do:
divide(L) ->
case lists:max(L) of
N when N > 0 ->
[V/N || V <- L];
_ ->
error(badarg, [L])
end.
Related
I am new to Prolog. I want a predicate that takes a list, process it with maplist/3 creating a corresponding list with zeros in place of numbers less than mean and 1 for number above the mean. I then want a second predicate to sum the 1's to find out how many numbers are above the mean. This second predicate then returns this number which corresponds to total numbers above the mean.
I know the code below works fine:
numAtOrAboveMean(Mean, Num, Val) :- Num > Mean -> Val is 1; Val is 0.
maplist(numAtOrAboveMean(Mean), [], List), sumlist(List, Below).
When I modified it to this, I get a type erros that expected [] but found a list. The comments correspond to how I think the predicate behavior is.
nGMean(Mean, Num, Val) :- Num > Mean -> Val is 1; Val is 0.%sorts list
nGMean([], _ , []). %takes a list, a constant, relates to a list
nGMean(L, Mean, List) : - maplist(nGMean(Mean), L, List). %maplist call sort
Then to sum I will use a second predicate. Something like this:
sumtotal(L,V) :- mean(L, M), M2 is M, nGMean(L, M2, List), sum(List, V).
Which is not working probably mostly because nGMean is throwing an error. nGMean full error is shown below:
So my question is, why am I getting that type error on the nGMean predicate?
Edit -As requested in comments below is the entire thing. As I explained that is the only part because I am testing it separately.
Thank you for answers. Next time I will post complete code.Or make clear that I just want to trouble shoot one predicate.
Maplist for numAtOrAboveMean
Full Pic of code on Editor
You should post complete code that can just be copied and run. In what you have posted, mean/2 and sum/2 are not defined.
(Addition:) the reason for the error seems to be that you are comparing a value and a list (2<[2,3|...]). The reason this happens is because your first clause for nGMean/3 has Mean as first parameter, whereas the other clauses has the list, i.e. the list becomes Mean which is used in the comparison (Num > Mean). I'm not sure how > becomes <.
Also, calling maplist/3 on an empty list does not make sense.
A recursive predicate should have two clauses. A recursive clause that (typically) does something with the head of the list and then calls recursively on the tail, and a base case (empty list).
nGMean([Num|Nums],Mean,[Val|List]) :-
( Num > Mean ->
Val = 1
; Val = 0 ),
nGMean(Nums,Mean,List).
nGMean([],_,[]).
With this definition I get the same output as your first two lines above, so I believe this is what you wanted.
(Earlier addition: you only need to use is when the right-hand side contains mathematical calculations. To just set a value, = is fine.)
As a personal excercize in the process of learning Haskell, I'm trying to port this F# snippet for Random Art.
I've not embedded full source code for not bloating the question, but is available as gist.
An important part of the program is this Expr type:
data Expr =
VariableX
| VariableY
| Constant
| Sum Expr Expr
| Product Expr Expr
| Mod Expr Expr
| Well Expr
| Tent Expr
| Sin Expr
| Level Expr Expr Expr
| Mix Expr Expr Expr
deriving Show
and two functions:
gen :: Int -> IO Expr random generates a tree-like structure given a number of iterations
eval :: Expr -> IO (Point -> Rgb Double) walks the tree and terminates producing a drawing function.
More high is the number passed to gen than higher are the probability that the following exception is generated: Ratio has zero denominator.
I'm new to Haskell so to solve the problem I've tried to compile it as above:
ghc RandomArt.hs -prof -auto-all -caf-all
Obtaining only this more (to me quite useless) info:
$ ./RandomArt +RTS -xc
*** Exception (reporting due to +RTS -xc): (THUNK_STATIC), stack trace:
GHC.Real.CAF
--> evaluated by: Main.eval.\,
called from Main.eval,
called from Main.tga.pxs',
called from Main.tga,
called from Main.save,
called from Main.main,
called from :Main.CAF:main
--> evaluated by: Main.eval.\.r,
called from Main.eval.\,
called from Main.eval,
called from Main.tga.pxs',
called from Main.tga,
called from Main.save,
called from Main.main,
called from :Main.CAF:main
*** Exception (reporting due to +RTS -xc): (THUNK_STATIC), stack trace:
Main.tga,
called from Main.save,
called from Main.main,
called from GHC.Real.CAF
RandomArt: Ratio has zero denominator
The code that persist the generated function to a TGA file works because it was my previous excercize (a port from OCaml).
I've tried executing various Expr tree from GHCi, assembling data by hand or applying functions as in the program but I wasn't able to identify the bug.
Haskell docs talks about a package named loch that should able to compile preserving source code line numbers, but I was not able to install it (while I normally install with cabal install every package I need).
The question, to be honest are two:
where's is the bug (in this specific case)?
which tool do I need to master to find bugs like this (or bugs in general)?
Thanks in advance.
The exception
Let's focus on the exception first.
Finding the bug
where's is the bug (in this specific case)?
In mod'. We can check this easily if we provide an alternative version instead of the one by Data.Fixed:
mod' :: RealFrac a => a -> a -> a
mod' _ 0 = error "Used mod' on 0"
mod' a b =
let k = floor $ a / b
in a - (fromInteger k) * b
We now get Used mod' on 0.
Rationale
which tool do I need to master to find bugs like this (or bugs in general)?
In this case, the necessary hint was already in the exception's message:
Ratio has zero denominator
This means that there's a place where you divide by zero in the context of a Ratio. So you need to look after all places where you divide something. Since you use only (/) and mod', it boils down to whether one of them actually can throw this exception:
(/) usually returns ±Infinity on division by zero if used on Double,
mod' uses toRational internally, which is a Ratio Integer.
So there's only one culprit left. Note that the other implementation yields the same results if b isn't zero.
The actual problem
Using mod or mod' with b == 0 isn't well-defined. After all, a modulo operation should hold the following property:
prop_mod :: Integral n => n -> n -> Bool
prop_mod a b =
let m = a `mod` b
d = a `div` b
in a == b * d + m -- (1)
&& abs m < abs b -- (2)
If b == 0, there doesn't exist any pair (d, m) such that (1) and (2) hold. If we relax this law and throw (2) away, the result of mod isn't necessarily unique anymore. This leads to the following definition:
mod' :: RealFrac a => a -> a -> a
mod' a 0 = a -- this is arbitrary
mod' a b =
let k = floor $ a / b
in a - (fromInteger k) * b
However, this is an arbitrary definition. You have to ask yourself, "What do I actually want to do if I cannot use mod in a sane way". Since F# apparently didn't complain about a % 0, have a look at their documentation.
Either way, you cannot use a library mod function, since they aren't defined for a zero denominator.
I want to append([],C,C) where C is a list containing some elements . Is it possible? I will append some list in C containing elements append (Found,C,C) if other condition is true.
And also i want to store final value in C to a variable D . How can I do that?
I want to append([],C,C) where C is a list containing some elements. Is it possible?
append([],C,C) is always true. An empty list combined with anything is that anything. Look what Prolog says when you attempt it:
?- append([],C,C).
true.
This true without any bindings tells you that Prolog established the proof but no new bindings were created as a result. This code would have the same result:
meaningless(_, _, _).
?- meaningless(everybody, X, Squant).
true.
This suggests your desire is misplaced. append([], C, C) does not do what you think it does.
I will append some list in C containing elements append (Found,C,C) if other condition is true. And also i want to store final value in C to a variable D. How can I do that?
Thinking in terms of "storing" and other operations implying mutable state is a sure sign that you are not understanding Prolog. In Prolog, you establish bindings (or assert facts into the dynamic store, which is a tar pit for beginners). Something similar could be achieved in a Prolog fashion by doing something like this:
frob(cat, List, Result) :- append([cat], List, Result).
frob(dog, List, List).
This predicate frob/3 has two in-parameters: an atom and a list. If the atom is cat then it will append [cat] to the beginning of the list. The threading you see going between the arguments in the head of the clause and their use in the body of the clause is how Prolog manages state. Basically, all state in Prolog is either in the call stack or in the dynamic store.
To give an example in Python, consider these two ways of implementing factorial:
def fac(n):
result = 1
while n > 1:
result = result * n
n = n - 1
This version has a variable, result, which is a kind of state. We mutate the state repeatedly in a loop to achieve the calculation. While the factorial function may be defined as fac(n) = n * fac(n-1), this implementation does not have fac(n-1) hiding in the code anywhere explicitly.
A recursive method would be:
def fac(n):
if n < 1:
return 1
else:
return n * fac(n-1)
There's no explicit state here, so how does the calculation work? The state is implicit, it's being carried on the stack. Procedural programmers tend to raise a skeptical eyebrow at recursion, but in Prolog, there is no such thing as an assignable so the first method cannot be used.
Back to frob/3, the condition is implicit on the first argument. The behavior is different in the body because in the first body, the third argument will be bound to the third argument of the append/3 call, which will unify with the list of the atom cat appended to the second argument List. In the second body, nothing special will happen and the third argument will be bound to the same value as the second argument. So if you were to call frob(Animal, List, Result), Result will be bound with cat at the front or not based on what Animal is.
Do not get mixed up and think that Prolog is just treating the last argument as a return value! If that were true, this would certainly not work like so:
?- frob(X, Y, [whale]).
X = dog,
Y = [whale].
What appears to have happened here is that Prolog could tell that because the list did not start with cat it was able to infer that X was dog. Good Prolog programmers aspire to maintain that illusion in their APIs, but all that really happened here is that Prolog entered the first rule, which expanded to append([cat], X, [whale]) and then unification failed because Prolog could not come up with an X which, having had [cat] prepended to it, would generate [whale]. As a result, it went to the second rule, which unifies X with dog and the second two arguments with each other. Hence Y = [whale].
I hope this helps!
Here is what I have and the error that I am getting sadly is
Error: This function has type 'a * 'a list -> 'a list
It is applied to too many arguments; maybe you forgot a `;'.
Why is that the case? I plan on passing two lists to the deleteDuplicates function, a sorted list, and an empty list, and expect the duplicates to be removed in the list r, which will be returned once the original list reaches [] condition.
will be back with updated code
let myfunc_caml_way arg0 arg1 = ...
rather than
let myfunc_java_way(arg0, arg1) = ...
Then you can call your function in this way:
myfunc_caml_way "10" 123
rather than
myfunc_java_way("10, 123)
I don't know how useful this might be, but here is some code that does what you want, written in a fairly standard OCaml style. Spend some time making sure you understand how and why it works. Maybe you should start with something simpler (eg how would you sum the elements of a list of integers ?). Actually, you should probably start with an OCaml tutorial, reading carefully and making sure you aunderstand the code examples.
let deleteDuplicates u =
(*
u : the sorted list
v : the result so far
last : the last element we read from u
*)
let rec aux u v last =
match u with
[] -> v
| x::xs when x = last -> aux xs v last
| x::xs -> aux u (x::v) x
in
(* the first element is a special case *)
match u with
[] -> []
| x::xs -> List.rev (aux xs [x] x)
This is not a direct answer to your question.
The standard way of defining an "n-ary" function is
let myfunc_caml_way arg0 arg1 = ...
rather than
let myfunc_java_way(arg0, arg1) = ...
Then you can call your function in this way:
myfunc_caml_way "10" 123
rather than
myfunc_java_way("10, 123)
See examples here:
https://github.com/ocaml/ocaml/blob/trunk/stdlib/complex.ml
By switching from myfunc_java_way to myfunc_caml_way, you will be benefited from what's called "Currying"
What is 'Currying'?
However please note that you sometimes need to enclose the whole invocation by parenthesis
myfunc_caml_way (otherfunc_caml_way "foo" "bar") 123
in order to tell the compiler not to interpret your code as
((myfunc_caml_way otherfunc_caml_way "foo") "bar" 123)
You seem to be thinking that OCaml uses tuples (a, b) to indicate arguments of function calls. This isn't the case. Whenever some expressions stand next to each other, that's a function call. The first expression is the function, and the rest of the expressions are the arguments to the function.
So, these two lines:
append(first,r)
deleteDuplicates(remaining, r)
Represent a function call with three arguments. The function is append. The first argument is (first ,r). The second argument is deleteDuplicates. The third argument is (remaining, r).
Since append has just one argument (a tuple), you're passing it too many arguments. This is what the compiler is telling you.
You also seem to be thinking that append(first, r) will change the value of r. This is not the case. Variables in OCaml are immutable. You can't do anything that will change the value of r.
Update
I think you have too many questions for SO to help you effectively at this point. You might try reading some OCaml tutorials. It will be much faster than asking a question here for every error you see :-)
Nonetheless, here's what "match failure" means. It means that somewhere you have a match that you're applying to an expression, but none of the patterns of the match matches the expression. Your deleteDuplicates code clearly has a pattern coverage error; i.e., it has a pattern that doesn't cover all cases. Your first match only works for empty lists or for lists of 2 or more elements. It doesn't work for lists of 1 element.
I am solving the Programming assinment for Harvard CS 51 programming course in ocaml.
The problem is to define a function that can compress a list of chars to list of pairs where each pair contains a number of consequent occurencies of the character in the list and the character itself, i.e. after applying this function to the list ['a';'a';'a';'a';'a';'b';'b';'b';'c';'d';'d';'d';'d'] we should get the list of [(5,'a');(3,'b');(1,'c');(4,'d')].
I came up with the function that uses auxiliary function go to solve this problem:
let to_run_length (lst : char list) : (int*char) list =
let rec go i s lst1 =
match lst1 with
| [] -> [(i,s)]
| (x::xs) when s <> x -> (i,s) :: go 0 x lst1
| (x::xs) -> go (i + 1) s xs
in match lst with
| x :: xs -> go 0 x lst
| [] -> []
My question is: Is it possible to define recursive function to_run_length with nested pattern matching without defining an auxiliary function go. How in this case we can store a state of counter of already passed elements?
The way you have implemented to_run_length is correct, readable and efficient. It is a good solution. (only nitpick: the indentation after in is wrong)
If you want to avoid the intermediary function, you must use the information present in the return from the recursive call instead. This can be described in a slightly more abstract way:
the run length encoding of the empty list is the empty list
the run length encoding of the list x::xs is,
if the run length encoding of xs start with x, then ...
if it doesn't, then (x,1) ::run length encoding of xs
(I intentionally do not provide source code to let you work the detail out, but unfortunately there is not much to hide with such relatively simple functions.)
Food for thought: You usually encounter this kind of techniques when considering tail-recursive and non-tail-recursive functions (what I've done resembles turning a tail-rec function in non-tail-rec form). In this particular case, your original function was not tail recursive. A function is tail-recursive when the flows of arguments/results only goes "down" the recursive calls (you return them, rather than reusing them to build a larger result). In my function, the flow of arguments/results only goes "up" the recursive calls (the calls have the least information possible, and all the code logic is done by inspecting the results). In your implementation, flows goes both "down" (the integer counter) and "up" (the encoded result).
Edit: upon request of the original poster, here is my solution:
let rec run_length = function
| [] -> []
| x::xs ->
match run_length xs with
| (n,y)::ys when x = y -> (n+1,x)::ys
| res -> (1,x)::res
I don't think it is a good idea to write this function. Current solution is OK.
But if you still want to do it you can use one of two approaches.
1) Without changing arguments of your function. You can define some toplevel mutable values which will contain accumulators which are used in your auxilary function now.
2) You can add argument to your function to store some data. You can find some examples when googling for continuation-passing style.
Happy hacking!
P.S. I still want to underline that your current solution is OK and you don't need to improve it!