Stdlib.Filename.extension error: This expression has type string but an expression was expected of type int - ocaml

let get_path_elts path =
let rec walk_dir dirs =
match dirs with
| [] -> []
| dir::tail ->
match (stat dir).st_kind with
| S_REG -> if Stdlib.Filename.extension dir = "ml" || Stdlib.Filename.extension dir = "mli" then dir::(walk_dir tail) else walk_dir tail
| S_DIR -> List.concat [walk_dir (Array.to_list (Sys_unix.readdir dir)); (walk_dir tail)]
| _ -> walk_dir tail
in walk_dir [path]
;;
This is my code and I pasted it into utop. But it reports error:
Error: This expression has type string but an expression was expected of type
int
This code is originally in a file in vscode but there's no error there. Wonder why.

In core, which I know you use because of your previous question, = is defined as int -> int -> bool.
You need to use the string-specific equality operator, which you can bring into scope by locally opening String just for the predicate, for example:
String.(Stdlib.Filename.extension dir = "ml")

Related

How to construct a correct type transformation in OCaml?

In order to map from a constructed type tainted_value to other types, and from other basic types to the constructed type tainted_value, there are two functions constructed.
First, the type tainted_value is defined as:
type object_ = int
and location = Obj of object_ | Null
and closure = var * cmd * stack
and value = Fld of string | Int of int | Loc of location | Clo of closure
and tainted_value = Val of value | Error
If I just let my first function mapping from tainted_value to string look like:
let tva_to_string tva1 = match tva1 with
| Val (Fld e) -> e
| _ -> None
It reports error as:
This expression has type 'a option but an expression was expected of type string
However, it will not return error if I change None into failwith "Empty":
let tva_to_string tva1 = match tva1 with
| Val (Fld e) -> e
| _ -> failwith "Empty"
Why?
None is a constructor for the option type. If one clause in a match returns None then the others must return some other value of type option. They may also raise an exception, which is what the failwith function does.
The other constructor for option is Some, so you may be looking for:
let tva_to_string tva1 = match tva1 with
| Val (Fld e) -> Some e
| _ -> None
This will alleviate your type-checking issues. Of course, it still doesn't return a string so your naming of the function either needs some work, or you need to return strings.

Syntax error in OCaml evaluation function

I found this code to evaluate expressions in OCaml on the internet and want to try to understand how it works, but when I enter it in my editor and run it I get the following error:
type t =
| Integer of int
| Binary of binary * t * t
and binary =
| Add
| Sub
| Mult
| Div
type token =
| INTEGER of int
| ADD
| SUB
| MULT
| DIV
let rec eval = function
| Integer(k) -> k
| Binary(op, a, b) ->
(match op with
| Add -> ( + )
| Sub -> ( - )
| Mult -> ( * )
| Div -> ( / )) (eval a) (eval b)
let lexer s =
let open Str in
let split s =
let rec splitchar x l =
if x< 0 then l else splitchar (x-1) ( s.[x]:: l ) in
splitchar ( String.length s -1) []
|> List.map
(function
| "+" -> ADD
| "-" -> SUB
| "*" -> MULT
| "/" -> DIV
| _ -> failwith "lexer: Invalid token: %s" );;
Characters 280-282:
| _ -> failwith "lexer: Invalid token: %s" );;
^^
Error: Syntax error
The error message doesn't help very much and I've tried a few changes that only make things worse. Can anyone help me get started by figuring out what the syntax error is?
There is a couple of issues :
split is defined but not used.
failwith expects a string, not a format.
For the first issue : you have to use split before List.map:
...in split s | List.map...
failwith expect a string, in the current case, the mistake is that it is a string that looks more a format string that waits for another string.
The fix is as below :
- first catch the string
- then use it to form the final string expected by failwith
(function
| "+" -> ADD <br>
| "-" -> SUB <br>
| "*" -> MULT <br>
| "/" -> DIV <br>
| _ as s -> failwith ("lexer: Invalid token: " ^ s) );;
But I am not sure at all the whole code will work....

Extracting data from a tuple in OCaml

