Ocaml printing one statement after another - ocaml

I am very new to Ocaml and ML in general and I have been having a very fundamental issue. I am using a pattern match and within one match I would like to print two or more concatenated statements. Eg.
chan^"("^var^")"^op2^(poc p); chan^"("^var^")"^op^(poc p)
let processoperatorchange2 t2s2 proc2 op op2=
let rec poc2 p = match p with
| Zero -> "0"
| Pproc (x) -> String.lowercase x
| In(chan, var, _, p, _) -> chan^"("^var^")"^op^(poc2 p); chan^"("^var^")"^op2^(poc2 p)
in poc2 proc2
But then each time I run this, the only statement printed is the last one after the semi colon. Can I get some help with this?

Your function does not print a statement but builds a string, thus it returns a value, and doesn't perform any side-effects. The semicolon operator, when interspersed between two expressions, doesn't combine the value produced from these expressions, thus if you have "hello"; "world" the result is "world". That is what happens in your case when you do
chan^"("^var^")"^op^(poc2 p); chan^"("^var^")"^op2^(poc2 p)
Everything on the lift is just thrown away.
A quick fix would be to concatenate them, e.g.,
chan^"("^var^")"^op^(poc2 p) ^ ";\n" ^ chan^"("^var^")"^op2^(poc2 p)
But in general, an idiomatic way to print AST is to use the Format module, and implement a recursive pp function, that has type Format.formatter -> 'a -> unit. Note the return type, the function doesn't build a string (that is usually an operation of quadratic complexity), but rather prints it into generic output stream.

Related

How to partially match a pattern in OCaml

I have a list lst of objects of type value where
type value = A of int | B of bool | C of string
In doing some matching on the the list, I tried to write
match lst with
| A x :: val :: tl -> ...
and got an exception saying that in the variable val a pattern was expected. I am assuming this is because in the head of the list I matched on a value variant, but for val I wanted to capture all possible next entries in the list. I can think of some ways around them, like writing several cases for the several variants of val. But since I want to do the same basic thing no matter what val is, that seems like a very inelegant solution. Is there a better solution?
Elaborating an answer based on glennsl's comment, I assume this snippet entered into the top level is reproducing the syntax error you're hitting:
since val is a reserved keyword, it is not legal to use it in pattern matches. The error is saying that the underlined token val is triggering a syntax error since it is expecting something that could be part of a pattern.
The following should compile without any problems (using some random values for example):
type value = A of int | B of bool | C of string
match [A 1; B true; C "foo"] with
| A x :: v :: tl -> Some (x, v)
| _ -> None
And this is simply due to the replacement of the keyword val with the variable v in the pattern.

Type mismatch OCaml?

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

two consecutive recursive call OCaml

I have the following function :
let extract n l =
let rec aux acc pro = function
|[] -> acc
|a::b -> if (List.length pro) = n then aux (pro::acc) [] (a::b) else aux acc (a::pro) b; aux acc (pro) b
in aux [] [] l
As you can see in my pattern matching at the second test's case I am calling two times the function. Is it possible ?
So it is possible to have this kind of function :
let rec some_function = function
| [] ->[]
| a::b -> some_function b; some_function b (*so I am calling two times the function in a single test*)
I am asking this question because here I have the following warning :
File "main.ml", line 4, characters 48-72:
Warning 10: this expression should have type unit.
So there is a problem at the exact place I called two times my recursive function.
It might be because I am using ; but in this case how could I seperate these two calls ?
Thank you !
To add onto FlorianWeimer's answer, some information about your error message.
Warning 10: this expression should have type unit.
OCaml is strongly typed. Therefore, if a function returns, say, an integer or a list, and you don't do anything with it, it'll wonder what's going on and warn you.
A function call like print_int 5; returns (), which is of type unit. That basically means that it returns nothing because you're not calling it to compute something, but to do something. It has done that thing and now it returns and you move on.
But a function call like float_of_int 5;, that returns a value (the float 5.0). You (probably) didn't call it to do something, but to compute something, and what it returns is what interests you. Same goes for arithmetic expressions like 3+6; or for straight up values like 10; or "abc"; or [];.
That's why, if you write one of these things that have a value and you don't use that value (in an assignment, or as a parameter of another function), OCaml warns you. It tells you "I computed something that I didn't assign, didn't return, and didn't use as the argument of something else. Usually, things of type unit are the only things like that. Are you sure you don't have a bug in your code?"
Sometimes you know what you're doing and you don't want that warning. In that case, you can call the ignore function. ignore will take anything and ignore it, returning (). For instance, ignore 5; or ignore (float_of_int 10); won't throw the "this expression should have type unit" warnings that you'd get with 5; or float_of_int 10;.
It is possible in the sense that the compiler accepts it, but it only makes sense if you do something with the result (or the function has a side effect). The classic example for two function calls is the recursive computation of the Fibonacci sequence:
let rec fib = function
| 0 -> 0
| 1 -> 1
| n -> fib (n - 1) + fib (n - 2)

