I am actually stuck in adding a tuple in a list of tuple.
Here is my code.
let rec start_of_pattern = fun c index acc patterns n -> match patterns with
| [] -> acc
| h::t -> start_of_pattern c index [(Char.escaped c, index, h, n)]#acc t (n+1)
I tried also this:
let rec start_of_pattern = fun c index acc patterns n -> match patterns with
| [] -> acc
| h::t -> start_of_pattern c index (Char.escaped c, index, h, n)::acc t (n+1)
I want to add to "acc" a tuple of 4 elements (string, int, string, int). c is a char, index a int, acc normally tuple list, patterns a string list and n a int.
I have this error:
first version
second version
I hope u guys can help me. Thank you for reading!
Function application in OCaml has high precedence. So this expression:
f x#y z
Is parsed like this:
(f x) # (y z)
Looking at your first attempt, it seems to me you need to parenthesize like this:
start_of_pattern c index ([(Char.escaped c, index, h, n)]#acc) t (n+1)
I won't swear that this will fix all your problems. But without these parentheses, it looks like acc is being called as a function.
Related
I have a homework practice problem and I am new to F# and the syntax is so confusing, I do not know where to start
For example, If I have a list of tuples of increasing values :
let tupleList = [(1,2,3);(10,12,15);(9,10,20)]
I should write a function that returns a tuple that has the largest middle value.
So the function should return :
(10,12,15)
Any hints on what should I consider, read on the Internet, or research, or any other tips to help me learn how to do this is appreciated!
Thank you!
You should probably read a book on F# or work through https://fsharpforfunandprofit.com/
You can use List.max or List.maxBy to get the maximum in a list. Because you have a three element tuple, you will need to deconstruct it (as there is no function to access the nth element of a tuple, only the first or the second one). Once you exposed the middle value you can run maxby on it, and get rid of the unnecessary parts.
let tupleList = [(1,2,3);(10,12,15);(9,10,20)]
tupleList
|> List.map (fun (a,b,c) -> (b, (a,b,c)))
|> List.maxBy fst
|> snd
val it : int * int * int = (10, 12, 15)
If none of built-in function can be used, then you can use either (1) mutable variables and while loop or (2) recursion.
Since you are learning functional programming, it is very likely that your professor will prefer recursion. Here is the solution:
let max2 (a,b,c) (x,y,z) = if b > y then (a,b,c) else (x,y,z)
let maxMany tuples =
let rec loop currentMaxTuple remainTuples =
match remainTuples with
| [] -> currentMaxTuple
| tuple :: rest ->
let newMaxTuple = max2 currentMaxTuple tuple
loop newMaxTuple rest
match tuples with
| [] -> None
| head :: rest -> Some (loop head rest)
let tupleList = [(1,2,3);(10,12,15);(9,10,20)]
maxMany tupleList |> printfn "%A"
Slightly different from #Nghia Bui's solution, you can use pattern matching to compare tuples items.
let maxSnd tuples =
let rec loop list tuple =
match list, tuple with
| [], _ -> tuple
| (x, y, z) :: xs, (a, b, c) ->
if y < b then (a, b, c) else (x, y, z)
|> loop xs
match tuples with
| [] -> invalidArg "tuples" "Empty list"; 0, 0, 0
| x :: xs -> loop xs x
A little late but anyway:
let maxByMiddle data =
let rec find lst =
match lst with
| [] -> Error("No entries in list")
| [a, b, c] -> Ok(a, b, c)
| (_, bmax, _)::(a, b, c)::tail when b > bmax -> find ((a, b, c)::tail)
| maxima::_::tail -> find (maxima::tail)
find data
This is just an exercise (I realize that the functions mentioned below are already implemented in List).
Suppose that I have an interface that includes the following lines
val length : 'a list -> int
val fold : init:'acc -> f:('acc -> 'a -> 'acc) -> 'a list -> 'acc
...and that I implement fold like this:
let rec fold ~init ~f l =
match l with
| [] -> init
| h :: t -> fold ~init:(f init h) ~f:f t
I expected to now be able to implement length like this
let length = fold ~init:0 ~f:(fun c _ -> (c + 1))
...but the compiler complains with
Values do not match:
val length : '_a list -> int
is not included in
val length : 'a list -> int
Of course, I know that I can implement length like this
let length l = fold ~init:0 ~f:(fun c _ -> (c + 1)) l
...but I don't understand why I can't remove the trailing l from both sides of the =.
Where am I going wrong?
This is the value restriction. Your definition of length is not a value in a very technical sense. There are some good discussions of the issue already here on Stack Overflow. I'll look for a good one.
Here is a pretty good one:
Why does a partial application have value restriction?
I am new to Haskell and functional programming in general. I am trying to implement a function to take a list like this
["abc", "def", "ghi"]
and want to be able to replace the xth character in the yth element for example
replaceChar 1 2 'd' arr
would produce
["abc", "ded", "ghi"]
So essentially the first parameter is the element and the second is the position of the string, the third is the character and last is the [String].
The signature of this function looks like this:
replaceChar :: Int -> Int -> Char -> [String] -> [String]
Any help would be appreciated. Thanks!
First a note: while your signature is perfectly fine, you really don't use the fact that you're dealing with character strings, it could just as well be lists of any other type. It's usually a good idea1 to manifest that in your signature by using a completely generic type variable (lowercase letter) instead of Char:
replaceAtXY :: Int -> Int -> a -> [[a]] -> [[a]]
Next, note that basically the problem can be reduced to modifying the n-th element of an ordinary (non-nested) lists. On the outer list, you modify the y-th sublist, namely, in that sublist you modify the x-th element.
So what does "modifying" mean in Haskell? We can't mutate elements of course2. We need a function that takes a list and returns another one, and does this based on a function which operates on single elements of the list.
modifyNth :: Int -> (a->a) -> [a]->[a]
Observe that this is somewhat similar to the standard function map :: (a->b) -> [a]->[b].
Once you have that function, you can easily implement
modifyXY :: Int -> Int -> (a->a) -> [[a]]->[[a]]
modifyXY x y f nList = modifyNth y (modifyNth x f) nList
(BTW the nList parameter doesn't need to be written, you can η-reduce it).
1As to why this is a good idea: obviously, it allows you to use the function in more general settings. But more importantly, it gives the type checker extra information that you won't do anything with the contained elements themselves. This actually helps to catch a lot of bugs in more complicated applications!
2Actually you can, even with rather nice semantics, in the ST monad.
Let's break this problem into two functions, one that replaces an element in a string with a new char, and one that does this for a list of strings.
I would recommend something like:
replaceCharInStr :: Int -> Char -> String -> String
replaceCharInStr 0 c (s:ss) = c:ss
replaceCharInStr n c (s:ss) = s : ???
replaceCharInStr n c [] = error "replaceCharInStr: Empty string"
here we say that if n is 0, ignore the first element of the string with c, then if n is not 0 and the list has at least one element, prepend that element in front of something (exercise left to reader. Hint: recursion), then if our string is empty, raise an error. I will say that I don't particularly like that error is used here, it would be much better to return a Maybe String, or we could say that replaceCharInStr n c [] = [c]. We could also change the type signature to replaceCharInStr :: Int -> a -> [a] -> [a], since this isn't specific to strings.
For the next function, what we'd like to do is take an index, and apply a function at that index. In general, this function would have type
applyAt :: Int -> (a -> a) -> [a] -> [a]
And could be implemented similarly to replaceCharInStr with
applyAt :: Int -> (a -> a) -> [a] -> [a]
applyAt 0 f (x:xs) = f x : xs
applyAt n c (x:xs) = x : ???
applyAt n c [] = error "applyAt: Empty list"
In fact, this is the exact same shape as replaceCharInStr, so if you get this one implemented, then you should be able to implement replaceCharInStr in terms of applyAt as
replaceCharInStr n c xs = applyAt n (\x -> c) xs
-- Or = applyAt n (const c) xs
Then your replaceChar function could be implemented as
replaceChar :: Int -> Int -> Char -> [String] -> [String]
replaceChar n m c strings = applyAt n (replaceCharInStr m c) strings
-- Or = applyAt n (applyAt m (const c)) strings
All that's left is to implement applyAt.
If you have Edward Kmett's Lens package, then your example is a one-liner:
import Control.Lens
["abc", "def", "ghi"] & ix 1 . ix 2 .~ 'd'
returns
["abc","ded","ghi"]
Lens can emulate the indexing and property access you'd expect from an imperative language, but in Haskell. If you're just beginning to learn Haskell, you should probably wait a bit before using Lens. It's clever and powerful but it's also large and complex.
Try this:
replace n 0 c (x:xs) = (replace' n c x) : xs
replace n m c (x:xs) = x : (replace n (m-1) c xs)
where
replace' 0 c (x:xs) = c : xs
replace' n c (x:xs) = x : (replace' (n-1) c xs)
Here you just traverse the list until the corresponding index is 0 and we replace the character in the matches list. We use the same principle for replacing the charachter in the list. We traverse it and when we reach the specified index, we replace the character at that index by our new one.
In the end, everything gets consed bak on each other to replace the old structure, this time with the character replaced.
With a list of integers such as:
[1;2;3;4;5;6;7;8;9]
How can I create a list of list of ints from the above, with all new lists the same specified length?
For example, I need to go from:
[1;2;3;4;5;6;7;8;9] to [[1;2;3];[4;5;6];[7;8;9]]
with the number to split being 3?
Thanks for your time.
So what you actually want is a function of type
val split : int list -> int -> int list list
that takes a list of integers and a sub-list-size. How about one that is even more general?
val split : 'a list -> int -> 'a list list
Here comes the implementation:
let split xs size =
let (_, r, rs) =
(* fold over the list, keeping track of how many elements are still
missing in the current list (csize), the current list (ys) and
the result list (zss) *)
List.fold_left (fun (csize, ys, zss) elt ->
(* if target size is 0, add the current list to the target list and
start a new empty current list of target-size size *)
if csize = 0 then (size - 1, [elt], zss # [ys])
(* otherwise decrement the target size and append the current element
elt to the current list ys *)
else (csize - 1, ys # [elt], zss))
(* start the accumulator with target-size=size, an empty current list and
an empty target-list *)
(size, [], []) xs
in
(* add the "left-overs" to the back of the target-list *)
rs # [r]
Please let me know if you get extra points for this! ;)
The code you give is a way to remove a given number of elements from the front of a list. One way to proceed might be to leave this function as it is (maybe clean it up a little) and use an outer function to process the whole list. For this to work easily, your function might also want to return the remainder of the list (so the outer function can easily tell what still needs to be segmented).
It seems, though, that you want to solve the problem with a single function. If so, the main thing I see that's missing is an accumulator for the pieces you've already snipped off. And you also can't quit when you reach your count, you have to remember the piece you just snipped off, and then process the rest of the list the same way.
If I were solving this myself, I'd try to generalize the problem so that the recursive call could help out in all cases. Something that might work is to allow the first piece to be shorter than the rest. That way you can write it as a single function, with no accumulators
(just recursive calls).
I would probably do it this way:
let split lst n =
let rec parti n acc xs =
match xs with
| [] -> (List.rev acc, [])
| _::_ when n = 0 -> (List.rev acc, xs)
| x::xs -> parti (pred n) (x::acc) xs
in let rec concat acc = function
| [] -> List.rev acc
| xs -> let (part, rest) = parti n [] xs in concat (part::acc) rest
in concat [] lst
Note that we are being lenient if n doesn't divide List.length lst evenly.
Example:
split [1;2;3;4;5] 2 gives [[1;2];[3;4];[5]]
Final note: the code is very verbose because the OCaml standard lib is very bare bones :/ With a different lib I'm sure this could be made much more concise.
let rec split n xs =
let rec take k xs ys = match k, xs with
| 0, _ -> List.rev ys :: split n xs
| _, [] -> if ys = [] then [] else [ys]
| _, x::xs' -> take (k - 1) xs' (x::ys)
in take n xs []
I am working on a project with OCaml and there are some problems regarding to arrays that I am not sure with. I am not allowed to use the List module, so please give me some idea or suggestion with my works.
First, I already implemented a function 'a list -> 'a list called uniq that return a list of the uniq elements in an array, for example uniq [5;6;5;4] => [6;5;4]
Here is my implementation:
let rec uniq x =
let rec uniq_help l n =
match l with
[] -> []
| h :: t -> uniq_help t, n if (n = h) else (h :: (uniq_help(t, n)))
match x with
[] -> []
| h::t -> uniq_help t, h
;;
I mot sure this is a correct implementation, can someone give me some suggestion or correctness?
You functions are syntactically incorrect for various reasons:
uniq_help takes two elements so you have to invoke it using uniq_help t n, not uniq_help(t, n) and the like.
an if/else expression should have the form of if cond then expr1 else expr2.
to use uniq_help locally in uniq, you need an in keyword.
After fixing syntax errors, your function looks like:
let rec uniq x =
let rec uniq_help l n =
match l with
| [] -> []
| h :: t -> if n = h then uniq_help t n else h::(uniq_help t n) in
match x with
| [] -> []
| h::t -> uniq_help t h
However, to be sure that each element is unique in the list, you have to check uniqueness for all of its elements. One quick fix could be:
let rec uniq x =
(* uniq_help is the same as above *)
match x with
| [] -> []
| h::t -> h::(uniq_help (uniq t) h)