I'm trying to use the CIL library to parse C source code. I'm searching for a particular function using its name.
let cil_func = Caml.List.find (fun g ->
match g with
| GFun(f,_) when (equal f.svar.vname func) -> true
| _ -> false
) cil_file.globals in
let body g = match g with GFun(f,_) -> f.sbody in
dumpBlock defaultCilPrinter stdout 1 (body cil_func)
So I have a type GFun of fundec * location, and I'm trying to get the sbody attribute of fundec.
It seems redundant to do a second pattern match, not to mention, the compiler complains that it's not exhaustive. Is there a better way of doing this?
You can define your own function that returns just the fundec:
let rec find_fundec fname = function
| [] -> raise Not_found
| GFun (f, _) :: _ when equal (f.svar.vname fname) -> f (* ? *)
| _ :: t -> find_fundec fname t
Then your code looks more like this:
let cil_fundec = find_fundec func cil_file.globals in
dumpBlock defaultCilPrinter stdout 1 cil_fundec.sbody
For what it's worth, the line marked (* ? *) looks wrong to me. I don't see why f.svar.vname would be a function. I'm just copying your code there.
Update
Fixed an error (one I often make), sorry.

OCaml: Can't figure out the error in this snippet

I am working on an OCaml assignment and am a bit stuck. Currently this is what I have:
let rec icent (image) =
match image with
| [] -> 0.0
| imgHead::imgTail -> (centImCol(image, 1)) +. (icent(imgHead))
;;
let rec jcent (image) =
match image with
| [] -> 0.0
| imgHead::imgTail -> (centImRow(imgHead, 1)) +. (jcent(imgTail))
;;
where the centIm* functions are properly defined. The required signature for this is int list list -> float. Currently, I am only achieving error after error and can't quite get a grasp on why. Any help would be appreciated.
let rec centImRow(image, start_j) =
match image with
| imgHead::imgTail -> (sumRowCount(imgHead, start_j)) + (centImRow(imgTail, start_j+1))
| _ -> 0
;;
let rec centImCol(image, start_i) =
match image with
| imgHead::imgTail -> (sumRowCount(imgHead, start_i)) + (centImCol(imgTail, start_i+1))
| _ -> 0
;;
The first problem I see is that your recursive call to icent is applied to the head of the list. But the head of a list is not a list. But icent is supposed to work for lists.
The recursive call of a list handling function is going to be applied to the tail of the list.
I'd also expect some function to be applied to the head of the list. Otherwise nothing is going on other than the recursion itself.

How to check in the next 'head' in OCaml is empty?

I'm new at OCaml (and still a novice in learning programming in general) and I have a quick question about checking what kind of string the next element in the string list is.
I want it to put a separator between each element of the string (except for the last one), but I can't figure out how to make the program 'know' that the last element is the last element.
Here is my code as it is now:
let rec join (separator: string) (l : string list) : string =
begin match l with
| []->""
| head::head2::list-> if head2=[] then head^(join separator list) else head^separator^(join separator list)
end
let test () : bool =
(join "," ["a";"b";"c"]) = "a,b,c"
;; run_test "test_join1" test
Thanks in advance!
You're almost there. The idea is breaking down the list in three cases where it has 0, 1 or at least 2 elements. When the list has more than one element, you're safe to insert separator into the output string:
let rec join (separator: string) (l : string list) : string =
begin match l with
| [] -> ""
| head::[] -> head
| head::list-> head^separator^(join separator list)
end
I have several comments about your function:
Type annotation is redundant. Because (^) is string concatenation operator, the type checker can infer types of separator, l and the output of the function easily.
No need to use begin/and pair. Since you have only one level of pattern matching, there is no confusion to the compiler.
You could use function to eliminate match l with part.
Therefore, your code could be shortened as:
let rec join sep l =
match l with
| [] -> ""
| x::[] -> x
| x::xs -> x ^ sep ^ join sep xs
or even more concise:
let rec join sep = function
| [] -> ""
| x::[] -> x
| x::xs -> x ^ sep ^ join sep xs
The empty list is [], the list with one element is [h] and the list with at least one element is h::t. So your function can be written as:
let rec join separator = function
| [] -> ""
| [h] -> h
| h::t -> h ^ separator ^ join separator t