role of the |> operator vs partial application - ocaml

I have the following code:
type transaction = Withdraw of int | Deposit of int | Checkbalance
(* Bank account generator. *)
let make_account(opening_balance: int) =
let balance = ref opening_balance in
fun (t: transaction) ->
match t with
| Withdraw(m) -> if (!balance > m)
then
((balance := !balance - m);
(Printf.printf "Balance is %i" !balance))
else
print_string "Insufficient funds."
| Deposit(m) ->
((balance := !balance + m);
(Printf.printf "Balance is %i\n" !balance))
| Checkbalance -> (Printf.printf "Balance is %i\n" !balance)
;;
whenever I try to run the following command: make_account(100) Deposit(50) ;; I get the following error: This function has type int -> transaction -> unit. It is applied to too many arguments; maybe you forgot a `;'.
However the following command works just fine Deposit(50) |> make_account(100) ;;
But why aren't these two line of codes equivalent? shouldn't (make_account 100) be replaced by (fun (t: transaction) -> ...) ? Because then I don't understand why my first attempt did not work.
Thank you!

Notice that Ocaml doesn't use parenthesis for function calls. In the statement
make_account (100) Deposit (50);;
you have two unnecessary grouping parenthesis, it is the same as
make_account 100 Deposit 50 ;;
where make_account is applied with three arguments. What you meant to write was
make_account 100 (Deposit 50);;
which is equivalent to the parenthesis-less
Deposit 50 |> make_account 100;;

Related

problem with how we define tuples as the funtion input in OCaml

This ia an assignment problem:
In class, we have shown you a program which mimics transactions done
on a bank account. For this we have first defined a data-type for
transactions:
type transaction = Withdraw of int | Deposit of int |
CheckBalance | ChangePassword of string | Close
We have added two new
transactions to the example done in class. In class, we defined a
function make-account which generates a bank account when given an
opening balance. In this exercise, you are asked to modify this code
and generate a password-protected bank account. Any transaction on the
bank account should only be possible, if one provides the right
password. For this, implement the function makeProtectedAccount with
the arguments and types shown below. let
makeProtectedAccount(openingBalance: int, password: string) = This
function takes in the opening balance as a first argument and the
password as a second, and will return a function which when given the
correct password and a transaction will perform the transaction. One
crucial difference to be noted right away is that in the new code I
want you to print the balance on the screen instead of returning it as
a value.
I tried to declare a function in OCaml which takes as input a tuple. But it gave me an error when I tried to tell the compiler what type are each of the elements in the tuple. However, the compiler compiles when I put parenthesis around the type definition of each of the items in the tuples. Furthermore, I tried to put multiple statements as the execution sequence of a matched case in a match statement, but the compiler cannot recognize it. How can we execute multiple statements for a matched case?
function declaration with Compilor error:
makeProtectedAccount(openingBalance: int, password: string) =
function declaration without compilor error:
makeProtectedAccount((openingBalance: int), (password: string)) =
Codes that I wrote so far, as you can see the compiler dosen't understand that |Deposit is a matched case as it does not indent the statement automatically:
let makeProtectedAccount ( (openingBalance : int) , (password : string) ) =
let balance = ref openingBalance in
let pass = ref password in
fun (( passs : string ), (tras : transaction)) ->
if !passs = pass then
match trans with
| Withdraw q -> (if balance >= q then balance := !balance - q ; Printf.printf "withdrawing %d dollar, you have %d dollar left" q !balance
else Printf.printf "Invalid: withdrawing more money than you have!")
|Deposit q -> balance := !balance + q; Printf.printf "Deposit %d, you have now %d ", q !balance
Multiple questions here
How to write a function that accepts a tuple
Like you did, or
let makeProtectedAccount ((openingBalance, password): int*string) =
How to write multiple statements in a match case
Also as you did
match trans with
| Withdraw q -> Printf.printf "statement 1\n"; Printf.printf "statement 2\n"
| Deposit q -> Printf.printf "statement 3\n"; Printf.printf "statement 4\n"
I think a problem is the stray , in your last printf. Also, passs is not a ref, no need to dereference it with !. Also, parenthesize the statements in the then branch
This should work for example
let makeProtectedAccount ((openingBalance:int), (password:string)) =
let balance = ref openingBalance in
let pass = ref password in
function
| p, Withdraw q when p = !pass ->
if !balance >= q then (balance := !balance - q; Printf.printf "withdrawing %d dollar, you have %d dollar left" q !balance)
else Printf.printf "Invalid: withdrawing more money than you have!"
| p, Deposit q when p = !pass -> balance := !balance + q; Printf.printf "Deposit %d, you have now %d " q !balance
| _, _ -> ()
By the way, if there is no particular reason to accept a tuple, it would be more idiomatic to write a function with two parameters
let makeProtectedAccount (openingBalance:int) (password:string) =

Declaring function using function in F#

I'm trying to understand the following code to declare a function:
let string_of_int = function
| 0 -> "zero"
| 1 -> "one"
| 2 -> "two"
| _ -> "many"
which is the same as
let string_of_int2 x = match x with
|0 -> "zero"
|1 -> "one"
| 2-> "two"
_ -> "many
I understand The second way of declaring the function with is trying to match the input x with several possibilities that it could be. But I don't understand the first way to do it. What does function keyword do?
Also,
what does 'a'..'z' do in the following code?
let is_capital = function
| 'a'..'z' -> false
| 'A'..'Z' -> true
|_ -> failwith "Not a valid letter"
Why can't I have a function like this:
let examplefunc = function
|"string"-> Printf.printf "a string"
|3 -> Printf.print "an integer"
|true-> Printf.printf "a boolean"
|- -> Printf.printf "whatever"
The function keyword is a variant of fun that takes in account that the behavior of the function often directly depends on the value of the argument. For instance, if we start with the following definition of the factorial function:
For a positive integer n, n! is 1 if n = 0, and n * (n-1)! otherwise
then the natural translation to OCaml is
let factorial = function
| 0 (* if n = 0 *) -> 1
| n (* otherwise *) -> n * factorial (n-1)
like you said this strictly equivalent to
let factorial = fun n -> match n with
| 0 (* if n = 0 *) -> 1
| n (* otherwise *) -> n * factorial (n-1)
but when the argument of the function is immediately deconstructed in a pattern matching, it may be more readable to use function directly.
Concerning '0'..'9', those are range pattern that matches all characters (i.e '0'|'1'|'2'|'3'|'4'|..| '9' between the lower and upper bounds (included) of the range (following the ascii ordering of characters)
let is_digit = function '0'..'9' -> true | _ -> false
is_digit '0' (* returns true *);;
is_digit 'a' (* returns false *);;

How to take sublist without first and last item with F#?

I have sorted list of integer values:
let ls = [1..4]
How can I get a sublist without first and the last element? (In the most optimal way)
The expected result is [2; 3].
This is what I have so far, and yeah, it's working, but I in my opinion it's just not the best approach.
[1..4] |> List.tail |> List.rev |> List.tail |> List.sort
A somewhat long answer incoming in response to your innocently worded qualifier: "In the most optimal way"
Optimal in terms of what?
Performance? (Most likely)
Performance but also include GC performance?
Memory usage?
x86?
x64?
And so on...
So I decided to measure some aspects of the problem.
I measured the different answers (added a non-idiomatic version as well) in this thread in various different context.
Without further ado here is the program I used to measure
open System
open System.Diagnostics
open System.IO
module so29100251 =
// Daystate solution (OP)
module Daystate =
// Applied minor fixes to it
let trim = function
| [] | [_] | [_;_] -> []
| ls -> ls |> List.tail |> List.rev |> List.tail |> List.rev
// kaefer solution
module kaefer =
type 'a State = Zero | One | Other of 'a
let skipFirstAndLast xss =
let rec aux acc = function
| _, [] -> List.rev acc
| Zero, x::xs -> aux acc (One, xs)
| One, x::xs -> aux acc (Other x, xs)
| (Other prev), x::xs -> aux (prev :: acc) (Other x, xs)
aux [] (Zero, xss)
// Petr solution
module Petr =
let rec trimImpl ls acc =
match ls, acc with
| [], _ -> acc
| h::[], acc -> List.rev acc
| h::n::t, [] -> trimImpl t [n]
| h::t, acc -> trimImpl t (h::acc)
let trim ls = trimImpl ls []
// NonIdiomatic solution
module NonIdiomatic =
let trim (hint : int) (ls : 'T list) =
// trims last of rest
// Can't ask for ls.Length as that is O(n)
let ra = ResizeArray<_> (hint)
// Can't use for x in list do as it relies on .GetEnumerator ()
let mutable c = ls
while not c.IsEmpty do
ra.Add c.Head
c <- c.Tail
let count = ra.Count
let mutable result = []
for i in (count - 2)..(-1)..1 do
result <- ra.[i]::result
result
open so29100251
type Time = MilliSeconds of int64
type TestKind<'T> =
| Functional of 'T
| MeasurePerformance of int*int
[<EntryPoint>]
let main argv =
let factor = 10000000
// let maxHint = Int32.MaxValue
let maxHint = 100
let time (action : unit -> 'T) : 'T*Time =
let sw = Stopwatch ()
sw.Start ()
let r = action ()
sw.Stop ()
r, MilliSeconds sw.ElapsedMilliseconds
let adapt fn hint ls = fn ls
let trimmers =
[|
"Daystate" , adapt Daystate.trim
"kaefer" , adapt kaefer.skipFirstAndLast
"Petr" , adapt Petr.trim
"NonIdiomatic" , NonIdiomatic.trim
|]
#if DEBUG
let functionalTestCases =
[|
Functional [] , "empty" , []
Functional [] , "singleton" , [1]
Functional [] , "duoton" , [1;2]
Functional [2] , "triplet" , [1;2;3]
Functional [2;3] , "quartet" , [1;2;3;4]
|]
let performanceMeasurements = [||]
#else
let functionalTestCases = [||]
let performanceMeasurements =
[|
"small" , 10
"big" , 1000
"bigger" , 100000
// "huge" , 10000000
|] |> Array.map (fun (name, size) -> MeasurePerformance (size, (factor / size)) , name , [for x in 1..size -> x])
#endif
let testCases =
[|
functionalTestCases
performanceMeasurements
|] |> Array.concat
use tsv = File.CreateText ("result.tsv")
tsv.WriteLine (sprintf "TRIMMER\tTESTCASE\tSIZE\tHINT\tRUNS\tMEMORY_BEFORE\tMEMORY_AFTER\tGC_TIME\tRUN_TIME")
for trimName, trim in trimmers do
for testKind, testCaseName, testCase in testCases do
match testKind with
| Functional expected ->
let actual = trim 0 testCase
if actual = expected then
printfn "SUCCESS: Functional test of %s trim on testcase %s successful" trimName testCaseName
else
printfn "FAILURE: Functional test of %s trim on testcase %s failed" trimName testCaseName
| MeasurePerformance (size,testRuns) ->
let hint = min size maxHint
let before = GC.GetTotalMemory(true)
printfn "MEASURE: Running performance measurement on %s trim using testcase %s..." trimName testCaseName
let timeMe () =
for x in 1..testRuns do
ignore <| trim hint testCase
let _, MilliSeconds ms = time timeMe
let after = GC.GetTotalMemory(false)
let timeGC () =
ignore <| GC.GetTotalMemory(true)
let _, MilliSeconds msGC = time timeMe
printfn "...%d ms (%d runs), %d (before) %d (after) %d ms (GC)" ms testRuns before after msGC
tsv.WriteLine (sprintf "%s\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d" trimName testCaseName size hint testRuns before after msGC ms)
0
I then measured the execution time and GC time on x64 and max size hint allowed:
(size hints is only used by the non-idiomatic version)
x86 and max size hint allowed:
x64 and max 100 hint allowed:
x86 and max 100 hint allowed:
Looking at the performance charts we can note some somewhat surprising things:
All variants are iterating 10000000 times. One would expect the execution time to not differ between the different variants but they do.
The crusty old x86 scores consistently better overall. I won't speculate why.
OPs initial version while seemingly wasteful scores pretty good. It's probably helped by that List.rev is very optimized (IIRC it does some safe cheating available only to F# devs)
The kaefer version while on paper a better solution seems to score the worst. I think it's because it allocates extra State objects which are heap based. (This should obviously not be interpreted as a criticism of kaefers skills)
The non-idiomatic solution scores good with good size hints but not as good as I expected. It might be that building the final lists is what costs most cycles. It might also be that tail recursive functions over lists are more efficient than while loops as IIRC pattern matching are more effective than calling List.Tail/List.Head/List.IsEmpty
GC time is almost as big as the execution time.
I expected the GC time of the non-idiomatic solution to be significantly lower than the rest. However, while the ResizeArray<_> are probably quick to collect the list objects aren't.
On x86 arch the performance difference between Petr solution and the non-idiomatic one might not warrant the extra complexity.
Some final thoughts:
OPs original solution did pretty good
Garbage Collection takes time
Always measure...
Hopefully it was somewhat interesting
Edit:
The GC performance measurement numbers should not be over-interpreted into some thing more than: "GC can be expensive"
I later changed from a while loop to tail-recursion over a list which did improve the performance somewhat but not enough to warrant an update of the charts.
This is one of the ways:
let rec trim ls acc =
match ls, acc with
| [], _ -> acc
| h::[], acc -> List.rev acc
| h::n::t, [] -> trim t [n]
| h::t, acc -> trim t (h::acc)
let reslt = trim ls []
You didn't require standard library functions to achieve this, your're just asking for an efficient way. Defining a recursive function with an accumulator which holds the intermediate results would then appear a viable solution, even when the list has to be reversed at its termination.
I'm providing a custom Discriminated Union to keep track of the state, this is modelled along the lines of the Option type with an extra case.
type 'a State = Zero | One | Other of 'a
let skipFirstAndLast xss =
let rec aux acc = function
| _, [] -> List.rev acc
| Zero, x::xs -> aux acc (One, xs)
| One, x::xs -> aux acc (Other x, xs)
| (Other prev), x::xs -> aux (prev :: acc) (Other x, xs)
aux [] (Zero, xss)
[1..4] |> skipFirstAndLast // val it : int list = [2; 3]

How to set a timeout for tests with OUnit?

I have some tests on infinite lazy structures that might run indefinitely if the tested function is not correctly implemented, but I can’t find in the OUnit docs how to set a timeout on tests.
If you're using OUnit2, the following should work:
let tests =
"suite" >::: [OUnitTest.TestCase (
OUnitTest.Short,
(fun _ -> assert_equal 2 (1+1))
);
OUnitTest.TestCase (
OUnitTest.Long,
(fun _ -> assert_equal 4 (2+2))
)]
The type test_length is defined as:
type test_length =
| Immediate
| Short
| Long
| Huge
| Custom_length of float
I don't think that oUnit provides this functionality. I remember having to do this a while back and this is the quick hack I've come up with:
let race seconds ~f =
let ch = Event.new_channel () in
let timeout = Thread.create (fun () ->
Thread.delay seconds;
`Time_out |> Event.send ch |> Event.sync
) () in
let tf = Thread.create (fun () ->
`Result (f ()) |> Event.send ch |> Event.sync) () in
let res = ch |> Event.receive |> Event.sync in
try
Thread.kill timeout;
Thread.kill tf;
res
with _ -> res
let () =
let big_sum () =
let arr = Array.init 1_000_000 (fun x -> x) in
Array.fold_left (+) 0 arr in
match race 0.0001 ~f:big_sum with
| `Time_out -> print_endline "time to upgrade";
| `Result x -> Printf.printf "sum is: %d\n" x
This worked well enough for my use case but I'd definitely would not recommend using this if only because race will not work as you'd expect if ~f does no allocations or calls Thread.yield manually.

How to print a block of data in Ocaml?

I would like to print some rectangles one by one in a terminal like that:
4 5 7 8
2 5
3 : bool 6 : int
Which represents that, given an array a, the zone from a([2,3], [4,5]) is bool and the zone from a([5,6], [7,8]) is int.
So the key is to print a block of data in several rows, instead of 1 row as default. Does anyone know how to realize that in Ocaml?
Thank you very much!
Basically, there are two approaches possible:
accumulate your two-dimensional output and use a specialized print function which rearranges the strings in a way you wish
print to a medium with 2D capabilities like terminal or GUI element (to play with terminal screen, one can use a binding to ncurses)
The first approach is more universal and remains functional in spirit. For example:
let item1 =
[" 4 5 "
;"2 "
;"3 : bool "
]
let item2 =
[" 7 8 "
;"5 "
;"6 : int "
]
let transpose ll =
let rec pick_one ll =
match ll with
| [] -> []
| [] :: _ -> []
| _ ->
let tear (reaped, rest) l =
match l with
| [] -> assert false
| hd :: tl -> (hd :: reaped, tl :: rest)
in
let (reaped, rest) = List.fold_left tear ([], []) ll in
(reaped :: (pick_one rest))
in
pick_one ll
let multiline_print items =
let by_lines = transpose items in
let show_line line = List.iter print_string line; print_endline "" in
List.iter show_line by_lines
let _ = multiline_print [item1; item2]
Depending on your needs, you may build printf-like functionality around this.
You need to route through a "layout engine" the strings produced by the functions in your new Printf-like module.