Define nested functions in standard ml - sml

I am new in sml. I tried to convert int to int list. For example, assume that there is an input 1234, then output is a list like [1,2,3,4]. And my question is, how can I type nested functions in sml? let in end? There is my code.
fun digit (a : int): int =
let
fun size (a) = if a < 0 then nil
else x = Int.toString x then digit s = size(x)
fun insert (num, nil) = [num]
| insert (num,xs) = x :: insert ()
fun convert (a, s) = if s < 0 then nil
else insert (a / (10*(s - 1)), xs)
then convert(a - (10*(s - 1), s - 1)
in
end

Nested functions are just one way to split up your workload in multiple, smaller parts. Another option is non-nested library functions. The main differences are that functions that aren't nested don't inherit its parent's variable scope, so they can only work with their own input, and functions that are nested aren't available anywhere else and can't be re-used. Let's say you're giving this problem a first stab:
fun digit_meh n = if n < 10 then [n] else n mod 10 :: digit_meh (n div 10)
And you realize it isn't doing exactly as you want:
- digit_meh 1234;
> val it = [4, 3, 2, 1] : int list
You could remove the most significant digit first, but the calculation isn't as trivial as n mod 10, since it depends on the number of digits.
You could generate this list and then reverse it:
fun digit n = rev (digit_meh n)
But the function digit_meh isn't particularly useful outside of this function, so it could be hidden using local-in-end or let-in-end:
local
fun digit_meh n = if n < 10 then [n] else n mod 10 :: digit_meh (n div 10)
in
val digit = rev o digit_meh
end
fun digit n =
let fun meh n = if n < 10 then [n] else n mod 10 :: meh (n div 10)
in rev (meh n) end
Do notice that the function meh's copy of n shadows digit's copy of n.
For clarity you could also name the variables differently.
Or you could look at how rev is doing its thing and do that. It basically treats its input as a stack and puts the top element in a new stack recursively so that the top becomes the bottom, much like StackOverflow's logo would look like if it jumped out and landed upside down like a slinky spring:
fun rev L =
let fun rev_stack [] result = result
| rev_stack (x::xs) result = rev_stack xs (x::result)
in rev_stack L [] end
Because the result is accumulated in an additional argument, and rev should only take a single argument, nesting a function with an extra accumulating argument is a really useful trick.
You can mimic this behavior, too:
fun digit N =
let fun digit_stack n result =
if n < 10
then n::result
else digit_stack (n div 10) (n mod 10::result)
in f N [] end
This way, we continue to treat the least significant digit first, but we put it in the stack result which means it ends up at the bottom / end. So we don't need to call rev and save that iteration of the list.
In practice, you don't have to hide helper functions using either local-in-end or let-in-end; while it can be useful in the case of let-in-end to inherit a parent function's scope, it is not necessary to hide your functions once you start using modules with opaque signatures (the :> operator):
signature DIGIT =
sig
val digit : int -> int list
end
structure Digit :> DIGIT =
struct
fun digit_stack n result =
if n < 10
then n::result
else digit_stack (n div 10) (n mod 10::result)
fun digit n = digit_stack n []
end
As this is entered into a REPL, only the relevant function is available outside of the module:
> structure Digit : {val digit : int -> int list}
signature DIGIT = {val digit : int -> int list}
- Digit.digit 1234;
> val it = [1, 2, 3, 4] : int list

fun aFunctionCallingF2F3 someVariables =
let
<define some functions and local variables here>
fun F2 ...
fun F3 ...
val v1 ...
val v2 ...
in
<Make use of the functions/variables you defined above and `someVariables`>
end
For example,
fun areaCirle r:real =
let fun square x:real = x*x
val pi = 3.14
in
pi * square r
end
Or define functions you need to call beforehand if they are not mutually recursive. If they are mutually recursive, you can look up the keyword and.
fun F2 ...
fun F3 ...
fun aFunctionCallingF2F3 = <make use of F2 F3 directly>
For example,
fun square x:real = x * x
fun areaCircle r = square r * 3.14
Note that you cannot do
fun areaCircle r = square r * 3.14
fun square x:real = x * x
square needs to be defined before areaCircle.

Related

Can we use an assert statement inside a function in OCaml?

I wrote a simple recursive fibonacci program that works fine without an assert statement, but when I add an assert statement, even with various permutations of parentheses, spaces, and double semicolons, I keep getting a syntax error during compilation.
Working function:
let rec fib n =
if n = 1
then 1
else
n*(fib (n-1))
Not working:
let rec fib n =
assert (n>=0)
if n = 1
then 1
else
n*(fib (n-1))
Any thoughts appreciated.
Thanks.
You have two expressions: assert (n >= 0) and if ... then ... else .... If you want the two expressions to be evaluated in sequence (which you do), you need to separate them with a semicolon:
let rec fib n =
assert (n >= 0);
if n = 1 then 1
else n * fib (n - 1);;
val fib : int -> int = <fun>
# fib 3;;
- : int = 6
# fib (-3);;
Exception: Assert_failure ("//toplevel//", 2, 4).
Extra spaces do not affect the semantics of OCaml programs. There are also no statements per se in OCaml - everything is an expression. To evaluate two expressions in a sequence you may use the semicolon, e.g.,
print_endline "Hello";
assert (1 > 2);
print_endline "World";
You can also use let .. in .. to chain expressions, especially, if you need to the expression values, e.g.,
let x = 1 + 2 in
let y = 3 + 4 in
Format.printf "%d + %d = %d\n" x y (x + y)
Going back to your example, it should be
let rec fib n =
assert (n >= 0);
if n = 1 then 1
else n * fib (n - 1)
P.S. The double semicolons are not really a part of the language but a special input sequence to be used in the interactive toplevel.

f# concatenate list of objects

type Googol = {
number : float
power : float
result : float
}
let generatePowers (n:float) : list<Googol> =
let rec powerInner (n:float) (p:float) (acc : list<Googol>) =
match n with
| p when p <= 1.0 -> acc
| p when p > 1.0 -> powerInner n (p-1.0) ([{ number=n; power=p; result=n**p}]#acc)
let rec numberInner (n:float) (acc : list<Googol>) =
match n with
| n when n <=1.0 -> acc
| n when n >1.0 -> numberInner (n-1.0) ((powerInner n [])#acc)
numberInner n []
ProjectEuler.fsx(311,50): error FS0001: This expression was expected to have type
'Googol list'
but here has type
'Googol list -> Googol list'
I am trying to solve this problem -> https://projecteuler.net/problem=56 | but for this I need to generate powers below n < 100. When I try to concatenate [{ number=n; power=p; result=n**p}]#acc
these lists I get the error above. Explain please why error says 'Googol list -> Googol list' is in the function, does I plug a function as a parameter to the function or I plug the actual list when just after concatenation. Is # a function?
This looks like homework or practice, so first I'll give some hints to move on. Finally I'll show a version that seems to work, and then tell how I would approach the problem.
The task is to find the number a ** b, for a and b less than 100, that has the highest sum of its own digits.
The first problem is that float won't give us all the digits of a ** b, so that type is useless to solve the problem. To fix that, we turn to the BigInteger type, and the BigInteger.Pow function. Then we get a 1 followed by 200 zeroes if we run the following snippet, just like it says in the problem description.
let x: bigint = BigInteger.Pow (100I, 100)
let x: string = string x
printfn "s=%s" x
To get useful results, change the Googol type so that it uses bigint, except for power that should be an int.
Why are the functions powerInner and numberInner inside the function generatePowers? This doesn't seem to have a specific purpose, so I suggest moving them out to make this clearer.
The function powerInner do a match on n, but then goes on to name the results p, which shadows the p parameter so that it is unused. Ok, the intention here is probably to match on p rather than n, so just fix that, and then the shadowing of the p parameter is perfectly fine.
The tests first on <= 1 and then on > 1 causes incomplete matches. If the first line checks that the number is less or equal to one, then it must the greater than one in the next line. So just use n -> without the when to fix that. I also suspect you want to test <= 0 instead of 1.
This
[{ number=n; power=p; result=n**p}]#acc
can be just
{ number=n; power=p; result=n**p } :: acc
and here
(powerInner n [])
I suspect you just need a starting value for the power, which would be 99
(powerInner n 99 [])
SPOILER WARNING
After a bit of tinkering, this is what I ended up with, and it seems to print out a useful list of numbers. Note that in order to not run through all 99 by 99 results with printouts, I've used low starting numbers 3 and 5 for the countdowns here, so we get some simple printout we can study for analysis.
type Googol = { number: bigint; power: int; result: bigint }
let rec powerInner (n: bigint) (p: int) (acc: Googol list) =
match p with
| p when p <= 0 -> acc
| p ->
let newNumber = { number = n; power = p; result = n ** p }
printfn "newNumber=%0A" newNumber
powerInner n (p - 1) (newNumber :: acc)
let rec numberInner (n: bigint) (acc: Googol list) =
match n with
| n when n <= 0I -> acc
| n -> numberInner (n - 1I) ((powerInner n 5 []) # acc)
let generatePowers (n: bigint) : Googol list =
numberInner n []
let powers = generatePowers 3I
I'm not sure if this solution is correct. I'd do it differently anyway.
I would simply loop through a and b in two loops, one inside the other. For each a ** b I would convert the result to a string, and then sum the digits of the string. Then I'd simply use a mutable to hold on to whichever result is the highest. The same could be achieved in a more functional way with one of those fancy List functions.
You're missing a parameter here:
| n when n >1.0 -> numberInner (n-1.0) ((powerInner n [])#acc)
^^^^^^^^^^^^^^^
here
powerInner is defined with three parameters, but you're only passing two.
In F# it is not technically illegal to pass fewer parameters than defined. If you do that, the result will be a function that "expects" the remaining parameters. For example:
let f : int -> int -> string
let x = f 42
// Here, x : int -> string
let y = x 5
// Here, y : string
So in your case omitting the last parameter makes the resulting type Googol list -> Googol list, which then turns out to be incompatible with the type Googol list expected by operator #. Which is what the compiler is telling you in the error message.

OCaml: pell function with int lists

I am trying to write a simple function in OCaml
let rec pell (i: int) =
(if i <= 2 then i (*if given n is less tahn 2 then return 2, else return previous n-1 th term and n-2 nd term recursively*)
else if i>2 then
2 * pell i - 1 + pell i - 2
else failwith "unimplemented" (*else fail with unimplemented message*)
);;
Write an infinite precision version of the pell function from before
pell2 0 = []
pell2 1 = [1]
pell2 7 = [9; 6; 1]
pell2 50 = [2; 2; 5; 3; 5; 1; 4; 2; 9; 2; 4; 6; 2; 5; 7; 6; 6; 8; 4]
I have written below code for this:
let rec pell2 i =
(if i <= 2 then
[] -> i;
else if i=0 then [];
else if i>2 then (*finding pell number and using sum function to
output list with infinite precision...*)
[] -> pell2 i-1 + pell2 i-2;
else failwith "unimplemented"
);;
but still has some syntax errors. Can someone help me with this please.
if i <= 2 then
[] -> i
In snippets like this, the -> is invalid. It looks like you might be mixing pattern matching with match ... with ... and if/else up.
Also, you're first checking if i is less than or equal to 2, but then you have an else to test for i being equal to zero. The first check means the second is never going to happen.
First, let's look at the examples for the output of pell2. We see that pell2 has a single integer parameter, and returns a list of integers. So, we know that the function we want to create has the following type signature:
pell2: int -> int list
Fixing (some but not all of) the syntax errors and trying to maintain your logic,
let rec pell2 i =
if i=0 then []
else if i <= 2 then i
else if i>2 then pell2 i-1 + pell2 i-2
Note that I removed the semicolons at the end of each expression since OCaml's use of a semicolon in its syntax is specifically for dealing with expressions that evaluate to unit (). See ivg's excellent explanation on this. The major flaw with this code is that it does not type check. We see that we conditionally return a list, and otherwise return an int. Notice how above we defined that pell2 should return an int list. So, we can begin fixing this by wrapping our int results in a list:
let rec pell2 n =
if n = 0 then []
else if n <= 2 then [n]
else ... something that will return the Pell number as a list ...
As you have already written, the else branch can be written using recursive calls to the pell2 function. However, we can't write it as you did previously, because pell2 evaluates to a list, and the binary operator + only works on two integers. So, we will have to define our own way of summing lists. Calling this sum_lists, we are left with the following code:
We can now fully define our function pell2:
let rec pell2 n =
if n = 0 then []
else if n <= 2 then [n]
else (* Pell(n) = (2 * Pell(n-1)) + Pell(n-2) *)
let half_of_first_term = pell2 n-1 in
let first_term = sum_lists half_of_first_term half_of_first_term in
let second_term = pell2 n-2 in
sum_lists first_term second_term
So, all that is left is to define sum_lists, so that we are properly summing together two lists of the same format as the return type of pell2. The signature for sum_lists would be
sum_lists: int list -> int list -> int list
I'll give a basic outline of the implementation, but will leave the rest for you to figure out, as this is the main crux of the assignment problem.
let sum_lists lst1 lst2 =
let rec sum_lists_helper lst1 lst2 carry =
match lst1, lst2 with
| [], [] -> if carry = 1 then [1] else []
| h::t, []
| [], h::t -> ...
| h1::t1, h2::t2 -> ...
in
sum_lists_helper lst1 lst2 0

OCaml variable counting

I am trying to achieve the following: Finding the element at a specific index.
So if I had a list of [5; 2; 3; 6] and ask for the element at index 2, it would return 3.
let counter = 0;;
let increase_counter c = c + 1;;
let rec get_val x n = match x with
[] -> -1
| (h::t) ->
if (counter = n) then
h
else
increase_counter counter ; get_val t n
;;
But this code is giving me a bug saying that -1 is not of type 'unit'?
As Jeffrey Scofield said, you should write let counter = ref 0 to make counter mutable. Now, you can use the built in incr function to increment it (equivalent to counter := !counter + 1), and you'll get its value with !counter.
There is also a problem in your algorithm : if the counter is equal to n, you return the head of the list... you mean : if the head of the list is equal to n, you return the counter.
Your program is then :
let counter = ref 0;;
let rec get_val x n = match x with
[] -> -1
| (h::t) ->
if (h = n) then
!counter
else
begin incr counter ; get_val t n end
;;
Note that I've added begin and end around the else block so it can be interpreted as a sequence of instructions.
Your program now works, but it is not the best way to solve this problem with ocaml.
You should write something like
let get_val x n =
let rec get_val_aux x n counter = match x with
| [] -> -1
| h :: _ when h = n -> counter
| _ :: t -> get_val_aux t n (succ counter)
in
get_val_aux x n 0
;;
Here, we add a parameter to the get_val_aux function which we increment at each call. This function is nested within the get_val function to hide this additional parameter which is initialized with 0 on the first call.
Instead of using an if statement, we use the when condition to know when the element has been found, and add a new case to match the last case (not found). Note the use of the _ wildcard to avoid an unused variable.
The succ function (for successor) only adds 1 to its parameter. It is equivalent to counter + 1.
There are many problems with this code. If you ignore your immediate problem for a moment, you are treating OCaml variables like the variables of an imperative language. However, OCaml variables are immutable. This function
let increase_counter c = c + 1
Doesn't change the value of any variable. It just returns a number 1 bigger than what you give it.
The only error I get from the toplevel when I enter your code is for this expression:
increase_counter counter ; get_val t n
The compiler is warning you that the expression before ; is supposed to be executed for its side effects. I.e., it should almost always have type unit. Since (as I say) your function increase_counter returns an int, the compiler is warning you about this.

building a list of ints in ocaml

I want to write a function that does builds a list between two ints, inclusive
rec myFunc x y would build a list with all the ints between x and y, including x and y
For the logic right now I have something like this:
let rec buildList i n = let x = i+1 in if i <= n then i::(buildList x n)
But this gives me an error "Expression has type 'a list but but an expression was expected of type unit.
I thought buildList is returning a list of ints, and i as an int, so the cons operator would be valid, but its saying it should be void?
Why does this happen, and how do I fix it?
If the condition is true, you return the list i::(buildList x n). If it's not true, what do you return ?
Add else [] to your function to return the empty list when the condition is not met.
When you don't have any else, the compiler supposes it is else () (hence the error message).
Your if is missing an else condition
I suggest that you use a tail recursive function:
let buildList x y =
let (x,y) = if x<y then (x,y) else (y,x) in
let rec aux cpt acc =
if cpt < x then acc
else aux (cpt-1) (cpt::acc)
in aux y []
First, make sure that you ordered your boundaries correctly (idiot-proof), and then construct the list thank to a local recursive function which takes an accumulator.
Two alternatives relying on batteries' package,
Using unfold, which purpose is to build list,
let range ~from:f ~until:u =
BatList.unfold f (function | n when n <= u -> Some (n, succ n) | _ -> None)
Using Enum, allowing to work with lazy datastructure,
# BatList.of_enum ## BatEnum.(1--9);;
- : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9]
My suggestion, this respects the ordering of the arguments.
let rec iota n m =
let oper = if n < m then succ else pred in
if n = m then [n] else n :: iota (oper n) m
Edit:
The operator selection is inside the recursive part, it should better be outside like this:
let iota n m =
let oper = if n < m then succ else pred in
let rec f1 n m = if n = m then [n] else n :: f1 (oper n) m in
f1 n m
At more than 200000 elements I get a stack overflow (so here we are)
# iota 0 250000;;
Stack overflow during evaluation (looping recursion?).
Todo: tail recursion
let buildList i n =
let rec aux acc i =
if i <= n then
aux (i::acc) (i+1)
else (List.rev acc)
in
aux [] i
Test:
# buildList 1 3;;
- : int list = [1; 2; 3]
# buildList 2 1;;
- : int list = []
# buildList 0 250000;;
- : int list =
[0; 1; 2; 3; .... 296; 297; 298; ...]