Trying to get square root in SML? - sml

Trying to work out how to get the square root in SML using this pseudocode:
sqrt x s = s if s*s <= x
sqrt x s = sqrt x (s-1) if s*s > x
This formulae was given to us by the lecturer, we have to solve the problem in SML.
I've tried it a few different ways, but I'll post the different ways with the errors via the console:
- fun sqrt x s = if ((s*s) <= x) then s | sqrt x s = if (s*s) > x then sqrt x (s - 1);
stdIn:32.39-32.45 Error: syntax error: deleting BAR ID
stdIn:32.52-32.56 Error: syntax error: deleting IF LPAREN
stdIn:32.59-32.62 Error: syntax error: deleting RPAREN ID
stdIn:32.65-32.74 Error: syntax error: deleting THEN ID
- fun sqrt x s = s if ((s*s) <= x) | sqrt x (s - 1);
stdIn:10.2-17.4 Error: syntax error: deleting IF LPAREN
stdIn:17.14 Error: syntax error found at RPAREN
- fun sqrt x s = s if s*s <= x | sqrt x (s - 1);
stdIn:10.2-17.4 Error: syntax error: deleting IF ID
- fun sqroot x s = s if s*s <= x | sqrt x (s - 1);
stdIn:17.2-17.6 Error: syntax error: deleting IF ID
- fun sqrt x s = s IF s*s <= x | sqrt x (s - 1);
= ;
= ;
= ;;
stdIn:17.28-34.2 Error: syntax error: deleting SEMICOLON SEMICOLON SEMICOLON
- fun sqrt x s = s IF s*s <= x END | sqrt x s = sqrt x (s-1) IF s*s > x END;
stdIn:17.12-17.15 Error: unbound variable or constructor: END
stdIn:10.2-17.2 Error: unbound variable or constructor: IF
stdIn:35.20-35.23 Error: unbound variable or constructor: END
stdIn:35.9-35.11 Error: unbound variable or constructor: IF
stdIn:1.17-17.15 Error: operator is not a function [circularity]
operator: 'Z
in expression:
(s <errorvar>) s
stdIn:1.17-17.15 Error: operator and operand don't agree [overload]
operator domain: 'Z * 'Z
operand: _ * (_ -> 'Y)
in expression:
(s <errorvar>) s * s
stdIn:1.6-35.23 Error: types of rules don't agree [literal]
earlier rule(s): (_ -> int) * (_ -> 'Z) -> bool
this rule: (_ -> int) * int -> bool
in rule:
(x,s) => (<exp> <exp>) s * s > x <errorvar>
stdIn:1.6-35.23 Error: right-hand-side of clause doesn't agree with function result type [literal]
expression: (_ -> 'Z) -> bool
result type: int -> _ -> int -> int
in declaration:
sqrt = (fn arg => (fn <pat> => <exp>))
Lines marked with a '-' are prompt input from me and all others are returned by the interactive system.
Any help is appreciated thanks.

#popovitsj Has a good inclination.
SML uses pattern matching to determine which version of the function definition to use.
fun sqrt x s = if ((s*s) <= x) then s | sqrt x s = if (s*s) > x then sqrt x (s - 1);
Is non-deterministic, and SML doesn't have the facility to backtrack and try another definition if the one it tries fails (i.e. like Prolog).
In this scenario you can just use
fun sqrt x s = if s * s <= x then s else sqrt x (s-1);
This function is logically valid only if you are passing it a value that when originally passed will fail the if expression.
I haven't tested this but I believe it should help.

Perhaps this is useful? The pseudocode implemented in Python:
def sqrt(x,s):
if (s*s <= x):
return s
return sqrt(x,s-1)
For SML, I can't check this, because I don't have an SML compiler, but perhaps this would work?
fun sqrt (x, s) = if s*s <= x then s else sqrt(x,s-1)

Related

using user-defined datatype as a type for a function argument

I have the following datatypes defined:
datatype Arguments
= IntPair of int * int
| RealTriple of real * real * real
| StringSingle of string;
datatype OutputArgs = IntNum of int | RealNum of real | Str of string;
and I try to create a function MultiFunc: Arguments -> OutputArgs:
fun MultiFunc(RealTriple (x, y, z)) : OutputArgs = RealNum ((x+y+z)/3.0)
| MultiFunc(IntPair (x,y)) : OutputArgs = IntNum (x+y)
| MultiFunc(StringSingle(s)) : OutputArgs = Str (implode(rev(explode(s))));
However when I call MultiFunc(1.0,2.0,3.0) I get the following error:
stdIn:588.1-588.23 Error: operator and operand don't agree [tycon mismatch]
operator domain: Arguments
operand: real * real * real
in expression:
MultiFunc (1.0,2.0,3.0)
I.e. for some reason it doesn't recognize the input argument as being a RealTriple.
MultiFunc(1.0,2.0,3.0)
for some reason it doesn't recognize the input argument as being a RealTriple.
That's because the input isn't a RealTriple, but a 3-tuple of reals (real * real * real).
Try instead:
- MultiFunc (RealTriple (1.0, 2.0, 3.0));
> val it = RealNum 2.0 : OutputArgs
Here's how I'd write the function:
fun multiFunc (RealTriple (x, y, z)) = RealNum ((x+y+z)/3.0)
| multiFunc (IntPair (x,y)) = IntNum (x+y)
| multiFunc (StringSingle s) = Str (implode (rev (explode s)))
By having function names start with a lowercase, I distinguish them visually from value constructors like RealTriple. I don't write : OutputArgs but let the type of the function be inferred instead. And I omit redundant parentheses like StringSingle(s) or explode(s): In many programming languages, function calls must have parentheses. In Standard ML, function application is achieved by juxtaposition of function on the left and argument on the right separated by whitespace. So f x is f being called on x, and (f x) y is "whatever f x returns, used as a function, on y."
You need to wrap your triple into the corresponding data constructor to explain to the compiler that you mean something of type Arguments and not just a triple of real numbers:
MultiFunc (RealTriple (1.0,2.0,3.0))

How can I divide two numbers in ML defined as a datatype?

I'm trying to write a recursive function in SML that receives two natural numbers n1,n2 and returns the result of n1 div n2
The datatype natural is defined as follows:
datatype natural = zero | Succ of natural
I want to write it in terms of the new datatype , or in other words, not by converting them to their regular form and converting back the result.
Any ideas how division is done in this definition?
You could start by defining subtraction:
exception Negative
fun sub (a, zero) = a
| sub (zero, b) = raise Negative
| sub (Succ a, Succ b) = sub (a, b)
From here, it should be pretty easy to simply count how many times you can subtract n2 from n1 without going negative. In particular, this equation should help:
n1 div n2 = 1 + (n1 - n2) div n2
I'll leave the rest to you.
Similar to Sam Westrick's definition, "number of times you can subtract n2 from n1 without going negative", you could also do integer division with addition and greater-than using the definition, "number of times you can add n2 to itself before it is greater than n1."
datatype nat = Z | S of nat
fun gt (S x, S y) = gt (x, y)
| gt (S _, Z) = true
| gt (Z, _) = false
fun add (x, Z) = x
| add (x, S y) = add (S x, y)
fun divide (_, Z) = raise Domain
| divide (x, y) = (* ... *)
Addition might seem like a conceptually simpler thing than subtraction. But greater-than is a more expensive operator than determining when a number is negative, since the case is incurred by induction, so Sam's suggestion would be more efficient.
You might test your solution with the following tests:
fun int2nat 0 = Z
| int2nat n = S (int2nat (n-1))
fun nat2int Z = 0
| nat2int (S n) = 1 + nat2int n
fun range (x, y) f = List.tabulate (y - x + 1, fn i => f (i + x))
fun divide_test () =
let fun showFailure (x, y, expected, actual) =
Int.toString x ^ " div " ^ Int.toString y ^ " = " ^
Int.toString expected ^ ", but divide returns " ^
Int.toString actual
in List.mapPartial (Option.map showFailure) (
List.concat (
range (0, 100) (fn x =>
range (1, 100) (fn y =>
let val expected = x div y
val actual = nat2int (divide (int2nat x, int2nat y))
in if expected <> actual
then SOME (x, y, expected, actual)
else NONE
end))))
end

SML: Function composition with isSome

I have the following examples and they do not work even though the types do matchup with each other
- isSome;
val it = fn : 'a option -> bool
- SOME;
val it = fn : 'a -> 'a option
- val my_converter = (fn x => if x = 5 then SOME x else NONE);
val my_converter = fn : int -> int option
Both SOME and my_converter return an option but when I do the following
- fn x => isSome o SOME x;
stdIn:19.9-19.24 Error: operator and operand don't agree [tycon mismatch]
operator domain: ('Z option -> bool) * ('Y -> 'Z option)
operand: ('Z option -> bool) * 'X option
in expression:
isSome o SOME x
I get a type error why?
The error message is telling you that o wants a function operand but what it actually gets is an option. This is because isSome o SOME x parses as isSome o (SOME x), which makes no sense.
You can fix this by writing
(isSome o SOME) x
instead.

"operator is not a function" on `$` Usage

Given the following:
// credit to http://stackoverflow.com/questions/28802305/trying-to-define-type
datatype 'alpha susp = $ of 'alpha
fun sum n = if n = 0 then 1
else n + sum(n-1)
What does this error mean?
- use "Lazy.sml";
[opening Lazy.sml]
datatype 'a susp = $ of 'a
val sum = fn : int -> int
val it = () : unit
- val foo = $sum 100000000000;
stdIn:17.5-17.28 Error: operator is not a function [tycon mismatch]
operator: (int -> int) susp
in expression:
($ sum) 100000000000
after you declare a new datatype, you should use it as a function(actually it is indeed turned into a function):
- datatype 'alpha susp = $ of 'alpha;
datatype 'a susp = $ of 'a
- fun sum n = if n = 0 then 1
= else n + sum(n-1);
val sum = fn : int -> int
- $(sum 10);
val it = $ 56 : int susp
- $;
val it = fn : 'a -> 'a susp
update
in your question, you have error:
- val foo = $sum 100000000000;
stdIn:17.5-17.28 Error: operator is not a function [tycon mismatch]
operator: (int -> int) susp
in expression:
($ sum) 100000000000
notice that:
[tycon mismatch]
and
operator: (int -> int) susp
in expression:
($ sum) 100000000000
it means it's a type error, the type mismatched. you should know function in sml takes only one parameter, so it's very easy to find out the association:
the expression $ sum 100000000000 is equivalent to (($ sum) 100000000000), which means you create a variable ($ sum) first, which has a type of (int -> int) susp, and then use it as a function and pass parameters to it, which cause this error.
actually the way you call this functions as a chain has a name in sml(or even in general functional programming), called curry. you can have a look at corresponding documentation.

error in the SML of NJ

hello everyone I have this snippet of the code:
local
fun NTimesF(f, n:int) =
if n = 1 then fn (x) => f(x)
else fn (x) => f(NTimesF(f, n - 1)(x))
in
fun compList f n = if n = 0 then []
else (NTimesF(f, n)) :: (compList f n-1)
end;
I need to write program which receives some function f and integer n and produce list of functions such as [f1, f2, ... fn] <- fn is the composition of the function n times but every time I receive an error:
- stdIn:7.11-7.46 Error: operator and operand don't agree [literal]
operator domain: ('Z -> 'Z) * ('Z -> 'Z) list
operand: ('Z -> 'Z) * int
in expression:
NTimesF (f,n) :: (compList f) n - 1
stdIn:6.6-7.46 Error: right-hand-side of clause doesn't agree with function result type [literal]
expression: int -> _ list
result type: int -> int
in declaration:
compList = (fn arg => (fn <pat> => <exp>))
-
can somebody please help me, thanks in advance
Because function application has higher precedence than the - operator, compList f n-1 is parsed as (compList f n) - 1, which is obviously not what you want.
You need to write compList f (n-1).