** Reason for termination =
** {badarg,[{erlang,'++',[<<>>,"</after></set></query></iq>"]},
{geoloc,get_nearby,1},
And the method was:
get_nearby({_Pid, DynVars})->
%Last = ts_dynvars:lookup(last, DynVars),
Last = lists:keysearch(last,1,DynVars),
{ok, Rad} = ts_dynvars:lookup(rad,DynVars),
{ok, Lat} = ts_dynvars:lookup(lat,DynVars),
{ok, Lon} = ts_dynvars:lookup(lon,DynVars),
if is_tuple(Last) ->
{value,{Key,After}} = Last,
if length(After) == 0 ->
After2 = "0";
true ->
After2 = After
end,
"<iq id=\"" ++ common:get_random_string(5,"abcdefghijklmnopqrstuvwxyz0123456789-+=") ++ "\" xmlns=\"http://xmpp.xgate.com.hk/plugins\" to=\"xmpp.xgate.hk.com\" type=\"get\"><query xmlns=\"jabber:iq:geoloc\"><geoloc><lat>" ++ Lat ++ "</lat><lon>" ++ Lon ++ "</lon><radius>" ++ Rad ++ "</radius></geoloc><set xmlns=\"http://jabber.org/protocol/rsm\"><max>" ++ integer_to_list(ran_max()) ++ "</max><after>" ++ After2 ++ "</after></set></query></iq>";
true -> % Last is boolean, namely the 'false' atom
ts_dynvars:set([rad, lat, lon], [Rad, Lat, Lon], DynVars),
"<iq id=\"" ++ common:get_random_string(5,"abcdefghijklmnopqrstuvwxyz0123456789-+=") ++ "\" xmlns=\"http://xmpp.xgate.com.hk/plugins\" to=\"xmpp.xgate.hk.com\" type=\"get\"><query xmlns=\"jabber:iq:geoloc\"><geoloc><lat>" ++ Lat ++ "</lat><lon>" ++ Lon ++ "</lon><radius>" ++ Rad ++ "</radius></geoloc><set xmlns=\"http://jabber.org/protocol/rsm\"><max>" ++ integer_to_list(ran_max()) ++ "</max></set></query></iq>"
end.
You are trying to concatenate a binary (<<>>) and a string, but ++ can only concatenate two strings (or lists - Erlang strings are actually lists).
That means that After2 is a binary, and consequently it received this value in the second clause of the if expression. Normally calling length(After) when After is not a list would cause a badarg exception, but as it appears in an if test it is treated as a guard test and exceptions are ignored, and therefore length(After) == 0 is treated as false. So the corresponding value was a binary already when you got it in DynVars.
A few suggestions:
To check whether a list is empty, it is somewhat wasteful to call length on it, as length needs to go through the entire list. Instead, write something like:
case After of
"" ->
After2 = "0";
[_|_] ->
After2 = After
end
[_|_] is a pattern that matches non-empty lists. In your case, the value of After would not match any of the clauses, and you'd have a case_clause error that tells you what value you actually got.
Of course, if you actually expect a binary here, check for <<>> and <<_/binary>> instead.
You're doing quite a few concatenations (++) there. In the expression A ++ B, the ++ operator needs to walk along the entire list in A, and thus the run time is proportional to the length of A.
There are two common alternatives to concatenation. First, often the function that will consume the result doesn't actually need a flat list, but would be equally happy with a "deep list" or "iolist" - instead of "foo" ++ "bar", write ["foo", "bar"]. Notably, if you're going to write the result to a file or send it to a socket, both file:write and gen_tcp:send accept both variants.
Second, you could use binaries instead of strings. Binaries are different from strings in many interesting ways (not the least how they behave with respect to garbage collection), but they do have the nice property that they can be concatenated efficiently. If A and B are binaries, and you write C = <<A/binary, B/binary>>, and the compiler can see that you only use C but not A after that, B will simply be concatenated to the memory area that held A. See the chapter on binary handling in the Efficiency Guide for more details.
The two lines starting with "<iq id=\"" are nearly identical, except that the first one inserts "<after>" ++ After2 ++ "</after>" in the middle. You could have the first case clause set MaybeAfter = "<after>" ++ After2 ++ "</after>" and the second case clause set MaybeAfter = "", and then have one single line that inserts the value of MaybeAfter in the right place. That would help making the code more readable.
Related
In my code I call the validateFEN function with a FEN String. A Fen string looks like this for example:
",w84,w41,w56,w170,w56,w41,w84,/,,w24,w40,w17,w40,w48,,/,,,w16,w16,w16,,,/,,,,,,,,/,,,,,,,,/,,,,,,,,/,,,b1,b1,b1,,,/,,b3,b130,b17,b130,b129,,/,b69,b146,b131,b170,b131,b146,b69,"
The function should take the string and check if it's a FEN string.
How does it know if it's a FEN string? -> My string has 9 rows and 9 columns. I don't need to check if the pieces (example: w86) are at their right position.
validateFEN' b = help3 (filter (\x -> x == ',' || x == '/' ) b)
help3 b = (if help1 b == True then (if head (drop 8 b) == '/' then help3 (drop 9 b) else False) else False )
help1 b = help2 (take 8 b)
help2 b = foldr (+) 0 (map (\x -> if x == ',' then 1 else 0 )b) == 8
Why do I keep getting the error for a empty list?
Exception: Prelude.head: empty list
I understand that with my code there is no stop. The program doesn't know when the string is "correct".
Is there a shorter simpler way of doing this?
One way to reuse existing library functions to make this clearer would be to use stripPrefix.
help3 s = case stripPrefix ",,,,,,,,/" s of
Nothing -> False
Just s' -> help3 s'
Of course, you still need to handle the final case, where there is no terminating /. This can be done with a single extra clause:
help3 ",,,,,,,," = True
help3 s = {- ... -}
You might want to ponder whether validateFEN' should have a similar special case for the empty string.
BUT I would strongly suggest simply not implementing validateFEN' in the first place. My guess is that the plan is something like this:
Check if a string is valid FEN.
Process the string, assuming FEN-ness.
Instead, I recommend the following approach:
Parse the string into a native data structure that represents the information available in a FEN string.
Process the native structure.
Step 1, if written with standard parsing solutions, will "accidentally" validate the string -- i.e. running your parser will return something like Either Error FEN, which you can pattern match on to either discover that the string is invalid or that it is valid and has been turned into a more idiomatic representation.
I tried making a function that as in the title takes 2 arguments, a number that specifies how many times the number must occur and a list that we are working on, I made a function that counts number of appearances of given number in a list and I tried using it in my main function, but I cannot comprehend how the if else and indentations work in Haskell, it's so much harder fixing errors than in other languages, i think that I'm missing else statement but even so I don't know that to put in there
count el list = count el list 0
where count el list output
| list==[] = output
| head(list)==el = count el (tail(list)) output+1
| otherwise = count el (tail(list)) output
moreThan :: Eq a => Int -> [a] -> [a]
moreThan a [] = []
moreThan a list = moreThan a list output i
where moreThan a list [] 0
if i == length (list)
then output
else if elem (list!!i) output
then moreThan a list output i+1
else if (count (list!!i) list) >= a
then moreThan a list (output ++ [list!!i]) i+1
All I get right now is
parse error (possibly incorrect indentation or mismatched brackets)
You just forgot the = sign and some brackets, and the final else case. But also you switched the order of the internal function declaration and call:
moreThan :: Eq a => Int -> [a] -> [a]
moreThan a [] = []
moreThan a list = go a list [] 0 -- call
where go a list output i = -- declaration =
if i == length (list)
then output
else if elem (list!!i) output
then go a list output (i+1) -- (i+1) !
else if (count (list!!i) list) >= a
then go a list (output ++ [list!!i]) (i+1) -- (i+1) !
else
undefined
I did rename your internal function as go, as is the custom.
As to how to go about fixing errors in general, just read the error messages, slowly, and carefully -- they usually say what went wrong and where.
That takes care of the syntax issues that you asked about.
As to what to put in the missing else clause, you've just dealt with this issue in the line above it -- you include the ith element in the output if its count in the list is greater than or equal to the given parameter, a. What to do else, we say in the else clause.
And that is, most probably, to not include that element in the output:
then go a list (output ++ [list!!i]) (i+1)
else ---------------------
undefined
So, just keep the output as it is, there, instead of the outlined part, and put that line instead of the undefined.
More importantly, accessing list elements via an index is an anti-pattern, it is much better to "slide along" by taking a tail at each recursive step, and always deal with the head element only, like you do in your count code (but preferably using the pattern matching, not those functions directly). That way our code becomes linear instead of quadratic as it is now.
Will Ness's answer is correct. I just wanted to offer some general advice for Haskell and some tips for improving your code.
First, I would always avoid using guards. The syntax is quite inconsistent with Haskell's usual fare, and guards aren't composable in the same way that other Haskell syntax is. If I were you, I'd stick to using let, if/then/else, and pattern matching.
Secondly, an if statement in Haskell is very often not the right answer. In many cases, it's better to avoid using if statements entirely (or at least as much as possible). For example, a more readable version of count would look like this:
count el list = go list 0 where
go [] output = output
go (x:xs) output = go xs (if x == el
then 1 + output
else output)
However, this code is still flawed because it is not properly strict in output. For example, consider the evaluation of the expression count 1 [1, 1, 1, 1], which proceeds as follows:
count 1 [1, 1, 1, 1]
go [1, 1, 1, 1] 0
go [1, 1, 1] (1 + 0)
go [1, 1] (1 + (1 + 0))
go [1] (1 + (1 + (1 + 0)))
go [] (1 + (1 + (1 + (1 + 0))))
(1 + (1 + (1 + (1 + 0))))
(1 + (1 + 2))
(1 + 3)
4
Notice the ballooning space usage of this evaluation. We need to force go to make sure output is evaluated before it makes a recursive call. We can do this using seq. The expression seq a b is evaluated as follows: first, a is partially evaluated. Then, seq a b evaluates to b. For the case of numbers, "partially evaluated" is the same as being totally evaluated.
So the code should in fact be
count el list = go list 0 where
go [] output = output
go (x:xs) output =
let new_output = if x == el
then 1 + output
else output
in seq new_output (go xs new_output)
Using this definition, we can again trace the execution:
go [1, 1, 1, 1] 0
go [1, 1, 1] 1
go [1, 1] 2
go [1] 3
go [] 4
4
which is a more efficient way to evaluate the expression. Without using library functions, this is basically as good as it gets for writing the count function.
But we're actually using a very common pattern - a pattern so common, there is a higher-order function named for it. We're using foldl' (which must be imported from Data.List using the statement import Data.List (foldl')). This function has the following definition:
foldl' :: (b -> a -> b) -> b -> [a] -> b
foldl' f = go where
go output [] = output
go output (x:xs) =
let new_output = f output x
in seq new_output (go new_output xs)
So we can further rewrite our count function as
count el list = foldl' f 0 list where
f output x = if x == el
then 1 + output
else output
This is good, but we can actually improve even further on this code by breaking up the count step into two parts.
count el list should be the number of times el occurs in list. We can break this computation up into two conceptual steps. First, construct the list list', which consists of all the elements in list which are equal to el. Then, compute the length of list'.
In code:
count el list = length (filter (el ==) list)
This is, in my view, the most readable version yet. And it is also just as efficient as the foldl' version of count because of laziness. Here, Haskell's length function takes care of finding the optimal way to do the counting part of count, while the filter (el ==) takes care of the part of the loop where we check whether to increment output. In general, if you're iterating over a list and have an if P x statement, you can very often replace this with a call to filter P.
We can rewrite this one more time in "point-free style" as
count el = length . filter (el ==)
which is most likely how the function would be written in a library. . refers to function composition. The meaning of this is as follows:
To apply the function count el to a list, we first filter the list to keep only the elements which el ==, and then take the length.
Incidentally, the filter function is exactly what we need to write moreThan compactly:
moreThan a list = filter occursOften list where
occursOften x = count x list >= a
Moral of the story: use higher-order functions whenever possible.
Whenever you solve a list problem in Haskell, the first tool you should reach for is functions defined in Data.List, especially map, foldl'/foldr, filter, and concatMap. Most list problems come down to map/fold/filter. These should be your go-to replacement for loops. If you're replacing a nested loop, you should use concatMap.
in a functional way, ;)
moreThan n xs = nub $ concat [ x | x <- ( group(sort(xs))), length x > n ]
... or in a fancy way, lol
moreThan n xs = map head [ x | x <- ( group(sort(xs))), length x > n ]
...
mt1 n xs = [ head x | x <- ( group(sort(xs))), length x > n ]
I'm trying to re-arrange a list based on these steps:
First move every operator (+,-,*) 1 index to the left by switching it with the element to the left.
Then find any '+' or '-' two indexes ahead of a *, and move the '+' or '-' to the index before the *.
Example
["a","-","2","*","b","+","c"]
["-","a","*","2","+","b","c"]
["-","a","+","*","2","b","c"]
I have an imperative programming background, so my initial idea was to have an iterator as an argument, and keep track of the position in the index like that, but I could not get it to work. My second idea was to embrace Haskell and use list comprehension with generators, but I struggled there as well. Any ideas or solutions are appreciated!
You can make use of explicit recursion. You can for example move elements one position to the left with:
isOperator :: String -> Bool
isOperator "+" = True
isOperator "-" = True
isOperator "*" = True
isOperator _ = False
stepOne :: [String] -> [String]
stepOne (x:xs#(o:xs'))
| isOperator o = o : x : stepOne xs'
| otherwise = x : stepOne xs
stepOne xa#[_] = xa
stepOne [] = []
Here the (x:xs#(o:xs')) pattern matches with lists with two or more elements. THe first element is x, the second is o, the remaining elements is stored in the xs' variable. xs is the tail of the "outer" cons. We check if o is an operator, if that is the case we swap with x and recurse on the tail xs'. If o is not an operator, we recurse on the tail xs'.
For the given sample data, we get:
Prelude> stepOne ["a","-","2","*","b","+","c"]
["-","a","*","2","+","b","c"]
I leave step two as an exercise.
That being said, one of the success stories of Haskell is probably parsing. Several libraries and tools exist like parsec [Hackage] and attoparsec [Hackage]. happy [haskell.org] is a compiler compiler that can construct a parser in Haskell based on a grammer. You thus do not per se need to perform infix-to-prefix conversion, but let tools do the work for you.
For my assignment, I have to take a list of tuples of people at a wedding who can't sit next to each other. Then compare it with a list of people at a table. If any two people in the same tuple are in the table list, then it should be false. Otherwise true. This is my first time coding in F# so the syntax is killing me here.
let isValidTable (cantSit:(string*string) list) (people: string list) =
let truth = true;
let rec matchPeople cantSit person1 person2=
match cantSit with
| [] -> None
| head :: tail ->
let (person1,person2) = head
if ((List.exists(fun names -> names = person1) people) && (List.exists(fun names2 -> names2 = person2) people)) then
let result2 = false
else
matchPeople tail fst snd;;
let result = true;;
matchPeople cantSit fst snd;;
let x = [("Eric", "Mark"); ("Anna", "Maya"); ("Beth", "Hope")];;
let weddingList = ["Eric"; "Anna"; "Beth"]
let validOrNah = isValidTable x weddingList;;
printf("\n%O") validOrNah;;
The problem for me is that I keep getting errors like "matchPeople constructor not defined", or "let is unfinished". Any help would be appreciated thank you!
Before: I had
if(first person is in list and second person is in list)
then Some false
else recursive statement;
This code compiled without errors but only printed null. I know variables are immutable in F#, which is making this tough.
There are many problems in your code, all caused by your unfamiliarity with F#. I'll go through it line by line and try to explain what you haven't yet understood.
let isValidTable (cantSit:(string*string) list) (people: string list) =
This is fine.
let truth = true;
There's no need for this assignment at all, since you never use the name truth anywhere else in your code. And if you did need to use it, you could just replace it with the constant true and it would read better. Let's remove this line entirely.
BTW, there's no need for semicolons at the end of lines in F#, unlike in C-like languages. The double semicolon is only used in the F# Interactive interpreter, to tell the interpreter "I'm done entering this expression". This allows you to split an expression across multiple lines, without the interpreter needing to guess when you're done (because many partial expressions in F# can look complete, so explicit expression termination is needed). I won't mention this every time a semicolon comes up, but you can remove all semicolons (and double semicolons) at the end of your lines. The only place a semicolon is needed in F# is between items in a list, such as in x or in weddingList.
On to the next line.
let rec matchPeople cantSit person1 person2=
This looks fine, but in fact, you don't need the person1 and person2 parameters at all. My guess is that you have them in the parameter list because you think you need to declare variables before you create them, but that's not how F# works at all. When you write let (person1, person2) = head later in the function, the variables person1 and person2 are created right there, and there's no need to have them as function parameters. So you can remove them, and your function definition will become let rec matchPeople cantSit =
match cantSit with
This is fine.
| [] -> None
This is a minor mistake. Elsewhere you look like you want to return a Boolean value, but here you return an option instead. In F#, all branches of match and/or if...else must return the same type. Your isValidTable function clearly is intended to return a Boolean, and so is matchPeople, so this should be a Boolean value as well. The question is, should this line return false or true? To answer that question, think about what an empty cantSit list means in the semantics of your problem domain. It would mean that there is nobody who can't sit with each other, so the seating list is valid no matter who's at the table. Or, of course, it could also mean that you've reached the end of the cantSit list by multiple recursive calls, in which case the value you return here will be the value you return finally from the last recursive call. And again, returning true is what you want, because if you had found an invalid sitting pair earlier, you would have returned false immediately and not made another recursive call. So if you get to the point where the cantSit list is empty, then you're ready to return true.
| head :: tail ->
This is fine.
let (person1,person2) = head
This is not just fine, it's quite good.
if ((List.exists(fun names -> names = person1) people) && (List.exists(fun names2 -> names2 = person2) people)) then
This is fine, but could be simplified. There's a List.contains function that does what you want here. Any call of the type List.exists (fun item -> item = value) itemList) can be simplified to List.contains item itemList. So this would become if (List.contains person1 people) && (List.contains person2 people) then, which is much easier to read and understand quickly.
let result2 = false
This is incorrect; a let assignment in F# has no value, and since it's the last expression in the if block, that means the if block would not have a value if its condition turns out to be true. This is why you're getting the "unfinished" errors: in F#, a let assignment may never be the last expression of a code block. It must always be followed by an expression that has a value. What you're actually trying to do here is pretty clear: you want to return false if both people are in the list. You can do that by just writing false in this line; I'll explain a little more here.
In F#, if...else is an expression that returns a value, not a statement like it is in most other languages. So you can write something like this:
let n = 5
let s = if n % 2 = 0 then "Even" else "Odd"
printfn "%s" s // Prints "Odd"
Here, your if...else is the last line of one case of the match expression, so its value will be the value of the match expression. And the match expression is the last expression of the matchPeople function, so its value will be the return value of the function. So in the case where you find a matching pair that can't sit together (the true branch of this if...else expression), then you just have to have a line saying false, and that will be the return value of the function if it hits that branch.
Moving on to your next line.
else
This is fine, obviously.
matchPeople tail fst snd;;
This is fine once you remove the fst and snd (since we changed our function signature so that matchPeople now takes just one argument), and remove the semicolons as mentioned previously.
let result = true;;
Same comment as for the earlier let result2 = false line: a let assignment may never be the last line of a code block in F#. Here, what you want to do is let the result of the recursive matchPeople call be the final result of your "outer" level of recursion. You can do that by simply deleting this let result = true line, so that the matchPeople call is the last line of the else block. That means that its result will be the result of the else block, and since the if...else expression is the last expression of this case of match, the recursive call will be the last expression of the match statement. And since the match statement is the last expression of the matchPeople function, its result will also be the result of the overall function (if the code reaches the else branch). That means that this recursive call is in tail position, which is an important concept later: a call is in tail position if its result will be the result of the overall function. A call in tail position is usually known as a "tail call" for short. I won't go into depth about tail calls here, except to say that a tail call can be optimized by the compiler so that it will never cause a stack overflow error, no matter how many times you go through the recursive call. For now, we'll put tail calls aside and go on to look at the rest of your code:
matchPeople cantSit fst snd;;
As with the other call, just remove the fst and snd parameters (and the double semicolon) and this will be fine.
let x = [("Eric", "Mark"); ("Anna", "Maya"); ("Beth", "Hope")];;
let weddingList = ["Eric"; "Anna"; "Beth"]
let validOrNah = isValidTable x weddingList;;
printf("\n%O") validOrNah;;
All of this is fine once you remove the unnecessary double semicolons. I'd probably write printfn "%O" validOrNah on the last line, but that's personal preference: I like to print a newline at the end of my output, rather than the beginning (printfn prints a newline after whatever you ask it to print, while printf without a trailing n in the function name does not print a trailing newline). But what you have written here is fine.
Making all those changes, here's what your code turns into:
let isValidTable (cantSit:(string*string) list) (people: string list) =
let rec matchPeople cantSit =
match cantSit with
| [] -> true
| head :: tail ->
let (person1,person2) = head
if (List.contains person1 people) && (List.contains person2 people) then
false
else
matchPeople tail
matchPeople cantSit
let x = [("Eric", "Mark"); ("Anna", "Maya"); ("Beth", "Hope")]
let weddingList = ["Eric"; "Anna"; "Beth"]
let validOrNah = isValidTable x weddingList
printfn "%O" validOrNah
I made no changes to your logic since it's correct (well done!), so once you make these syntax fixes that I suggested, this should run and print the correct results.
I've tried to write a function which returns a repeated element
findMul :: [String] -> String
findMul [] = []
findMul s
|ss!!0 == ss!!1 = ss!!0
|otherwise = findMul (tail s)
where
ss = sort s
sort :: [String] -> [String]
sort [] = []
sort (x:ys) = (sort ls) ++ [x] ++ (sort gs)
where
ls = [y | y<-ys, y<=x]
gs = [y | y<-ys, y>x ]
This seems to work when tested with the input
findMul ["d","c","b","a","a"]
which correctly returns
"a"
but when I test it with a slightly different input
findMul ["d","c","b","b","a"]
which returns the error
*** Exception: Prelude.(!!): index too large
Could anyone possibly explain what the error means? And possibly why it occurs?
Your sort function is fine; the problem lies in the definition of your findMul function. Note that the second pattern,
findMul s
is used in case list s is nonempty. In particular, it's used in case s be a singleton list (a list composed of only one element).
Moreover, lists s and ss always have the same length; therefore, if s only has one element, ss also has only one element.
However, in ss!!1, you're trying to access the second element of ss, which doesn't exist if s is a singleton list. You're essentially trying to access an element beyond the actual length (i.e. 1) of list ss! That's why Haskell is yelling at you:
*** Exception: Prelude.(!!): index too large
Your pattern matching for findMul can take a single element list
findMul ["b"]
when this happens, the ss list is also of length 1, but you are using the second element in it in the guard ss!!1.
This is the error.
Using ! for list access is often not the best idea. Use pattern matching, and things become clearer.
findMul (x:y:rest) = if x == y then y else findMul (y:rest)
findMul [x] = x -- the branch you originally missed
findMul [] = undefined -- or what you'd prefer
It also becomes obvious that you find the first repetition only. Consider going full RLE :)