What is problematic about below ocaml code? - functional-programming

let rec funli li k = match li with
| [x] -> if k==1 then Some(x) else None
| x::ll -> funli ll k-1;;
utop shows
Error: This expression has type 'a option but an expression was expected of type int
I see no reason for it to expect int. Please help me understand what is happening in this code. I am new to OCaml.

There are a few problems with your code. First, you want to be explicit that k-1 is a parameter and that you're not trying to return (funli ll k)-1, which is what OCaml is interpreting that arm as. Additionally, == is not used to test equality in OCaml. This will work fine
let rec funli li k = match li with
| [x] -> if k=1 then Some(x) else None
| x::ll -> funli ll (k-1);;

funli ll k-1 is parsed as (funli ll k)-1. So you're trying to subtract one from an option, leading to the error you got.
What you want is funli ll (k-1).

Related

F# define search function

I am new to F# and am having trouble with my code. Its a simple problem to define a function, search, with that take a boolean function and a list and return an index. So for example:
> search (fun x -> x > 10) [ 2; 12; 3; 23; 62; 8; 2 ];;
val it : int = 1
> search (fun s -> s < "horse") [ "pig"; "lion"; "horse"; "cow"; "turkey" ];;
val it : int = 3
What I have as of right now finds the right match but what I cant figure out is how to return a number instead of the rest of the list. I know I'm getting the list instead of a value back because I wrote "if f head then list". What I don't know is what I should put there instead or if what I have is not going to get the result I want.
Below is the code I have written.
let rec search f list =
match list with
| [] -> [-1]
| head::tail ->
if f head then list
else search f tail
Returning a number is easy, you just... return it. Your problem is that you don't have a number to return, because you can't derive it directly from the current state. You have to keep track of the number yourself, using some internal state variable.
When using recursion you change state by calling your function recursively with "modified" arguments. You're already doing that with the list here. To keep internal state in a recursive function you have to introduce another argument, but not expose it outside. You can solve that by using an internal recursive helper function. Here's one that keeps track of the previous item and returns that when it encounters a match:
let search f list =
let rec loop list prev =
match list with
| [] -> None
| head::tail ->
if f head then prev
else loop tail (Some head)
in
loop list None
That's a silly example, but I don't want to just solve your homework for you, because then you wouldn't learn anything. Using this you should be able to figure out how to keep a counter of which position the current item is in, and return that when it matches. Good luck!
You typically define an inner recursive function to help you carry state as you loop, and then call the inner function with an initial state.
let search predicate list =
let rec loop list index =
match list with
| [] -> -1
| head::tail ->
if predicate head then index
else loop tail (index + 1)
loop list 0

expression has type 'a list -> 'b list but an expression was expected of type 'b list

This is my function
let rec helper inputList = function
| [] -> []
| a :: b :: hd ->
if a = b then helper ([b::hd])
else a :: helper (b::hd)
It's not complete, however I can't see why I keep getting the error in the title at helper ([b::hd]). I've tried helper (b::hd) or helper (b::hd::[]) however all come up with errors. How do I make it so that it works?
When you use function you are supplying a pattern for the parameter of the function. But you already have a parameter named inputList. So this function helper is expecting two parameters (but it ignores the first).
You can fix this by removing inputList.
You also have a problem in your first recursive call to helper. Your expression [b :: hd] is a list of lists. I suspect that you want something more like just b :: hd here.
There is at least one other problem, but I hope this helps get you started.
There are multiple errors here. One is that the keyword function means we have an implicit parameter over which we are working. So the pattern matching happens on that "invisible" parameter. But here you defined probably the explicit one: inputList. So we can remove that one:
let rec helper = function
| [] -> []
| a :: b :: hd -> if a = b then helper ([b::hd]) else a :: helper (b:: hd)
Next there is a problem with the types: in the recursion, you use:
helper ([b::hd]); and
a :: helper (b:: hd)
But you put these on the same line, and that makes no sense, since the first one passes a list of lists of elements, and the second a list of elements. So the result of the first one would be a list of list of elements, and the second one a list of elements. It does not make sense to merge these.
If I understood correctly that you want to ensure that no two consecutive elements should occur that are equal, then we should rewrite it to:
let rec helper = function
| [] -> []
| a :: b :: hd -> if a = b then helper (b::hd) else a :: helper (b:: hd)
You have defined two patterns here:
one for the empty list; and
one for a list with at least two elements.
The second one will perform recursion on the tail of the list b :: hd. So that means that eventually when we pass it a list with n elements, it will recursively work on a list with n-1 elements, n-2 elements, etc. But eventually it will have one element. And there is no case for that. So we need to add a case for the one element pattern:
let rec helper = function
| [] -> []
| h :: [] -> h :: []
| a :: b :: hd -> if a = b then helper (b::hd) else a :: helper (b:: hd)

