How can I improve my Haskell code and make it work? - list

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.

Related

Haskell function that returns a list of elements in a list with more than given amount of occurrences

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 ]

How can I solve this Ocaml dictionary problem?

I have to write a function that has as parameters a dictionary and a character. The dictionary is string to string and you should look at it as a function. For example f("a")="b" in ("a", "b"). The function returns a max number for which f^number(character) is defined and an exception if f(character) cycles at infinity.
so if I have for eg this dictionary [("a", "b");("b", "c");("d", "e");("e", "f");("f", "e")]
my function appelead with this dictionary and charcater 'a' will give the result 2(a goes in b, b goes is c and it stops); for 'x' it will give 0 beacuse there's no such key; for 'b' the result will be 1(b goes in c and stops); for 'd' it will raise an exception(d goes in e, e goes in f, f goes in e and returns in e so infinite cycle); same exception for 'e' or 'f'
module MS = Map.Make(String);;
let d = MS.add "a" "b" (MS.add "b" "c" (MS.add "d" "e" (MS.add "e" "f" (MS.add "f" "e" MS.empty))));;
let f d c =
I just created the dictionary because I don't have any idea how could I implement this problem, but I think I need MS.Fold function for going through the dictionary.
The purpose of a fold is to "visit" all the elements of a structure, while accumulating some desired result. Your goal isn't to visit all the elements of your dictionary (which secretly is a graph). So a fold probably isn't what you want.
I'd say your main problem is in detecting cycles so you can raise an exception. To do this you need to track the places you've been. Then you raise the exception when you come to a place for the second time.
Otherwise this is a standard graph traversal problem, I'd say. You can solve it with a recursive function that visits nodes (i.e., looks up strings in the dictionary) until it gets a resolution. A resolution is a string that isn't in the dictionary, or a visit to a string that has already been visited.
Update
OK, I'll write some code that shows how to move through the dictionary. This function returns a string that is the concatenation of the first 10 strings it encounters. If it reaches a dead end before 10 it returns what it has seen so far. It uses your module MS.
let what_i_saw dict str =
let rec look sofar n s =
if n <= 0 then
sofar
else
match MS.find_opt s dict with
| None -> sofar
| Some s2 -> look (sofar ^ s2) (n - 1) s2
in
look str 9 str
Here's how it looks when you call the function:
# what_i_saw d "d";;
- : MS.key = "defefefefe"
# what_i_saw d "a";;
- : MS.key = "abc"
By the way, you say your function takes a character but your dictionary has keys that are strings. Strings and characters aren't the same thing in OCaml. I'm using strings everywhere in this example.

How can I check that the length of a list of custom data types in Haskell?

I'm making a simple sudoku program that only utilises a 9 x 9 grid. To that end, I have a function to check it is 9 x 9 and also checks to make sure the inputted values are Just Num's.
Here's the closest solution I've come to, I'm thinking the issue is in the pattern match I think (correct me if I'm wrong), this is because it compiles but has the logical error of returning False not True when given a perfectly fine test case. Anyways, here's the code dump :D
type Cell = Maybe Int
type Row = [Cell]
data Sudoku = Sudoku [Row]
deriving ( Show, Eq )
rows :: Sudoku -> [Row]
rows (Sudoku ms) = ms
isSudoku :: Sudoku -> Bool
isSudoku (Sudoku [[cs]]) = length [cs] == 9 && length cs == 9
isSudoku (Sudoku _) = False
Many thanks in advance for any advice given!
[x] as a pattern will only match a singleton list (list with exactly one element in it).
To perform the nested lists check, do
isSudokuList cs = length cs == ... &&
and [length c == ... | c <- cs]
You will have to tweak it to fit your types of course.
You could also define
niner [a,b,c,d,e,f,g,h,i] = True
.......
and use it.

Ocaml: Get a list of characters that are between two characters