List.iter & List.fold_right used together

I am trying to use the fold_right and List.iter functions in the List module. Is there anyway to use them in conjunction with one another?
let step nfa start transition =
let transition_list = get_transition nfa in
List.iter ( fun state ->
List.fold_right (fun ct nl ->
if ((get_pre_trans transition)= state && (get_trans ct) = transition) then
(get_post_transition transition)::nl
else
nl
) transition_list []
) start
;;
** The get_xxx functions get values from a tuple where there is a pre-transition, transition value, and post-transition.
Return error:
Error: This expression has type 'a list but an expression was expected of type unit.
Not sure what to do.
The body of the function that you pass to iter contains only one expression, a call to fold_right, that evaluates to a value of type list, but iter signature requires you to pass a function, that returns a value of type unit. That is basically what compiler tries to say to you. If you're not interested in the value to which fold_right is evaluated, then you can ignore it using ignore function, that takes a value of any type and returns a value of type unit. On the other hand, if you don't want to discard it, then you shouldn't use iter, and use fold_right or, better, fold_left.
And, finally, answering your question, yes, there're ways to combine them together, but usually, if you're applying a fold inside iter, you're doing something wrong.

Substring in Haskell

I'm supposed to split a string and return the substring that occurs before a passed character, but we're just starting Haskell, and it is like Chinese to me. I've been messing with it, but no luck.
Here's what I have so far:
--spanString returns substring of string s before char c
spanString (c, [s])::(c, [s]) -> []
spanString (c, a:b) =
let (x, y) = spanString (c, b)
in
if a < c then (a:x,y)
else (x, a:y)
What am I messing up?
First of all, your type signature is completely messed up. It must either be absent or be of the form spanString :: <some type>. Even if we ignore the (c, [s]) standing before the double colon, the rest is still something strange. One can read it as "a function taking values of type (c, [s]) to values of type [] for any c and s" (c and s are type variables). First, there is no type [] in Haskell. There is not going be a list type without its element type. Next, we can't work with any c and s. We must be able to compare them, right?
Actually, let's avoid using polymorphism for now and specify exactly which types we want. We want a character and a list of characters, packed up into a tuple for some reason: (Char, [Char]). Note that Char starts with a capital letter, which means it's not a type variable, but rather a concrete type. What about our result type? If you trust the problem description, you need to return a list of characters ([Char]), but if you look at the code, it obviously returns tuples of lists (([Char], [Char])). Okay, maybe the second list is useful, let's leave it for now:
spanString :: (Char, [Char]) -> ([Char], [Char])`
Now your code compiles.
However, when run, it crashes with exception: Non-exhaustive patterns in function spanString. This is because you don't handle the case when the passed list is empty. If you do that, by adding an equation like
spanString (_, []) = ([], [])
, your function runs well, but now let's look at what it does. It turns out you have a function for list partitioning: it returns all characters of the given string less than c as the first element of the tuple and all other characters as the second element. Seems like a bug to me (you've implemented a completely different function!).
Err, quite a lot.
First, your type declaration is wrong. Haskell uses upper case names for types, and it doesn't pass parameters in brackets like most languages do. We write
y = sin x
instead of
y = sin (x)
You probably want something like
spanString :: Char -> String -> String
Your definition of spanString is syntactically right, but still wrong. Think about it this way: if first character doesn't match then you want to spanString the rest of the string and then return the result with the first character prepended. If the first character does match then you want to return "".
Your type definition is wrong .
spanString :: Char-> String-> String
spanString _ [] = []
spanString c (x:xs) | c==x = []
| otherwise = x:spanString c xs
Just for information, utility functions like this can almost always be found in Prelude, or one of the standard libraries. In this case, takeWhile will help:
spanString :: (Char, String) -> String
spanString (c, s) = takeWhile (/= c) s
(i.e., keep taking characters while they don't equal c).
Passing arguments in a tuple is slightly odd, but if that's what's required then so be it.