Why am I getting an error in first case but not in second?

I started learning OCaml recently and came across the following problem:
*Write a function last : 'a list -> 'a option that returns the last element of a list. *
I tried the following code:
# let rec last = function
| [] -> None
| _ :: t -> last t
| [x] -> Some x;;
I got the following response:
Characters 65-68:
Warning 11: this match case is unused.
val last : 'a list -> 'a option = <fun>
But the following code compiles without an error:
# let rec last = function
| [] -> None
| [x] -> Some x
| _ :: t -> last t;;
giving the response
val last : 'a list -> 'a option = <fun>
So, my doubt is why just by changing the order I am getting the error?
Any remarks and guidance will be highly appreciated.
I asked this question on programmers.stackexchange As per suggestion I am asking on overflow.
in this line,
| _ :: t -> last t
what is t? it's a list!. That means it could either be a cons cell of (a :: a list), or it could be []. Since this case, along with the first, now match every possible list, the third case cannot be reached.

How to convert a string to integer list in ocaml?

I need to pass two list as command line arguments in ocaml.
I used the following code to access it in the program.
let list1=Sys.argv.(1);;
let list2=Sys.argv.(2);;
I need to have the list1 and list2 as list of integers.
I am getting the error
This expression has type string but an expression was expected of type
int list
while processing.
How can I convert that arguments to a list of integers.
The arguments are passed in this format [1;2;3;4] [1;5;6;7]
Sys.argv.(n) will always be a string. You need to parse the string into a list of integers. You could try something like this:
$ ocaml
OCaml version 4.01.0
# #load "str.cma";;
# List.map int_of_string (Str.split (Str.regexp "[^0-9]+") "[1;5;6;7]");;
- : int list = [1; 5; 6; 7]
Of course this doesn't check the input for correct form. It just pulls out sequences of digits by brute force. To do better you need to do some real lexical analysis and simple parsing.
(Maybe this is obvious, but you could also test your function in the toplevel (the OCaml read-eval-print loop). The toplevel will handle the work of making a list from what you type in.)
As Sys.argv is a string array, you need to write your own transcription function.
I guess the simplest way to do this is to use the Genlex module provided by the standard library.
let lexer = Genlex.make_lexer ["["; ";"; "]"; ]
let list_of_string s =
let open Genlex in
let open Stream in
let stream = lexer (of_string s) in
let fail () = failwith "Malformed string" in
let rec aux acc =
match next stream with
| Int i ->
( match next stream with
| Kwd ";" -> aux (i::acc)
| Kwd "]" -> i::acc
| _ -> fail () )
| Kwd "]" -> acc
| _ -> fail ()
in
try
match next stream with
| Kwd "[" -> List.rev (aux [])
| _ -> fail ()
with Stream.Failure -> fail ()
let list1 = list_of_string Sys.argv.(1)
let list2 = list_of_string Sys.argv.(2)
Depending on the OCaml flavor you want to use, some other library may look more interesting. If you like yacc, Menhir may solve your problem in a few lines of code.

OCaml - Traversing a list without recursion

I'm trying to write following code without recursion:
let rec traverse lst =
match lst with
| a::b::t ->
(* Something that return None*)
traverse (b::t)
| _ -> ()
How to do it in imperative way ?
In an imperative way:
let traverse li =
let state = ref li in
while !state <> [] do
let x = List.hd !state in
state := List.tl !state;
(* do whatever you want *)
done
If you need to access the second element of the list, just use the appropriate List.hd call. But you may need to check that the list isn't empty first.
I see no reason to do that this way, which is heavier, less efficient and less flexible than a recursive loop.

Resources