to clarify my dilemma I'll explain the problem I'm faced with...
Basically, I am being passed a string that can contain single characters or ranges of characters and am trying to return back a list of characters represented by the string I was passed.
Ex. "b" would just give a list ['b'] "a-z" would give ['a' ; 'b' ; 'c' ; ... ; 'z'] and something like "ad-g2-6" would be ['a' ; 'd' ; 'e' ; 'f' ; 'g' ; '2' ; '3' ; '4' ; '5' ; '6'] since there is the character a and the ranges d-g and 2-6. (Also worth noting that something like "a-" would just be ['a' ; '-'] since the range wasn't completed.
My ideas for solving this have come to exploding the string into a list of characters (lst) then pattern matching and building onto an accumulator like
let mainfunc str = let lst = (explode str) in
let rec func lst acc = match lst with
| [] -> acc
| a::'-'::b::t -> func t (acc # **SOMETHING TO GET THIS RANGE**)
| a::t -> func t (acc # [a])
in func lst []
Anything that could help me get a range between the characters would be great and I'm open to ideas if someone has a better way to go about this problem than what I have set up.
(Also note that my explode function works as intended and converts a string into a char list)
Since you wrote a successful explode function I'll assume that you have no trouble with recursion etc. So the problem might just be a way to talk about characters as values (so you can get the next character after a given one).
For this you can use Char.code and Char.chr (from the OCaml standard library).
Here's a function that takes a character and returns a list consisting of the character and the next one in order:
let char_pair c =
[ c; Char.chr (Char.code c + 1) ]
Here's how it looks when you run it:
# char_pair 'x';;
- : char list = ['x'; 'y']
(I leave as an exercise the problem of dealing with the character with code 255.)
As a side comment, your approach looks pretty good to me. It looks like it will work.

Empty character in OCaml

I am trying to do something fairly simple. I want to take a string such as "1,000" and return the string "1000".
Here was my attempt:
String.map (function x -> if x = ',' then '' else x) "1,000";;
however I get a compiler error saying there is a syntax error wrt ''
Thanks for the insight!
Unfortunately, there's no character like the one you're looking for. There is a string that's 0 characters long (""), but there's no character that's not there at all. All characters (so to speak) are 1 character.
To solve your problem you need a more general operation than String.map. The essence of a map is that its input and output have the same shape but different contents. For strings this means that the input and output are strings of the same length.
Unless you really want to avoid imperative coding (which is actually a great thing to avoid, especially when starting out with OCaml), you would probably do best using String.iter and a buffer (from the Buffer module).
Update
The string_map_partial function given by Andreas Rossberg is pretty nice. Here's another implementation that uses String.iter and a buffer:
let string_map_partial f s =
let b = Buffer.create (String.length s) in
let addperhaps c =
match f c with
| None -> ()
| Some c' -> Buffer.add_char b c'
in
String.iter addperhaps s;
Buffer.contents b
Just an alternate implementation with different stylistic tradeoffs. Not faster, probably not slower either. It's still written imperatively (for the same reason).
What you'd need here is a function like the following, which unfortunately is not in the standard library:
(* string_map_partial : (char -> char option) -> string -> string *)
let string_map_partial f s =
let buf = String.create (String.length s) in
let j = ref 0 in
for i = 0 to String.length s - 1 do
match f s.[i] with
| None -> ()
| Some c -> buf.[!j] <- c; incr j
done;
String.sub buf 0 !j
You can then write:
string_map_partial (fun c -> if c = ',' then None else Some c) "1,000"
(Note: I chose an imperative implementation for string_map_partial, because a purely functional one would require repeated string concatenation, which is fairly expensive in OCaml.)
A purely functional version could be this one:
let string_map_partial f s =
let n = String.length s in
let rec map_str i acc =
if i < n then
map_str (i + 1) (acc ^ (f (String.make 1 s.[i])))
else acc
in map_str 0 ""
Which is terminal recursive, but less performant than the imperative version.