Hi I'm new to f# and I got this exercise I can't figure out:
"Implement a Function :"
let compress (l : List<'a>) : List<'a> = ...
That removes consecutive occurences of the same element in l. for example compressing [a;a;a;a;b;b;c] to [a;b;c]
I'm not allowed to use the built-in functions of f# and need to do this with pattern matching.
My current code (it's not much) :
let rec compress (l: List<'a>) : List<'a> =
match l with
| [] -> l
thanks for the help!
For any recursive function you need to consider: 1. the terminal case and 2. the general case. In your scenario:
the empty list []
non-empty list x::xs (where x represents the head of the list and xs the rest aka tail)
The other important aspect to consider when you build such a functions is to assume it works for a previous value. For example in the case of factorial, we assume the function already works for a previous scenario e.g. factorial of n-1.
let fact n =
match n with
| 0 | 1 -> 1
| _ -> n * fact (n-1)
Hello i have to make exercise with list. I had one with checking arithmetic with lists code :
let rec q3 lista r =
match lista with
| [] -> false
| [x] -> true
| x1::x2::xs -> if r = x2 - x1 then (q3 xs r) else false
q3 [2;4;6] 2;;
But after this excersize i have problem. I have to calculate sum for numbers in list after last negative number
or for all if i have only positive numbers in my list.
this is code for sum . This is pretty easy but how do make this :( I am quite new in f# programming :P Any reflections ?
I have list for exmaple like this :
let lists = [4;-3;1;9]
// sum =10
//calculate
let rec sum values =
match values with
| [] -> 0
| head::tail -> head + sum(tail)
//test
let x = sum lists
I guess that you're learning F# and so I'm not going to show the full answer (then you wouldn't learn much).
You want to sum all numbers in a list after the last negative number. Another way to look at this is that you want to restart the counting (to start from zero again) every time you find a negative number as you are walking over the list.
This is not easy to do with your version of sum, but you can rewrite the sum function to use the accumulator argument (which keeps the sum of numbers so far):
let rec sumAcc acc values =
match values with
| [] ->
// return the sum of values in the list so far
| head::tail ->
// add the value in the 'head' to the sum so far
// and call 'sumAcc' recursively on the rest of the list
let sum values = sumAcc 0 values
Now, you can solve the problem quite easily - because when head is negative, you can just reset the "sum so far" in the accumulator argument. So, you just need to add another case looking like:
| head::tail when head < 0 ->
// Ignore the sum so far and call 'sumAcc' on the rest of the list
let rec sumList acc lst =
match lst with
| [] -> acc
| hd::tl -> hd + sumList acc tl
|hd::tl when hd < 0 -> sumList acc lst
let sum lst = sumList 0 lst ;;
sum [1;2;-5] ;;
Dont know how to do this //'sumAcc' recursively on the rest of the list
sumList acc lst is rather wrong :D because still get -2 value :D
I would like to build a string list by prompting the user for input. My end goal is to be able to parse a string list against a simple hash table using a simple routine.
`let list_find tbl ls =
List.iter (fun x ->
let mbr = if Hashtbl.mem tbl x then "aok" else "not found"
in
Printf.printf "%s %s\n" x mbr) ls ;;`
Building a string list is accomplished with the cons operator ::, but somehow I am not able to get the prompt to generate a string list. A simpe list function returns anything that is put into it as a list:
`let build_strlist x =
let rec aux x = match x with
| [] -> []
| hd :: tl -> hd :: aux tl
in
aux x ;;`
Thus far, I have been able to set the prompt, but building the string list did not go so well. I am inclined to think I should be using Buffer or Scanning.in_channel. This is what I have thus far:
`#load "unix.cma" ;;
let prompt () = Unix.isatty Unix.stdin && Unix.isatty Unix.stdout ;;
let build_strlist () =
let rec loop () =
let eof = ref false in
try
while not !eof do
if prompt () then print_endline "enter input ";
let line = read_line () in
if line = "-1" then eof := true
else
let rec build x = match x with
| [] -> []
| hd :: tl -> hd :: build tl
in
Printf.printf "you've entered %s\n" (List.iter (build line));
done
with End_of_file -> ()
in
loop () ;;`
I am getting an error the keyword "line" has the type string, but an expression was expected of type 'a list. Should I be building the string list using Buffer.create buf and then Buffer.add_string buf prepending [ followed by quotes " another " and a semicolon? This seems to be an overkill. Maybe I should just return a string list and ignore any attempts to "peek at what we have"? Printing will be done after checking the hash table.
I would like to have a prompt routine so that I can use ocaml for scripting and user interaction. I found some ideas on-line which allowed me to write the skeleton above.
I would probably break down the problem in several steps:
get the list of strings
process it (in your example, simply print it back)
1st step can be achieved with a recursive function as follow:
let build_strlist' () =
let rec loop l =
if prompt () then (
print_string "enter input: ";
match read_line () with
"-1" -> l
| s -> loop (s::l)
) else l
in loop [];;
See how that function loops on itself and build up the list l as it goes. As you mentioned in your comment, I dropped the imperative part of your code to keep the functional recursion only. You could have achieved the same by keeping instead the imperative part and leaving out the recursion, but recursion feels more natural to me, and if written correctly, leads to mostly the same machine code.
Once you have the list, simply apply a List.iter to it with the ad hoc printing function as you did in your original function.
How to create a function in Haskell that returns the fifth element from a list.
Something like this:
fifth [] = []!!4
Should return this:
*Main> fifth [1,2,3,20,30,40]
30
Simply use:
fifth :: [a] -> a
fifth l = l !! 4
Using fifth [] like you suggest is wrong since that will pattern match the list against the empty list — you simply want to bind a variable name to the full list so that you can use the !! function afterwards.
You can even define the function as:
fifth :: [a] -> a
fifth = (!!4)
Here we use partial application: you normally think of !! as a function taking two arguments: a list and an integer. We can provide it with one of the arguments and get a new function (fifth) that only takes a list. When we provide (!!4) with a list, it returns the fifth element:
Prelude> let fifth = (!!4)
Prelude> fifth [1,2,3,20,30,40]
30
The function is of course a partial function since it will fail for small lists:
Prelude> (!!4) [1,2,3,20]
*** Exception: Prelude.(!!): index too large
That's to be expected. If you want, you can make it safe by letting it return Maybe a instead of a::
fifth :: [a] -> Maybe a
fifth (a:b:c:d:e:rest) = Just e
fifth _ = Nothing
Here the first pattern will match lists of length 5 or more, and the second pattern matches anything not matched by the first. You use it like this:
*Main> fifth [1,2,3,20,30,40]
Just 30
*Main> fifth [1,2,3,20]
Nothing
You have now forced yourself to always pattern match the result of fifth against either Just a or Nothing. This means that when you code calls fifth someList, then it must take into account that someList might be too short. That way you can ensure at compile time that there wont be any runtime errors from this function.
I would define a safe-indexing operator !!! and then define fifth in terms of !!!.
(!!!) :: [a] -> Int -> Maybe a
xs !!! n | n < 0 = Nothing
[] !!! _ = Nothing
(x : _) !!! 0 = Just x
(_ : xs) !!! n = xs !!! (n - 1)
fifth :: [a] -> Maybe a
fifth = (!!! 4)
Another unsafe variant would be
fifth = head . drop 4
But hey, sometimes one just knows this damn list will have more than 4 elements. The type system is just not powerful enough to express it (using standard lists, that is).
I have some code which is designed to replace a value in a list
replaceNth n newVal (x:xs)
| n == 0 = newVal:xs
| otherwise = x:replaceNth (n-1) newVal xs
For example, when I load the function into GHCI, I enter and get the following:
*Main> replaceNth 3 4 [3,3,3,3,3]
[3,3,3,4,3]
However I am trying to use this function for a multiple lists within a list and can't seem to do so (e.g.).
What I want is to get a result like this:
[[3,3,3,3,3],[3,3,3,**2**,3],[3,3,3,3,3]]
From this [[3,3,3,3,3],[3,3,3,3,3],[3,3,3,3,3]]
using something like the function above.
Your function is not general enough to handle the task you wish it to preform. In particular, you need to know what the replacement value will be before you call the function. To get this working you might either:
Select the nth list, compute the new list then use your function to put that replacement in the list of lists. OR (and better)
Make a more general function that instead of taking a new value takes a function from the old value to the new:
Example
replaceNth' :: Int -> (a -> a) -> [a] -> [a]
replaceNth' n f (x:xs)
| n == 0 = (f x):xs
| otherwise = x:replace (n-1) f xs
Now to solve you second problem:
let ls = [[3,3,3,3,3],[3,3,3,3,3],[3,3,3,3,3]]
in replaceNth' 1 (replaceNth' 3 (const 2)) ls
That is replace the second list with a list made by taking the fourth element of that list and replacing what ever it is with 2.
Make a function that applies a function to the nth element of a list instead. Then you can easily get what you want by composing that with itself and using const for the inner replacement.
perhaps this does what you want (applied to the list of lists):
replaceNth 1 (replaceNth 3 4 [3,3,3,3,3])
Using your existing definition:
ghci> let arg = [[3,3,3,3,3],[3,3,3,3,3],[3,3,3,3,3]]
ghci> replaceNth 1 (replaceNth 3 2 (arg !! 1)) arg
[[3,3,3,3,3],[3,3,3,2,3],[3,3,3,3,3]]
ghci>
To refactor it into a function:
replaceMthNth m n v arg = replaceNth m (replaceNth n v (arg !! m)) arg