I have a problem, OCaml thinks the a and s parameters of my function are unit lists, but they have to be 'a list and string respectively. The function has to output the list elements separated by the given separator.
The result has to be a string, with the below input: "This-is-label"
P.S. I know about match, but I can`t use it
let rec function1 a s =
if a = [] then failwith "Empty list" else
if List.tl a = [] then List.hd a else
if List.tl a != [] then List.hd a; s; function1 List.tl a s
;;
function1 ["This"; "is"; "label"] "-";;
It seems you expect this expression to be a string:
List.hd a; s; function1 List.tl a s
However, the meaning of the ; operator is to evaluate the expression at the left and then ignore its value. (It is also considered bad form if the type isn't unit.) Then evaluate the expression at the right, which is the value of the expression.
So this expression says to evaluate List.hd a, then forget the value. Then evaluate s, then forget the value. Then evaluate the recursive call.
So the first problem is to assemble these things into a string.
The ^ operator concatenates two strings. So something like this is closer to what you want:
List.hd a ^ s ^ function1 (List.tl a) s
Note that you need to parenthesize the call to List.tl. Otherwise it looks like two separate parameters to function1.
The problem in your code are missing () around List.tl a in the recursive call. Also ^ must be used to concatenate the strings instead of ;. The code is still very un-ocaml like.
There really is no good way to do this without pattern matching. If this is a homework assignment where you aren't allowed to use pattern matching then please give your instructor a big kick in the behind.
The order of arguments also would be better the other way around, have the separator as first argument. That way you can bind the function to a separator and reuse it many times.
Two alternative implementations:
let rec join s = function
| [] -> "" (* or failwith "Empty list" if you insist *)
| [x] -> x
| x::xs -> x ^ s ^ join s xs
let join s a =
let (res, _) =
List.fold_left
(fun (acc, sep) x -> (x ^ sep ^ acc, s))
("", "")
a
in
res
Related
I am a beginner in OCaml. I am curious to know how, syntactically speaking, call two functions, or more, within a match expression. Or is that possible at all?
For example :
let rec foo l:list =
match l with
| [x,y] -> (foo1 x) (foo2 y)
| _ -> doSome
I have tried using the ; operator but that seems to be used for something else. I have tried different combinations of bracketing but in all cases I get
This is not a function it cannot be applied under foo1 x.
You just need a semicolon (no begin/end). You don't need the parentheses (they don't hurt but they're not especially idiomatic OCaml).
let rec foo l : 'a list = match l with
| [x,y] -> foo1 x; foo2 y
| _ -> doSome
I am to use combinators and no for/while loops, recursion or defined library functions from F#'s List module, except constructors :: and []
Ideally I want to implement map
I am trying to write a function called llength that returns the list of the lengths of the sublists. For example llength [[1;2;3];[1;2];[1;2;3]] should return [3;2,3]. I also have function length that returns the length of a list.
let Tuple f = fun a b -> f (a, b)
let length l : int =
List.fold (Tuple (fst >> (+) 1)) 0 l
currently have
let llength l : int list =
List.map (length inner list) list
Not sure how I should try accessing my sublists with my restraints and should I use my other method on each sublist? any help is greatly appreciated, thanks!
Since this is homework, I don't want to just give you a fully coded solution, but here are some hints:
First, since fold is allowed you could implement map via fold. The folding function would take the list accumulated "so far" and prepend the next element transformed with mapping function. The result will come out reversed though (fold traverses forward, but you prepend at every step), so perhaps that wouldn't work for you if you're not allowed List.rev.
Second - the most obvious, fundamental way: naked recursion. Here's the way to think about it: (1) when the argument is an empty list, result should be an empty list; (2) when the argument is a non-empty list, the result should be length of the argument's head prepended to the list of lengths of the argument's tail, which can be calculated recursively. Try to write that down in F#, and there will be your solution.
Since you can use some functions that basically have a loop (fold, filter ...), there might be some "cheated & dirty" ways to implement map. For example, via filter:
let mymap f xs =
let mutable result = []
xs
|> List.filter (fun x ->
result <- f x :: result
true)
|> ignore
result |> List.rev
Note that List.rev is required as explained in the other answer.
I am writing an OCaml function that accepts a function type, such as (fun _ -> true) and a list. This is what I currently have:
let drop_until_boolean (x: 'a -> bool) lst =
match lst with
| x -> true
Currently that written statement does not work properly, as it always evaluates to true.
When I call drop_until_boolean (fun _ -> true) [] I want it to return true, and when I call drop_until_boolean (fun _ -> true) ["a"] I want it to return false.
Question Summary: How do I make a function such that drop_until_boolean (fun _ -> true) [] evaluates to true.
Another example: drop_until_boolean (fun s -> s.[0]='z') ["z"] evaluates to true and drop_until_boolean (fun s -> s.[0]='z') ["y"] evaluates to false.
I managed to figure out what I wanted to do, probably did a terrible job explaining it. This is what I wanted.
let drop_until_boolean (x: 'a -> bool) lst = if (x lst) then true else false
Your current function says the following in English:
Take a function, call it x, and a second value of any type. Examine the second value. In all cases, no matter what the value, return true.
The variable x that appears in your match is a new variable that is matched against the second argument. Since it's just a simple variable, it always matches successfully. It has no relationship to the first parameter (which happens to be named x also).
It shouldn't be surprising that this function always returns true.
I'm not at all sure what you want the function to do. The name suggests it will return some trailing portion of the list that you give it. But you seem to be saying that it should return a boolean.
Let's assume that you want to do something reasonably simple with the second argument. You say the second argument is a list. The most common structure for a simple list-processing function is like this:
let rec my_function list =
match list with
| [] ->
(* Handle case of empty list *)
| head :: rest ->
(* Handle case of non-empty list,
probably with recursive call *)
Maybe you could think about this general structure as a possible solution to your problem. I hope it is helpful.
I try to define function with the following protocol:
[(1,2), (6,5), (9,10)] -> [3, 11, 19]
Here is what I have now:
fun sum_pairs (l : (int * int) list) =
if null l
then []
else (#1 hd(l)) + (#2 hd(l))::sum_pairs(tl(l))
According to type checker I have some type mismatch, but I can't figure out where exactly I'm wrong.
This code runs in PolyML 5.2:
fun sum_pairs (l : (int * int) list) =
if null l
then []
else ((#1 (hd l)) + (#2 (hd l))) :: sum_pairs(tl l)
(* ------------^-------------^ *)
The difference from yours is subtle, but significant: (#1 hd(l)) is different from (#1 (hd l)); the former doesn't do what you think - it attempts to extract the first tuple field of hd, which is a function!
While we're at it, why don't we attempt to rewrite the function to make it a bit more idiomatic? For starters, we can eliminate the if expression and the clunky tuple extraction by matching on the argument in the function head, like so:
fun sum_pairs [] = []
| sum_pairs ((a, b)::rest) = (a + b)::sum_pairs(rest)
We've split the function into two clauses, the first one matching the empty list (the recursive base case), and the second one matching a nonempty list. As you can see, this significantly simplified the function and, in my opinion, made it considerably easier to read.
As it turns out, applying a function to the elements of a list to generate a new list is an incredibly common pattern. The basis library provides a builtin function called map to aid us in this task:
fun sum_pairs l = map (fn (a, b) => a + b) l
Here I'm using an anonymous function to add the pairs together. But we can do even better! By exploiting currying we can simply define the function as:
val sum_pairs = map (fn (a, b) => a + b)
The function map is curried so that applying it to a function returns a new function that accepts a list - in this case, a list of integer pairs.
But wait a minute! It looks like this anonymous function is just applying the addition operator to its arguments! Indeed it is. Let's get rid of that too:
val sum_pairs = map op+
Here, op+ denotes a builtin function that applies the addition operator, much like our function literal (above) did.
Edit: Answers to the follow-up questions:
What about arguments types. It looks like you've completely eliminate argument list in the function definition (header). Is it true or I've missed something?
Usually the compiler is able to infer the types from context. For instance, given the following function:
fun add (a, b) = a + b
The compiler can easily infer the type int * int -> int, as the arguments are involved in an addition (if you want real, you have to say so).
Could you explain what is happening here sum_pairs ((a, b)::rest) = (a + b)::sum_pairs(rest). Sorry for may be dummy question, but I just want to fully understand it. Especially what = means in this context and what order of evaluation of this expression?
Here we're defining a function in two clauses. The first clause, sum_pairs [] = [], matches an empty list and returns an empty list. The second one, sum_pairs ((a, b)::rest) = ..., matches a list beginning with a pair. When you're new to functional programming, this might look like magic. But to illustrate what's going on, we could rewrite the clausal definition using case, as follows:
fun sum_pairs l =
case l of
[] => []
| ((a, b)::rest) => (a + b)::sum_pairs(rest)
The clauses will be tried in order, until one matches. If no clause matches, a Match expression is raised. For example, if you omitted the first clause, the function would always fail because l will eventually be the empty list (either it's empty from the beginning, or we've recursed all the way to the end).
As for the equals sign, it means the same thing as in any other function definition. It separates the arguments of the function from the function body. As for evaluation order, the most important observation is that sum_pairs(rest) must happen before the cons (::), so the function is not tail recursive.
What doesx :: xs' mean?
I dont have much functional experience but IIRC in F# 1 :: 2 :: 3 :: [];; creates an array of [1,2,3]
so what does the ' do?
let rec sum xs =
match xs with
| [] -> 0
| x :: xs' -> x + sum xs'
I think sepp2k already answered most of the question, but I'd like to add a couple of points that may clarify how F#/OCaml compiler interprets the code and explain some common uses.
Regarding the ' symbol - this is just a part of a name (a valid identifier starts with a letter and then contains one or more letters, numbers or ' symbols). It is usually used if you have a function or value that is very similar to some other, but is in some way new or modified.
In your example, xs is a list that should be summed and the pattern matching decomposes the list and gives you a new list (without the first element) that you need to sum, so it is called xs'
Another frequent use is when declaring a local utility function that implements the functionality and takes an additional parameter (typically, when writing tail-recursive code):
let sum list =
let rec sum' list res =
match list with
| [] -> res
| x::xs -> sum' xs (res + x)
sum' list 0
However, I think there is usually a better name for the function/value, so I try to avoid using ' when writing code (I think it isn't particularly readable and moreover, it doesn't colorize correctly on StackOverflow!)
Regarding the :: symbol - as already mentioned, it is used to create lists from a single element and a list (1::[2;3] creates a list [1;2;3]). It is however worth noting that the symbol can be used in two different ways and it is also interpreted in two different ways by the compiler.
When creating a list, you use it as an operator that constructs a list (just like when you use + to add two numbers). However, when you use it in the match construct, it is used as a pattern, which is a different syntactic category - the pattern is used to decompose the list into an element and the remainder and it succeeds for any non-empty list:
// operator
let x = 0
let xs = [1;2;3]
let list = x::xs
// pattern
match list with
| y::ys -> // ...
The ' is simply part of the variable name. And yes foo :: bar, where foo is an element of type a and bar is a list of type a, means "the list that has foo as its first element, followed by the elements of bar". So the meaning of the match statement is:
If xs is the empty list, the value is 0. If xs is the list containing the item x followed by the items in xs' the value is x + sum xs'. Since x and xs' are fresh variables, this has the effect that for any non empty list, x will be assigned the value of the first element and xs' will be assigned the list containing all other elements.
Like others have said, the ' is a carryover from mathematics where x' would be said as "x prime"
It's idiomatic in ML-family languages to name a variable foo' to indicate that it's somewhat related to another variable foo, especially in recursions like your code sample. Just like in imperative languages you use i, j for loop indices. This naming convention may be a little surprising since ' is typically an illegal symbol for identifiers in C-like languages.
What does x :: xs' mean?
If you have two variables called x and xs' then x :: xs' creates a new list with x prepended onto the front of xs'.
I dont have much functional experience but IIRC in F# 1 :: 2 :: 3 :: [];; creates an array of [1,2,3]
Not quite. It's a list.
so what does the ' do?
It is treated as an alphabetical character, so the following is equivalent:
let rec sum xs =
match xs with
| [] -> 0
| x :: ys -> x + sum ys
Note that :: is technically a type constructor which is why you can use it in both patterns and expressions.