Matching two files in OCaml - exception

I am trying to check to see whether some two files are the same and wrote the following code.
let print_test_success input1 input2 =
let ic1, ic2 = open_in input1, open_in input2 in
let rec loop i1 i2 =
match (input_line i1, input_line i2) with
| string1, string2 -> if String.trim string1 = (String.trim string2)
then loop i1 i2
else print_endline "Failed with line from file1:";
print_endline string1;
print_endline " and from line 2:";
print_endline string2
| exception End_of_file, exception End_of_file -> print_endline "Passed"
| s, exception End_of_file -> if String.trim s = ""
then loop i1 i2
else print_endline "Failed"
| exception End_of_file, s -> if String.trim s = ""
then loop i1 i2
else print_endline "Failed"
in loop ic1 ic2
;;
This sort of structure worked when I had a single input channel, but now when matching on two input channels simultaneously, it throws the exception Error: Exception patterns are not allowed in this position. Is there a way around this? I've seen other ways of reading through a file that involve using try ... with ... but if possible I'd prefer to solve this with simple matching on input_line ...

If you wrap input_line in a function that converts the exception and return value into an option, you can pattern match on that:
let input_line_opt ch =
try Some input_line ch with
| End_of_file -> None
...
match (input_line_opt i1, input_line_opt i2) with
| Some string1, Some string2 -> ...
| None, None -> ...
| Some s, None -> ...
| None, Some s -> ...

Related

F# error FS0588: The block following this 'let' is unfinished. Every code block is an expression and must have a result

I am tasked with finishing an interpreter in F#, but I'm having some trouble, as I im getting the error: error FS0588: The block following this 'let' is unfinished. Every code block is an expression and must have a result. 'let' cannot be the final code element in a block. Consider giving this block an explicit result.
Its been a long time since last time I programmed I F#.
The following is my code. I have a helper function inside my eval function, called OperateAux. It gets called in the pattern matching, when it matches e with OPERATE. It should then call OperateAux, and calculate the given expression. The error I'm getting is at line: let OperateAux (op:BINOP) (e1:EXP) (e2:EXP) : VALUE =
so I guess somehow my helper function isn't finished, I just cant figure out where.
let rec eval (vtab : SymTab) (e : EXP) : VALUE =
match e with
| CONSTANT n -> n
| VARIABLE v -> lookup v vtab
| OPERATE (op, e1, e2) -> OperateAux op e1 e2//(eval vtab e1) (eval vtab e2)
| LET_IN (var, e1, e2) -> failwith "case for LET_IN not handled"
| OVER (rop, var, e1, e2, e3) -> failwith "case for OVER not handled"
let OperateAux (op:BINOP) (e1:EXP) (e2:EXP) : VALUE =
let (INT e1) = eval vtab e1
let (INT e2) = eval vtab e2
match op with
| BPLUS -> (e1+e2)
| BMINUS -> (e1-e2)
| BTIMES -> (e1*e2)
| _ -> ()
Here is some types, I'm not sure if they are relevant for this question, but for good measure I'll show them.
type VALUE = INT of int
type BINOP = BPLUS | BMINUS | BTIMES
type RANGEOP = RSUM | RPROD | RMAX | RARGMAX
type EXP =
| CONSTANT of VALUE
| VARIABLE of string
| OPERATE of BINOP * EXP * EXP
| LET_IN of string * EXP * EXP
| OVER of RANGEOP * string * EXP * EXP * EXP
(* A list mapping variable names to their values. *)
type SymTab = (string * VALUE) list
Nevermind, I figured it out. You have to "initialise" your helper function before actually calling it. So the helper function operateAux should come before the pattern matching which calls it.

Raising meaningful exceptions in Ocaml

