I want to understand the following code example:
let rec sumlen = function
| [] -> (0,0)
| x::xs -> let (s,l) = sumlen xs in (s+x,l+1)
The result is clear: It prints out the pair sum and length. But i do not know how this piece of code works.
For example: if i want to print out the sumlen of [1;2;3]:
sumlen [1;2;3]
let (s,l) = sumlen [2;3] in (s+1,l+1)
let (s,l) = let (s,l) = sumlen [3] in (s+2,l+1) in (s+1,l+1)
let (s,l) = let (s,l) = let(s,l) = sumlen [] in (s+3,l+1) in (s+2,l+1) in (s+1,l+1)
let (s,l) = let (s,l) = let(s,l) = (0,0) in (s+3,l+1) in (s+2,l+1) in (s+1,l+1)
I do not know if I am right, and if I am right why this works.
The reason why I need to understand this, is because i have to prove that
sumlen xs = ( sum xs, length xs )
Can someone help me?
Thank you
There are quite a few ways to understand the code. You can unfold the text repeatedly as you have done. In fact your result is correct if you evaluate it:
# let (s,l) = let (s,l) = let(s,l) = (0,0) in (s+3,l+1) in (s+2,l+1) in (s+1,l+1);;
- : int * int = (6, 3)
This works pretty well for understanding what's going on, but it doesn't work so well for proving things.
As a rule, recursion is related directly to the proof method of induction.
To prove something about this code you can show two things:
It works when the input list is empty.
If it works for a list of length n - 1, then it works for a list of length n.
This would be called "induction on the length of the list".
Different people have different responses to whether induction actually "explains" how the code works. In my opinion, it does explain the code.
agreed with answer of Jeffrey.I am trying to answer to your comment : "My problem in this snippet was the let...in statement. I dont know how to prove the code."
let (s,l) = let (s,l) = let (s,l) = (3,1) in (s+2,l+1) in (s+1,l+1)
I rewrite it this way:
let (s,l) =
let (s,l) =
let (s,l) = (3,1)
in
(s+2,l+1)
in
(s+1,l+1)
"let" binds variables in a given scope. The inner let binds (s,l) to (3,0) and returns (5,1) ; which is then used to binds (s,l) in the intermediate scope. The outer let will then bind (s,l) to (6,2) - and this (s,l) is visible at top-level scope.
Related
I need a main function to run the others functions.
I tried this:
let main () =
let deck = make_mazo in
let jugadores = players [] 0 in
dothemagic deck jugadores 0 [] [] [];;
But I got this error:
File "game.ml", line 329, characters 37-39:
Error: Syntax error
I think ;; is the problem and I need a different way to end the code. Also try with only ; and the problem is the same.
[EDIT]
An update here
let main =
let deck = make_mazo [] in
let game = players deck [] 0 in
let dd = fst game in
let jugadores = snd game in
dothemagic dd jugadores 0 [] [] [] [];
let () = main;;
Error persist:
File "game.ml", line 253, characters 13-15:
Error: Syntax error
The other functions are working perfectly fine, but i need a main function because I want to run the program with ocaml game.ml or ocamlbuild game.native
[SECOND EDIT]
After #camlspotter response: The use of ; of your code is wrong. Remove it.
Update 2.0
let main =
let deck = make_mazo [] in
let game = players deck [] 0 in
let dd = fst game in
let jugadores = snd game in
dothemagic dd jugadores 0 [] [] [] []
let () = main;;
New Error:
File "game.ml", line 253, characters 0-3: Error: Syntax error
Think let is the problem now, so i try with this
let main =
let deck = make_mazo [] in
let game = players deck [] 0 in
let dd = fst game in
let jugadores = snd game in
dothemagic dd jugadores 0 [] [] [] []
main;;
But Error is:
File "game.ml", line 253, characters 4-6:
Error: Syntax error
There's nothing syntactically wrong with the code you show here.
Most likely the problem is near the end of the part you don't show, like around line 324 of the file.
If I had to guess, I'd say that line 324 ends with in :-)
As a side comment, you'll also need to call this main function. You might want the last line of the file to be something like this:
let () = main ()
(This line appears in many of my OCaml projects.)
In ocaml, there is no main function unlike other languages, see the code below :
let () = print_string "hello\n";;
let f = print_string "hello, this is f\n";;
let () = f;;
OCaml programs, unlike programs in many other languages, do not have a specific entry-point: all the code in a module (file) is evaluated in order from top to bottom, sort of like in a scripting language. A common idiom you'll see is:
let name = "World" (* I could have added a ;; at the
* end of this line, but that would
* have been unnecessary *)
let () =
Printf.printf "Hello, %s!\n" name
which will output
Hello, World!
The let () = ... may seem a bit wonky, but it's really just pattern-matching: the return type of Printf.printf is unit, () is also of type unit, the you're really just saying "match this unit value with the result of evaluating this expression". Basically, this idiom means "run this unit-type expression in a safe way".
A similar, although highly discouraged, idiom, uses the catch-all pattern:
let greet s =
match s with
| "" -> false
| _ ->
Printf.printf "Hello, %s!\n" s;
true
let name = "World"
let _ =
greet world
The catch-all pattern doesn't care about the type (or value) of the expression it's being matched against, and this idiom means "run this expression and discard whatever it returned".
To solve my problem, I had to write the functions in the following way,
let fun x =
let y = blabla in
code_returning_unit; (* Use ; for unit returns *)
return_value;; (* Use ;; for end of fun *)
Thanks all for the help.
[<EntryPoint>]
let main argv =
let linshi1 = [|1,2|]
let linshi2 = Array.append linshi1 [|2,3|]
let map1 = Map.ofArray linshi2
let mutable it = 1
while it = 1 do
it <- it - 1
let map2 = map1.Add(3,4)
let map1 = map2
printfn "!\n"
printfn "done"
0
this is my test code. I am trying to update the "map1" in the while loop but the result shows that I failed. So how can I achieve this function? I really need updating a map during reading a Excel file. Thanks in advance.
Firstly, you cannot "update" F# map as it is immutable data structure, i.e. adding to a map produces another map. It is not clear how you are going to align reading your Excel with updating a map, but you can always do something like
let mutable myMap = ...
......
myMap <- (x,y) ||> Map.add <| myMap
which creates a new map instance off the old one and then points the original reference to new contents discarding the previous one.
Secondly, when you use while expression it creates a new scope so your let map1=... shadows "original" map1 outside the while. This "internal" map1 in turn gets discarded when control is getting back outside of while. That's why your manipulations inside while do not anyhow affect your "original" map1. See FSharp Programming/Basic Concepts for details of scoping and shadowing.
Summing up, you do not need any while loop; just convert your snippet to something like the snippet below, where instead of making map1 mutable it is simply redefined. This is allowed inside functions, and main is a function, indeed:
[<EntryPoint>]
let main argv =
let linshi1 = [|1,2|]
let linshi2 = Array.append linshi1 [|2,3|]
let map1 = Map.ofArray linshi2
let map1 = (3,4) ||> Map.add <| map1
printfn "%A" map1
0
which being executed will output map [(1, 2); (2, 3); (3, 4)] as expected.
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.
I wrote a OCaml program for union find algorithm. This algorithm I wrote is not optimal and is the simplest version.
I put my OCaml code here because I am not sure whether this code is good enough or not (despite of the algorithm itself), although this code can run without errors.
This is the first time I wrote a complete working thing after I started to learn OCaml, so please help me by reviewing it.
Useful suggestions will help me improving my OCaml skills. Thanks
type union_find = {id_ary : int array; sz_ary : int array};;
let create_union n = {id_ary = Array.init n (fun i -> i);
sz_ary = Array.init n (fun i -> 1)};;
let union u p q =
let rec unionfy id_ary i =
let vp = id_ary.(p) in
let vq = id_ary.(q) in
if i < Array.length id_ary then begin
if i != q && id_ary.(i) = vp then id_ary.(i) <- vq;
unionfy id_ary (i + 1)
end
else print_string "end of union\n"
in
unionfy u.id_ary 0;;
let is_connected u p q = u.id_ary.(p) = u.id_ary.(q);;
First of all,
Am I creating the data structure of union (as in union find) correctly?
Should I include two arrays inside or is there any better way?
Second,
I am using array in this code, but array is mutable which is not that good for fp right?
Is there a way to avoid using array?
Finally,
Overall, is this piece of code good enough?
Anything can be improved?
P.S. I am not using OCaml's object oriented bit yet, as I haven't learnt to that part.
Some comments on the code:
You don't seem to use sz_ary for anything.
Your code iterates through the whole array for each union operation. This is not correct for the standard (Tarjan) union-find. For a linear number of union operations your code produces a quadratic solution. Wikipedia has the standard algorithm: Disjoint-set Data Structure.
To answer your second question: as far as I know, union-find is one of the algorithms for which there's no known functional (immutable) solution with the same complexity as the best imperative solution. Since an array is simply a map from integers to values, you could always translate any array-based solution into an immutable one using maps. As far as I've been able to determine, this would match the best known solution in asymptotic complexity; i.e., it would add an extra factor of log n. Of course there would also be a constant factor that might be large enough to be a problem.
I've implemented union-find a few times in OCaml, and I've always chosen to do it using mutable data. However, I haven't used arrays. I have a record type for my basic objects, and I use a mutable field in each record to point to its parent object. To do path compression, you modify the parent pointer to point to the current root of the tree.
A few stylistic points:
Not sure why unionfy takes id_ary as a parameter since it keeps it constant throughout
don't use Array.init with a constant function. Just use Array.make.
print_string "...\n" is equivalent to print_endline "..."
The following definition can be cleaned up with punning to
let union u p q = to: let union {id_ary; _} p q so that there are no extraneous references to u.
Same punning trick for let is_connected u p q = u.id_ary.(p) = u.id_ary.(q);;
This might be a personal choice but I would get rid of:
let vp = id_ary.(p) in
let vq = id_ary.(q) in
Or at least shove them above the recursive definition so that it's clear they are constant.
EDIT: corrected version
let union {id_ary;_} p q =
let (vp, vq) = (id_ary.(p), id_ary.(q)) in
let rec unionfy i =
if i < Array.length id_ary then begin
if i != q && id_ary.(i) = vp then id_ary.(i) <- vq;
unionfy (i + 1)
end else print_endline "end of union"
in unionfy 0;;
I am trying to create an expression tree containing a function call to a F# function on a certain module. However, I am missing something because the System.Linq.Expressions.Expression.Call() helper function cant find the function I'm supplying.
The Call() call gives an InvalidOperationException: "No method 'myFunction' on type 'TestReflection.Functions' is compatible with the supplied arguments."
If anyone can give me a hint on what I am doing wrong it would be very helpful.
See the code below:
namespace TestReflection
open System.Linq.Expressions
module Functions =
let myFunction (x: float) =
x*x
let assem = System.Reflection.Assembly.GetExecutingAssembly()
let modul = assem.GetType("TestReflection.Functions")
let mi = modul.GetMethod("myFunction")
let pi = mi.GetParameters()
let argTypes =
Array.map
(fun (x: System.Reflection.ParameterInfo) -> x.ParameterType) pi
let parArray =
[| (Expression.Parameter(typeof<float>, "a") :> Expression); |]
let ce = Expression.Call(modul, mi.Name, argTypes, parArray)
let del = (Expression.Lambda<System.Func<float, float>>(ce)).Compile()
printf "%A" (Functions.del.Invoke(3.5))
Regards,
Rickard
The third argument to Expression.Call is an array of generic type parameters - your method is not generic, so that should be null. You'll also need to pass your "a" argument to Expression.Lambda:
let a = Expression.Parameter(typeof<float>, "a")
let parArray = [| (a :> Expression); |]
let ce = Expression.Call(modul, mi.Name, null, parArray)
let del = (Expression.Lambda<System.Func<float, float>>(ce, a)).Compile()