I am new to SML, but would like to get some experience with a strongly typed language. I've been looking at tutorials and I copied a simple factorial function:
fun Factorial n =
if n = 0 then 1
else n * Factorial (n-1);
However, I am not sure how to save this program (Factorial.sml) in order to run it later. Also, I am confused as to how I pass an argument to this function; how would I run this function with n=5?
Related
Is it possible to write a C++ function like if we enter 9 then the program return 6 and if we input 6 the program return us 9 as output? Without using any conditional statement?
You are asking for functions that satisfy:
f(x) = y
f(y) = x
for some fixed x and y.
You can look for involutions, which are functions that satisfy:
f(f(x)) = x
Search for those that you can implement without conditionals, which usually means using only integers and the built-in arithmetic operators.
For instance, XOR:
f(x) = x ^ N
for some fixed N that you adjust using the given x/y.
I want to convert a sequence to a list using List.init. I want at each step to retrieve the i th value of s.
let to_list s =
let n = length s in
List.init n
(fun _i ->
match s () with
| Nil -> assert false
| Cons (a, sr) -> a)
This is giving me a list initialized with the first element of s only. Is it possible in OCaml to initialize the list with all the values of s?
It may help to study the definition of List.init.
There are two variations depending on the size of the list: a tail recursive one, init_tailrec_aux, whose result is in reverse order, and a basic one, init_aux. They have identical results, so we need only look at init_aux:
let rec init_aux i n f =
if i >= n then []
else
let r = f i in
r :: init_aux (i+1) n f
This function recursively increments a counter i until it reaches a limit n. For each value of the counter that is strictly less than the limit, it adds the value given by f i to the head of the list being produced.
The question now is, what does your anonymous function do when called with different values of i?:
let f_anon =
(fun _i -> match s () with
|Nil -> assert false
|Cons(a, sr) -> a)
Regardless of _i, it always gives the head of the list produced by s (), and if s () always returns the same list, then f_anon 0 = f_anon 1 = f_anon 2 = f_anon 3 = hd (s ()).
Jeffrey Scofield's answer describes a technique for giving a different value at each _i, and I agree with his suggestion that List.init is not the best solution for this problem.
The essence of the problem is that you're not saving sr, which would let you retrieve the next element of the sequence.
However, the slightly larger problem is that List.init passes only an int as an argument to the initialization function. So even if you did keep track of sr, there's no way it can be passed to your initialization function.
You can do what you want using the impure parts of OCaml. E.g., you could save sr in a global reference variable at each step and retrieve it in the next call to the initialization function. However, this is really quite a cumbersome way to produce your list.
I would suggest not using List.init. You can write a straightforward recursive function to do what you want. (If you care about tail recursion, you can write a slightly less straightforward function.)
using a recursive function will increase the complexity so i think that initializing directly the list (or array) at the corresponding length will be better but i don't really know how to get a different value at each _i like Jeffrey Scofield said i am not really familiar with ocaml especially sequences so i have some difficulties doing that:(
I am new to SML and I have written a program that takes 3 integer numbers (n,z,k) and wants to compare them with a value given in the program, if the statement is correct it will return true, else false. conditions and values should be equal simultaneously, I mean program will return true if all these numbers are equal to the value given in the program, so my if statement should check 3conditions at the same time.
my problem is that I don't know how I can write all these 3conditions in one if clause, because SML don't recognize for example & or ^ as and!
for example i want to check whether if(n==8 && k==5 && z==9). what should I use instead of &
here is the code:
fun EvalR (n: int , k: int , z:int) =
if (n=8 ???) then true
else false;
Since Ashkan Parsa referred to the CS317 SML Style Guide, I thought I would point out what you might derive from it.
Let function names start with a lower case, e.g. evalR.
Don't write if ... then true else false; simply write ....
Some disagree; type annotations certainly are helpful, but so is type inference.
As nazila says, the and operator in Standard ML is called andalso.
So,
fun evalR (n, k, z) =
n = 42 andalso k = 43 andalso z = 0
It might seem comfusing that the function body contains =s at the same time as the function being defined with a = to separate the function arguments from the function body. Just think of the latter =s as value operators and the first = as a part of declaring things (like types, values, functions, etc.)
I found it. we can use andalso in SML.
I have to generate an infinite list containing a Fibonacci sequence. I am new to ML so I want to check if this is correct.
-datatype 'a infist=NIL
= | CONS of 'a * (unit -> 'a inflist);
- fun fib a b = CONS (a , fn()=> fib b (a+b));
val fib=fn: int->int-int inflist
Is this what is called a generator function?
Will it give me an actual output i.e the infinite fib sequence when I give a and b inputs?
Your datatype definition and your function definition seem correct. Although I still would have preferred a Fibonacci function that does not expect any arguments, to avoid the possibility of getting wrong input:
fun fibonacci () =
let
fun fib(a,b) = Cons(a+b, fn() => fib(b,a+b))
in
Cons(0, fn()=> fib(0,1))
end
This is what I would call a stream
When you invoke it, it'll give an element of type infislist. You may consider writing some other functions to process your stream and interpret its contents. You may want see some examples of this in my another answer, for example, functions like takeWhile, take, filter, zip and toList.
I am trying to write a code which checks if number is Fibonacci or not in ML. I am a beginner. Help me find out what is the problem with my code.
fun isfib(n :int): bool=
let
val a1=1;
val a2=1;
val temp=0;
in
while a2<n do (
a1=temp
a2=a1
a2=temp+a2
)
if a2=n then true
else false
end;
a1=temp
a2=a1
a2=temp+a2
= is the equality operator in SML, not an assignment operator. So the above code is just equivalent to this:
false (* because a1 is 1, but temp is 0 *)
true (* because a1 and a2 are both 1 *)
true (* because 1 = 0 + 1 *)
So you have three side-effect-free expressions in your loop, so it just won't do anything.
It's clear that you actually want to change the values of those variables, but you can't do that. Variables in SML are immutable - you can't change them after they're set. So even having a while condition like a2 < n doesn't make sense because a2 and n can't change, so the condition is either always true or always false. If you want to use a while loop like this, you should look into the ref type, which allows you to create mutable values that you can use to simulate mutable variables.
That said using while loops and mutation is not idiomatic SML. There's a reason why variables in SML aren't mutable: the language designers want to encourage you to not rely on mutation (and thus also not on while loops). The idiomatic way to loop in SML is to either use higher order functions (like map, filter, foldl etc.) or recursion. For your problem a recursive function would make the most sense.