I would like to print a meaningful message when raising a defined exception in OCaml:
type t = A | B of int
exception Wrong of t
Say I have a function
let string_of_t = function
| A -> "A"
| B n -> ("B" ^ (string_of_int n))
Then I would like to have a function
val print_exception : ( 'a -> string ) -> a' exn -> string
so that I can define
let my_raise e =
print_endline ("Error: I got the unexpected value" ^ (print_exception string_of_t e));
raise e [???]
Is there such a function print_exception ?
The problem is not very well-posed (for instance, there is no a' exn type), but I hope my intent is understandable. I've seen that one can use [##deriving sexp] but this looks like some magic outside of the language, and there is probably something easier and within the language.
There are two ways. The first one is using Printexc, the second one would be to match all the exceptions you want to print and print accordingly, something like:
exception Zero of int
exception B of string
let pp ppf = function
| Zero d -> Format.fprintf ppf "Zero of %d" d
| B s -> Format.fprintf ppf "B of %s" s
| Not_found -> Format.fprintf ppf "Not found"
| _ -> Format.fprintf ppf "Your exception is in another castle"
let f n d = if d = 0 then raise (Zero d) else n / d
let () =
let n, d = (10, 0) in
try Format.printf "%d/%d is %d#." n d (f n d)
with e ->
Format.eprintf "%a#." pp e;
Format.eprintf "%s#." (Printexc.to_string e)
Will give
❯ ./exc
Zero of 0
Exc.Zero(0)
Combining the two seems to be the best solution to be able to customise some displays and let all the others be a default one:
let pp ppf = function
| Zero d -> Format.fprintf ppf "Zero of %d" d
| e -> Format.fprintf ppf "%s" (Printexc.to_string e)
In OCaml we don't have (yet) modular implicits so unless you use [##derive ...] you need to use one of the two solutions.
As a side-note, exceptions can be caught in a pattern matching:
let () =
let n, d = (10, 0) in
match f n d with
| r -> Format.printf "%d/%d is %d#." n d r
| exception e ->
Format.eprintf "%a#." pp e;
Format.eprintf "%s#." (Printexc.to_string e)
It does semantically the same as what I wrote before but it's better for call stacks (if I'm not mistaken)
[EDIT] Looks like I forgot a third solution, see #octachron's answer
If you want to log a meaningful message before raising, it seems to me that it might be simpler to combine the logging and exception raising in one function rather than trying to reconstruct an error message from a generic unknown exception after the fact. For instance, the following function
let log_and_raise exn fmt =
Format.kfprintf
(fun ppf -> Format.pp_print_newline ppf (); raise exn)
Format.err_formatter fmt
can be used like this
exception A of int
let test n = log_and_raise (A n) "Raising the exception (A %d)" n
and will raise the exception A n after printing the error message on stderr.

Recursive call in if expression - ocaml

module Dfs = struct
let rec dfslsts g paths final =
let l = PrimePath.removeDuplicates (PrimePath.extendPaths g paths)
in
let f elem =
if (List.mem "%d" (List.flatten final) = false) then (dfslsts g ["%d"] (List.flatten l)::final)
else final
in
List.iter f (Graph.nodes g)
end
Error: This expression has type string but an expression was expected of type int list
This error occurred when I called dfslsts function, which is recursive, inside the if condition.
The function dfslsts returns a list of lists.
If I try to replace the complex expression in if statement to
if (List.mem "%d" (List.flatten final) = false) then "%d"
else "%d"
then I get
Error: This expression has type 'a -> string
but an expression was expected of type 'a -> unit
Type string is not compatible with type unit
at List.iter line.
How do I solve this problem and are we allowed to call a recursive function inside the if expression.
This is the definition of my graph type:
module Graph = struct
exception NodeNotFound of int
type graph = {
nodes : int list;
edges : (int * int) list;
}
let makeGraph () =
{
nodes = [];
edges = [];
}
let rec isNodeOf g n = List.mem n g.nodes
let nodes g = g.nodes
let edges g = g.edges
let addNode g n =
let nodes = n::g.nodes and edges = g.edges in
{
nodes;
edges;
}
let addEdge g (n1, n2) =
if ((isNodeOf g n1) = false) then
raise (NodeNotFound n1)
else if ((isNodeOf g n2) = false) then
raise (NodeNotFound n2)
else
let nodes = g.nodes
and edges = (n1, n2) :: g.edges in
{
nodes;
edges;
}
let nextNodes g n =
let rec findSuccessors edges n =
match edges with
[] -> []
| (n1, n2) :: t ->
if n1 = n then n2::findSuccessors t n
else findSuccessors t n
in
findSuccessors g.edges n
let rec lastNode path =
match path with
[] -> raise (NodeNotFound 0)
| n :: [] -> n
| _ :: t -> lastNode t
end
module Paths = struct
let extendPath g path =
let n = (Graph.lastNode path) in
let nextNodes = Graph.nextNodes g n in
let rec loop path nodes =
match nodes with
[] -> []
| h :: t -> (List.append path [h]) :: (loop path t)
in
loop path nextNodes
let rec extendPaths g paths =
match paths with
[] -> []
| h :: t -> List.append (extendPath g h) (extendPaths g t)
(* Given a list lst, return a new list with all duplicate entries removed *)
let rec removeDuplicates lst =
match lst with
[]
| _ :: [] -> lst
| h :: t ->
let trimmed = removeDuplicates t in
if List.mem h trimmed then trimmed
else h :: trimmed
end
Any expression can be a recursive function call. There are no limitations like that. Your problem is that some types don't match.
I don't see any ints in this code, so I'm wondering where the compiler sees the requirement for an int list. It would help to see the type definition for your graphs.
As a side comment, you almost certainly have a precedence problem with this code:
dfslsts g ["%d"] (List.flatten l)::final
The function call to dfslsts has higher precedence that the list cons operator ::, so this is parsed as:
(dfslsts g ["%d"] (List.flatten l)) :: final
You probably need to parenthesize like this:
dfslsts g ["%d"] ((List.flatten l) :: final)

OCaml - Save values of recursive function in hashtable

I have this function:
let rec som a b acc =
if a > b then acc else
som (a+1) b (acc+(comb b a));;
And what I am trying to do is to save acc value in a hashtable, so my first try was:
let rec som a b acc =
if a > b then acc else
som (a+1) b (acc+(comb b a)) Hashtbl.add a acc;;
but it does not work... How can I save the values?
This is skeleton, you can try to add you code into it to get what you want. Maybe it will be helpful.
module Key = struct
type t=int
let compare: t->t->int = fun a b -> (* return -1 if a<b, 0 if a=b,and 1 if a>b *)
let equal = (=)
end
module H=Hashtbl.Make(Key)
let som =
let h = H.create () in
let rec f a b acc =
try H.find h acc
with Not_found ->
let ans = (* your evaluation code *) in
H.add h acc ans;
ans
in
f
First, let's take a look at the signature of Hashtbl.add
('a, 'b) Hashtbl.t -> 'a -> 'b -> unit = <fun>
The first argument of the function is an hash table, then you need to create one. To do it, write let h_table = Hashtbl.create 123456;;. And to put it in context your add instruction become HashTbl.add h_table a acc
Next, you can't call this function at the same level of the recursive call. Indeed the function som take three arguments and you will face the following error message, It is applied to too many arguments ....
And as you want to trace the value of acc you need to put it before the recursive call. Doing this can lead you to face some difficulty, then I've added below a hint.
let _ = Printf.printf "a\n" in
let _ = Printf.printf "b\n" in
(1+2)
;;
a
b
- : int = 3

How to get a name of a variable coming into a function as a parameter using F#?

Is there any way in F# how to get a name of a variable passed into a function?
Example:
let velocity = 5
let fn v = v.ParentName
let name = fn velocity // this would return "velocity" as a string
Thank you in advance
EDIT:
Why this code does not work? It is matched as value, so I can not retrieve the "variable" name.
type Test() =
let getName (e:Quotations.Expr) =
match e with
| Quotations.Patterns.PropertyGet (_, pi, _) -> pi.Name + " property"
| Quotations.Patterns.Value(a) -> failwith "Value matched"
| _ -> failwith "other matched"
member x.plot v = v |> getName |> printfn "%s"
let o = new Test()
let display () =
let variable = 5.
o.plot <# variable #>
let runTheCode fn = fn()
runTheCode display
For completing Marcelo's answer, yes you can use quotations for this task:
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
let velocity = 5
let fn (e:Expr) =
match e with
| PropertyGet (e, pi, li) -> pi.Name
| _ -> failwith "not a let-bound value"
let name = fn <#velocity#>
printfn "%s" name
As you can see in the code, F# let-bound top definition values (functions or variables) are implemented as properties of a class.
I can't find anymore the link that shows how a piece of F# code could be rewritten in a functional way with C#. Seeing the code, it becomes obvious why you need a PropertyGet pattern.
Now if you want to evaluate the expression too, you will need to install F# powerpack and reference FSharp.PowerPack.Linq in your project.
It adds an EvalUntyped method on Expr class..
open Microsoft.FSharp.Linq.QuotationEvaluation
let velocity = 5
let fn (e:Expr) =
match e with
| PropertyGet (eo, pi, li) -> pi.Name, e.EvalUntyped
| _ -> failwith "not a let-bound value"
let name, value = fn <#velocity#>
printfn "%s %A" name value
If you need to do it for the method of an instance, here's how I would do it:
let velocity = 5
type Foo () =
member this.Bar (x:int) (y:single) = x * x + int y
let extractCallExprBody expr =
let rec aux (l, uexpr) =
match uexpr with
| Lambda (var, body) -> aux (var::l, body)
| _ -> uexpr
aux ([], expr)
let rec fn (e:Expr) =
match e with
| PropertyGet (e, pi, li) -> pi.Name
| Call (e, mi, li) -> mi.Name
| x -> extractCallExprBody x |> fn
| _ -> failwith "not a valid pattern"
let name = fn <#velocity#>
printfn "%s" name
let foo = new Foo()
let methodName = fn <#foo.Bar#>
printfn "%s" methodName
Just to come back on the code snippet showing usage of EvalUntyped, you can add an explicit type parameter for Expr and a downcast (:?>) if you want/need to keep things type-safe:
let fn (e:Expr<'T>) =
match e with
| PropertyGet (eo, pi, li) -> pi.Name, (e.EvalUntyped() :?> 'T)
| _ -> failwith "not a let-bound value"
let name, value = fn <#velocity#> //value has type int here
printfn "%s %d" name value
You might be able to achieve this with code quotations:
let name = fn <# velocity #>
The fn function will be passed an Expr object, which it must cast to Quotations.Var (which it will only be if you pass a single variable) and extract the Name instance member.
Based on the previous solutions I came out with a more generic solution where you can get the name of functions, lambdas, values, properties, methods, static methods, public fields, Union types:
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
let cout (s:string)= System.Console.WriteLine (s)
let rec getName exprs =
let fixDeclaringType (dt:string) =
match dt with
| fsi when fsi.StartsWith("FSI_") -> "Fsi"
| _ -> dt
let toStr (xDeclType: System.Type) x = sprintf "%s.%s" (fixDeclaringType xDeclType.Name) x
match exprs with
| Patterns.Call(_, mi, _) ->
toStr mi.DeclaringType mi.Name
| Patterns.Lambda(_, expr) ->
getName expr
| Patterns.PropertyGet (e, pi, li) ->
toStr pi.DeclaringType pi.Name
| Patterns.FieldGet (_, fi) ->
toStr fi.DeclaringType fi.Name
| Patterns.NewUnionCase(uci, _) ->
toStr uci.DeclaringType uci.Name
| expresion -> "unknown_name"
let value = ""
let funcky a = a
let lambdy = fun(x) -> x*2
type WithStatic =
| A | B
with static member StaticMethod a = a
let someIP = System.Net.IPAddress.Parse("10.132.0.48")
getName <# value #> |> cout
getName <# funcky #> |> cout
getName <# lambdy #> |> cout
getName <# WithStatic.A #> |> cout
getName <# WithStatic.StaticMethod #> |> cout
getName <# someIP.MapToIPv4 #> |> cout
getName <# System.Net.IPAddress.Parse #> |> cout
getName <# System.Net.IPAddress.Broadcast #> |> cout