Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 months ago.
Improve this question
let z = 4 in let y=5 in
try
y = z+x
with Failure msg -> msg = "Free identifier: x"
If we do this, how does OCaml know if try fails?? In real, I'm trying to "try function with fail msg" but my function has to return int value. How can you make OCaml know that try has failed by returning int value?
My real code is something like this:
try
let ast = (Prog ([], (Add (Id "x", Num 1)))) in
interp ast = NumV 5
with Failure msg -> msg = "Free identifier: x"
but function has to return int (NumV is NumV of int) and this code doesn't work. msg doesn't show at fail and it does fails.
let interp (p: Ast.prog) : int = ~
I added function interp for additional info
If your function truly has to return an int value, then you have to pick an int value to represent failure. Let's say you pick -1 as your special failure value. Then the code might look like this:
let f x = try x + 1 with Failure _ -> -1
You can't return a message in the failure case and an int in the usual case. All the returns of a function have to be the same type.
That's why there is a type named result. It's used to combine a failure type and a success type into one larger type. The failure value is constructed by Error <value> and the success value is constructed by Ok <value>. These values can be two different types because the Error and the Ok are used to tell which is which. This code would look like this:
let f x = try Ok (x + 1) with Failure _ -> Error "msg"
If what you are trying to do is exit the program with a custom error message, you need to exit the program after printing your error message:
try
let ast = (Prog ([], (Add (Id "x", Num 1)))) in
interp ast = NumV 5
with Failure msg ->
Format.eprintf "Free identifier: x";
exit 2
You might also be trying to raise a custom exception:
exception My_exception of string
try
let ast = (Prog ([], (Add (Id "x", Num 1)))) in
interp ast = NumV 5
with Failure msg ->
raise (My_exception "Free identifier: x")
If the inner equality is supposed to be a pattern matching, you might be trying to write
let ast = (Prog ([], (Add (Id "x", Num 1)))) in
match interp ast with
| NumV n -> n
| _ ->
Format.eprintf "Free identifier: x";
exit 2
(you could also raise an exception, it is unclear what to do without more context)
A value Ok x means that the computation succeeded with x, and a value Error e means that it failed.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 months ago.
Improve this question
I'm trying to learn functional programming with Ocaml and I want to implement a function, which returns the sum of the elements in a list. I want to do it using a while loop, but I can't think of a way to write the check.
I imagined something like this
let sum_it (xs: int list) =
let j = ref 1 in
let add x y = x+y in
while xs <> [] do
j := add !j hd ;
xs = tl done ;
!j ;;
but now it fails with the j := add !j hd ;
Error: This expression has type 'a list -> 'a
but an expression was expected of type int
The OCaml way to analyze the shape of a value is to use pattern matching:
match list with
| [] -> ... (* 1 *)
| a :: q -> ... (* 2 *)
Compared to a language with only conditionals (like C), the advantage of pattern matching is that it directly associate a check to see if a value has a certain shape with the action to run for values of that shape. Combined with the possibility to check if a pattern matching covers all case, this decrease considerably the room for mistakes.
For instance, with
| [] -> ... (* 1 *)
the action 1 on the right hand side of -> is only run if the matched list list is empty whereas the second action
| a :: q -> ... (* 2 *)
is only run if the list has the shape a :: q for some a and q. Moreover, this second action can use the value a of the head of the list and the value q of the tail of the list directly in its body. For instance
| a :: q -> a + List.length q
sums the first element of the list list with the length of its tail.
P.S: The use of while loop for simple recursive function is not optimal. The idiomatic OCaml way is to define a recursive function. Indeed, a while loop may have a very complex flow of data. Contrarily, a pure recursive function will have much more explicit and often simpler flow of data.
I am C# dev that has just starting to learn F# and I have a few questions about unit testing. Let's say I want to the following code:
let input () = Console.In.ReadLine()
type MyType= {Name:string; Coordinate:Coordinate}
let readMyType =
input().Split(';')
|> fun x -> {Name=x.[1]; Coordinate = {
Longitude = float(x.[4].Replace(",","."))
Latitude =float(x.[5].Replace(",","."))
}}
As you can notice, there are a few points to take in consideration:
readMyType is calling input() with has a side effect.
readMyType assume many thing on the string read (contains ';' at least 6 columns, some columns are float with ',')
I think the way of doing this would be to:
inject the input() func as parameter
try to test what we are getting (pattern matching?)
Using NUnit as explained here
To be honest I'm just struggling to find an example that is showing me this, in order to learn the syntax and other best practices in F#. So if you could show me the path that would be very great.
Thanks in advance.
First, your function is not really a function. It's a value. The distinction between functions and values is syntactic: if you have any parameters, you're a function; otherwise - you're a value. The consequence of this distinction is very important in presence of side effects: values are computed only once, during initialization, and then never change, while functions are executed every time you call them.
For your specific example, this means that the following program:
let main _ =
readMyType
readMyType
readMyType
0
will ask the user for only one input, not three. Because readMyType is a value, it gets initialized once, at program start, and any subsequent reference to it just gets the pre-computed value, but doesn't execute the code over again.
Second, - yes, you're right: in order to test this function, you'd need to inject the input function as a parameter:
let readMyType (input: unit -> string) =
input().Split(';')
|> fun x -> {Name=x.[1]; Coordinate = {
Longitude = float(x.[4].Replace(",","."))
Latitude =float(x.[5].Replace(",","."))
}}
and then have the tests supply different inputs and check different outcomes:
let [<Test>] ``Successfully parses correctly formatted string``() =
let input() = "foo;the_name;bar;baz;1,23;4,56"
let result = readMyType input
result |> should equal { Name = "the_name"; Coordinate = { Longitude = 1.23; Latitude = 4.56 } }
let [<Test>] ``Fails when the string does not have enough parts``() =
let input() = "foo"
(fun () -> readMyType input) |> shouldFail
// etc.
Put these tests in a separate project, add reference to your main project, then add test runner to your build script.
UPDATE
From your comments, I got the impression that you were seeking not only to test the function as it is (which follows from your original question), but also asking for advice on improving the function itself, so as to make it more safe and usable.
Yes, it is definitely better to check error conditions within the function, and return appropriate result. Unlike C#, however, it is usually better to avoid exceptions as control flow mechanism. Exceptions are for exceptional situations. For such situations that you would have never expected. That is why they are exceptions. But since the whole point of your function is parsing input, it stands to reason that invalid input is one of the normal conditions for it.
In F#, instead of throwing exceptions, you would usually return a result that indicates whether the operation was successful. For your function, the following type seems appropriate:
type ErrorMessage = string
type ParseResult = Success of MyType | Error of ErrorMessage
And then modify the function accordingly:
let parseMyType (input: string) =
let parts = input.Split [|';'|]
if parts.Length < 6
then
Error "Not enough parts"
else
Success
{ Name = parts.[0]
Coordinate = { Longitude = float(parts.[4].Replace(',','.')
Latitude = float(parts.[5].Replace(',','.') }
}
This function will return us either MyType wrapped in Success or an error message wrapped in Error, and we can check this in tests:
let [<Test>] ``Successfully parses correctly formatted string``() =
let input() = "foo;the_name;bar;baz;1,23;4,56"
let result = readMyType input
result |> should equal (Success { Name = "the_name"; Coordinate = { Longitude = 1.23; Latitude = 4.56 } })
let [<Test>] ``Fails when the string does not have enough parts``() =
let input() = "foo"
let result = readMyType input
result |> should equal (Error "Not enough parts)
Note that, even though the code now checks for enough parts in the string, there are still other possible error conditions: for example, parts.[4] may be not a valid number.
I am not going to expand on this further, as that will make the answer way too long. I will only stop to mention two points:
Unlike C#, verifying all error conditions does not have to end up as a pyramid of doom. Validations can be nicely combined in a linear-looking way (see example below).
The F# 4.1 standard library already provides a type similar to ParseResult above, named Result<'t, 'e>.
For more on this approach, check out this wonderful post (and don't forget to explore all links from it, especially the video).
And here, I will leave you with an example of what your function could look like with full validation of everything (keep in mind though that this is not the cleanest version still):
let parseFloat (s: string) =
match System.Double.TryParse (s.Replace(',','.')) with
| true, x -> Ok x
| false, _ -> Error ("Not a number: " + s)
let split n (s:string) =
let parts = s.Split [|';'|]
if parts.Length < n then Error "Not enough parts"
else Ok parts
let parseMyType input =
input |> split 6 |> Result.bind (fun parts ->
parseFloat parts.[4] |> Result.bind (fun lgt ->
parseFloat parts.[5] |> Result.bind (fun lat ->
Ok { Name = parts.[1]; Coordinate = { Longitude = lgt; Latitude = lat } } )))
Usage:
> parseMyType "foo;name;bar;baz;1,23;4,56"
val it : Result<MyType,string> = Ok {Name = "name";
Coordinate = {Longitude = 1.23;
Latitude = 4.56;};}
> parseMyType "foo"
val it : Result<MyType,string> = Error "Not enough parts"
> parseMyType "foo;name;bar;baz;badnumber;4,56"
val it : Result<MyType,string> = Error "Not a number: badnumber"
This is a little follow-up to the excellent answer of #FyodorSoikin trying to explore the suggestion
keep in mind though that this is not the cleanest version still
Making the ParseResult generic
type ParseResult<'a> = Success of 'a | Error of ErrorMessage
type ResultType = ParseResult<Defibrillator> // see the Test Cases
we can define a builder
type Builder() =
member x.Bind(r :ParseResult<'a>, func : ('a -> ParseResult<'b>)) =
match r with
| Success m -> func m
| Error w -> Error w
member x.Return(value) = Success value
let builder = Builder()
so we get a concise notation:
let parse input =
builder {
let! parts = input |> split 6
let! lgt = parts.[4] |> parseFloat
let! lat = parts.[5] |> parseFloat
return { Name = parts.[1]; Coordinate = { Longitude = lgt; Latitude = lat } }
}
Test Cases
Tests are always fundamental
let [<Test>] ``3. Successfully parses correctly formatted string``() =
let input = "foo;the_name;bar;baz;1,23;4,56"
let result = parse input
result |> should equal (ResultType.Success { Name = "the_name"; Coordinate = { Longitude = 1.23; Latitude = 4.56 } })
let [<Test>] ``3. Fails when the string does not have enough parts``() =
let input = "foo"
let result = parse input
result |> should equal (ResultType.Error "Not enough parts")
let [<Test>] ``3. Fails when the string does not contain a number``() =
let input = "foo;name;bar;baz;badnumber;4,56"
let result = parse input
result |> should equal (ResultType.Error "Not a number: badnumber")
Notice the usage of a specific ParseResult from the generic one.
minor note
Double.TryParse is just enough in the following
let parseFloat (s: string) =
match Double.TryParse s with
| true, x -> Success x
| false, _ -> Error ("Not a number: " + s)
Why is this Ocaml statement giving me a syntax error?
let a = 0;; if a = 0 then let b = 0;;
Do if then else statements always have to return a value?
EDIT: Here is the code I am struggling with. I want to apply this function over a list with the map function. The function is supposed to look at each word in the list wordlist and add to the stringmap. If it has already been added to the string map then add 1 to its password.
module StringMap = Map.Make(String)
let wordcount = StringMap.empty
let findword testword =
let wordcount = (if (StringMap.mem testword wordcount)
then (StringMap.add testword ((StringMap.find testword wordcount)+1) wordcount)
else (StringMap.add testword 1 wordcount))
List.map findword wordlist
You can only have an if then without else if the then expression evaluates to unit () Otherwise, the expression will not type check. An if without an else is equivalent to writing if x then y else () which can only type check if y is unit.
Check this out for a reference.
(Terminology note: there are no statements in OCaml because everything is an expression, so the term "if statement" doesn't quite apply. I still understood what you meant, but I thought this was worth noting)
Yes, if is an expression in OCaml, not a statement. The best way to look at it is that there are no statements in OCaml. Everything is an expression. (Admittedly there are expressions that return (), which are similar to statements.)
You can only have if b then e if the type of e is unit (i.e., if it returns ()).
Note also that you can't just say let v = e, except at the top level of a module. At the top level it defines a global name in the module. In other cases you need to say let v = e1 in e2; the let defines a local symbol v for use in the expression e2.
One answer to the let b = problem - it works like this:
let a = 0
let b = if a = 0 then 0 else 1
(* or whatever value you need in the else branch *)
And then the Map problem: the manual says Map is applicative - that means Stringmap.add returns a new map. You must use a ref to store your map - see this ocaml toplevel protocol:
# module StringMap = Map.Make(String);;
# let mymap = ref StringMap.empty ;;
val mymap : '_a StringMap.t ref = {contents = <abstr>}
# mymap := StringMap.add "high" 1 !mymap;;
- : unit = ()
# StringMap.mem "high" !mymap;;
- : bool = true
# StringMap.mem "nono" !mymap;;
- : bool = false
# StringMap.find "high" !mymap;;
- : int = 1
# StringMap.find "nono" !mymap;;
Exception: Not_found.
I am building a floating point calculator and I'm stuck. The fp calculator has prompt shape, so my problem is that where I handle the exceptions I leave the recursive function that keeps the prompt showing up and ends the execution:
let initialDictionary = ref EmptyDictionary;;
let launcher () =
print_string ("Welcome");
let rec aux dic =
try
print_string ("->");
aux ( execute dic (s token (Lexing.from_string (read_line () ))));
with
End_of_exec -> print_endline ("closing")
Var_not_assigned s -> printf "var %s not assigned" s
in aux !initialDictionary;;
Where:
val exec : dictionary -> Instruction -> dictionary;
type dictionary = (string,float)list
The point here is that as lists are immutable on ocaml, the only way I have to keep my dictionary stacking variables with its value is applying recursion taking the value dictionary from exec return.
So any ideas on how not to leave the "prompt like" execution while showing exceptions?
A read eval print loop interpreter has all these different phases which must be handled separately, and I think your implementation tried to do too much in a single step. Just breaking down the second part of your function will help untangle the different error handlers:
let launcher () =
let rec prompt dic =
print_string "->";
parse dic
and parse dic =
let res =
try
s token (Lexing.from_string ## read_line ())
with End_of_exec -> (print_encline "closing"; raise End_of_exec)
in evalloop dic res
and evalloop dic rep =
let dic =
try execute dic rep
with Var_not_assigned s -> (printf "var %s not assigned\n" s; dic)
in prompt dic
in prompt !InitialDictionary;;
Since each sub function will either tail call the next one or fail with an exception, the overall code should be tail recursive and optimised to a loop.
The good thing about this is that now you get a better picture of what is going on, and it makes it easier to change an individual step of the loop without touching the rest.
By the way, recall that read_line may trigger an End_of_file exception as well, but it should be trivial now to handle it now (left as an exercise).
Ok a friend of mine gave me a solution and thinking about it I cant figure out a more elegant way.
Let exec () =
Let _= print_string "->" in
( try
Let inst = s token (Lexing.from_string (read_line())) in
Try
Let r = exec_instruction !initialDictionary inst in
initialDictionary := r
With
| Var_not_assigned s -> printf "var %s not assigned. \n" s
| Com_not_implemented s -> printf " command %s not implemented. \n" s
| Function_not_implemented s -> printf " function %s not implemented. \n" s
With
| lexic_error -> print_endline "lexic error"
| Parsing. Parse_error -> print_endline "sintax error"
);;
Let rec program cont =
If cont then
Try
Exec (); program true
With
| End_of_exec -> print_endline "closing"; program false;;
Program true
The only thing that bothers me its the initialDictionary := r assignment, because exec_instruction returns a dictionary so it can be done recursive but it works anyways, ill figure out something hah.
Thank you for the help, if someone can see a brigther solution let me know.
I have a function save that take standard input, which is used individually like this:
./try < input.txt (* save function is in try file *)
input.txt
2
3
10 29 23
22 14 9
and now i put the function into another file called path.ml which is a part of my interpreter. Now I have a problem in defining the type of Save function and this is because save function has type in_channel, but when i write
type term = Save of in_channel
ocamlc complain about the parameter in the command function.
How can i fix this error? This is the reason why in my last question posted on stackoverflow, I asked for the way to express a variable that accept any type. I understand the answers but actually it doesn't help much in make the code running.
This is my code:
(* Data types *)
open Printf
type term = Print_line_in_file of int*string
| Print of string
| Save of in_channel (* error here *)
;;
let input_line_opt ic =
try Some (input_line ic)
with End_of_file -> None
let nth_line n filename =
let ic = open_in filename in
let rec aux i =
match input_line_opt ic with
| Some line ->
if i = n then begin
close_in ic;
(line)
end else aux (succ i)
| None ->
close_in ic;
failwith "end of file reached"
in
aux 1
(* get all lines *)
let k = ref 1
let first = ref ""
let second = ref ""
let sequence = ref []
let append_item lst a = lst # [a]
let save () =
try
while true do
let line = input_line stdin in
if k = ref 1
then
begin
first := line;
incr k;
end else
if k = ref 2
then
begin
second := line;
incr k;
end else
begin
sequence := append_item !sequence line;
incr k;
end
done;
None
with
End_of_file -> None;;
let rec command term = match term with
| Print (n) -> print_endline n
| Print_line_in_file (n, f) -> print_endline (nth_line n f)
| Save () -> save ()
;;
EDIT
Error in code:
Save of in_channel:
Error: This pattern matches values of type unit
but a pattern was expected which matches values of type in_channel
Save of unit:
Error: This expression has type 'a option
but an expression was expected of type unit
There are many errors in this code, so it's hard to know where to start.
One problem is this: your save function has type unit -> 'a option. So it's not the same type as the other branches of your final match. The fix is straightforward: save should return (), not None. In OCaml these are completely different things.
The immediate problem seems to be that you have Save () in your match, but have declared Save as taking an input channel. Your current code doesn't have any way to pass the input channel to the save function, but if it did, you would want something more like this in your match:
| Save ch -> save ch
Errors like this suggest (to me) that you're not so familiar with OCaml's type system. It would probably save you a lot of trouble if you went through a tutorial of some kind before writing much more code. You can find tutorials at http://ocaml.org.