I have an assignment that involves making church numerals in SML. I've looked around and just can't find what I'm doing wrong. The goal is to make a function that takes an int and returns a church numeral, defined as datatype 'a numeral = Num of ('a -> 'a) -> 'a -> 'a (which is predefined by my teacher). Then to make a second function that takes a church numeral and returns an int.
I saw a previous post with the code:
val ZERO = C(fn (f,x) => x)
fun subCreate 0 (f,x) = x
| subCreate n (f,x) = f (subCreate (n-1) (f,x))
fun create n = C(fn (f,x) => subCreate n (f,x));
fun churchToInt (c, cn) = cn ((fn x => x+1), 0) 0;
but this does not work, and gives the error type vars not generalized because of value restriction are instantiated to dummy types.
When I used the code:
val zero = fn s => fn x => x;
(to define a zero) and then
val next = fn n => fn s => fn x => (f ((n s) x));
(just to do a test to see if I could increment zero, before setting up an iterative or recursive function), I got the same error. I've spent hours on this problem, unable to produce a church numeral. Can someone point me in the right direction?
I think you are running into the "value polymorphism" in SML'97. Here is a very long section of documentation discussing it.
One workaround is, whenever you have an expression which causes this problem, e.g. next zero, wrap a function around it, e.g. fn x => next zero x.
Another thing I think you could do is instead of evaluating definitions at the top level in the interpreter, wrap the definition and all the code that uses it into local scope (e.g. inside let ... in ... end) or into functions.
Related
I have written a method to return the first element in a list that satisfies a function (passed in via currying). The function returns NONE or SOME depending on whether or not the element satisfies a condition. I'm using Pattern Matching
However, I'm getting the dreaded error:
Error: unbound variable or constructor: my_function
I'm new to SML and one of the hardest things I find is understanding the error messages. From previous experience with the message, I would think the problem is that my_function never returns, but I'm having trouble seeing the logic problem here. Can someone take a quick look and tell me the problem? Is the problem that I'm raising an error when there is no element that satisfies the input function f?
I'm interested in what's wrong and perhaps more importantly, is there any way to get more information when you see this sort of error?
val my_function = fn f => fn lst => (* Notice currying *)
case lst of
[] => raise NoAnswer (* Get here is nothing in lst saf
| x::xs => case f(x) of NONE => ( my_function f xs)
| SOME y => x
val test = my_function(fn x => if x < 3 then SOME x else NONE) [1,2,3,4] = 2
Thanks, Dave
If you declare a function with the val keyword, the function can't be defined recursively. Hence, the problem is here:
... NONE => ( my_function f xs) ...
You can say that you want the function to be defined recursively by adding the rec keyword to the declaration.
val rec my_function = fn f => fn list => ...
Alternatively, the fun keyword is syntactic sugar for val rec. fun also includes nice syntactic sugar for currying:
fun my_function f lst = (* This is equivalent to your first line *)
Sometimes you still want to use just the val keyword and not val rec. For instance,
val f = fn x => x + 3
val f = fn y => f y + 4 (* f here refers to the previous declaration of f *)
I'm solving an old exam to practice SML. One task I found interesting was: Write a function repeat that executes another function with the signature 'a -> 'a.
I assumed the requested function is a curry function and used the o-Operator:
fun repeat (1, f: 'a->'a) = f
| repeat (n, f: 'a->'a) = f o repeat (n-1, f);
However, the o operator was not formally introduced in out course, and I wonder how I could write this without it?
Not the less verbose, but in some way, the most explicit, then after, the less verbose, with explanations.
A curried function is a function getting a single argument. If an expression has more arguments, then there are as many nested functions. The first outer level function gets an argument, and is made of an inner level function which may it‑self be made of an inner function, and so on. Any of this inner level function may be returned, not just the innermost, as explained later (this is a kind of “partial evaluation”). An inner function is “specialized” with the arguments (formally, the arguments are bound in a closure) of the outer functions.
We know there are at least a function argument f and integer argument counter. There needs to be an argument seed also, to invoke the function f the first time.
The order of nesting may be arbitrary or specified. If not specified, I personally prefer to put the least varying arguments on the outer‑scope and the most varying in the inner‑scope. Here, I would say it is, from least to most varying: f, counter seed.
This is already enough to suggest the beginning of a template:
val repeat: ('a -> 'a) -> int -> 'a -> 'a =
fn f: 'a -> 'a =>
fn count: int =>
fn seed: 'a =>
…
We already implemented the ('a -> 'a) -> int -> 'a part of the signature. Remains the last -> 'a which means an 'a is to be returned, and it will be evaluated by an inner loop.
A loop may be something of this form (in pseudo‑code):
val rec loop = fn i =>
if condition-to-stop
then return-something-or-`()`
else loop (i + 1) or (i - 1)
If the loop is to compute something, it will need an extra argument acting as an accumulator, and will return that accumulator as its final result.
Implementing the loop and putting it inside the curried function template above, we get:
val repeat: ('a -> 'a) -> int -> 'a -> 'a =
fn f: 'a -> 'a =>
fn count: int =>
fn seed: 'a =>
let
val rec loop = fn (counter, x) =>
if counter <= 0 then x
else loop (counter - 1, f x)
in
loop (count, seed)
end
Do you understand the let … in … end construct here?
Note the guard on counter may use a pattern as you did, but as SML's integer may be negative (there is no strict natural in SML), that's safer to catch this case too, thus the if … then … else instead of a pattern matching. Mileage may vary on that point, but that's not the question's focus.
The same as above, using fun instead of val rec:
fun repeat (f: 'a -> 'a) (count: int) (seed: 'a): 'a =
let
fun loop (counter, x) =
if counter <= 0 then x
else loop (counter - 1, f x)
in
loop (count, seed)
end
Note for repeat the arguments are not separated by a , (neither a *). This is the way to write a curried function using fun (on the contrary, loop is not curried). Compare it with the prior val version of the same function. If no type is specified and only names, the parenthesis can be omitted.
A test function to be used as the f argument:
val appendAnX = fn s: string => s ^ "x"
The test:
val () = print (repeat appendAnX 5 "Blah:")
Curried function are more abstract than function getting a tuple (which is formally a single argument, thus makes a curried function too, but that's another story and a bit cheating), as the outer function(s) may be partially applied:
This is a partial application, leaving the last argument, seed, unbound:
val repeatAppendAnXThreeTimes = repeat appendAnX 3
Then this function may be applied specifiying only this seed:
val () = print (repeatAppendAnXThreeTimes "Blah:")
Similarly, both counter and seed may be left free:
val repeatAppendAnX = repeat appendAnX
val () = print (repeatAppendAnX 4 "Blah:")
Another way of defining repeatAppendAnXThreeTimes. Compare it to its other definition above:
val repeatAppendAnXThreeTimes = repeatAppendAnX 3
val () = print (repeatAppendAnXThreeTimes "Blah:")
I have to write a function to print a list in SML with the following type signature :
val printGenList = fn : ('a -> 'b) -> 'a list -> unit
The "printGenList" will take two arguments function f and list l and applies the function f to each element of list l recursively.
Since I am new to ML, I am not able to implement it but I tried this code which is giving the different type signature
fun printGenList = CONS(fib, fn => printGenList fib fibs);
where, fib is
fun fib a b = CONS(a, fn => fib b (a+b));
and fibs is
val fibs = fib 0 1;
What you're trying to do is impossible, ML's type system doesn't support this type of polymorphism. If you Google, there are some printf libraries for SML that show you how to approach this -- for each type t that you want to print, you'll need to define a separate t -> unit function and compose them together.
EDIT: Oh, I see, you're not looking for a function to print lists of any type, you're looking for a higher order function that applies an 'a->'b function to every element of a list... my mistake. This is what you need:
val rec printGenList =
fn (f : 'a -> 'b) =>
(fn [] => ()
| x::xs => (f(x); printGenList f xs))
I am trying to find the the greatest value in a list using Standard ML. I need to use the given fold function:
fun fold f [] base = base
| fold f (x::xs) base = fold f xs (f x base);
Here is what i have so far:
fun max (x::xs) = fold (fn (a, b) => if a > b then a else 0) x (x::xs);
I have 0 in there because if the list is empty then I need to return 0;
This is only part of another function that I need to define, but I'm struggling with the fold part.
In your definition of the fold function, you require that the function f must take it's arguments in curry form, that is: f 1 1 instead of f(1,1).
As I understand, then your definition of the fold function is the right one. Thus you need to make proper changes to the anonymous function in the max function.
In SML, currying is actually just syntactic sugar. For example:
fun foo a b = a+b
would end up as (after desugaring):
val rec foo = fn a => fn b => a+b
It is also seen that the two functions has the same type:
- fun foo a b = a+b;
val foo = fn : int -> int -> int
- val rec foo = fn a => fn b => a+b;
val foo = fn : int -> int -> int
Thus the anonymous function must be define somewhat along the same lines.
Also you have mixed the arguments to fold. In the last part of the max function, you are giving the two last arguments in the reverse order.
The last problem is that your anonymous function returns 0. This screws with the invariant of you anonymous function and makes it fail in some cases. For example:
max [1,4,65,7,6];
Try to figure out why yourself.
If you really need to return 0 if the input list to max is empty, then you should pattern match that case. This also fixes the warning about "match nonexhaustive", and is the correct place to do it.
fun max [] = 0
| max (x::xs) = fold (fn a => fn b => if a > b then a else b) (x::xs) x;
I have to create a function about peano numbers defined as the following datatype:
datatype 'a peano = P of ('a -> 'a) * 'a -> 'a
val zero = P(fn (f, x) => x)
The function that I have to implement finds the succesive peano number of the peano parameter P(p). This is what I have written:
fun suc (P(p)) = case P(p) of P(fn(f,x)=>x) => P(fn(f,x)=>f(x));
The problem is that i get these errors:
stdIn:4.33-4.36 Error: syntax error: deleting FN LPAREN
stdIn:4.43 Error: syntax error found at RPAREN
I don't know what Im doing wrong. Please help!
There are a number of problems in this code. The one the compiler is whining about is that you have a function definition
fn (f,x) => x
on the left-hand side of a case arm, where only patterns are permitted.
Some other problems:
Redundant parentheses make the code hard to read (advice is available on removing them).
Your case expression is redundant; in the function definition
fun suc (P p) = ...
it should be possible just to compute with p without any more case analysis.
Since P carries a function, you will probably have an easier time if you write
fun suc (P f) = ...
and make sure that in the result, f is applied to a pair (as required by the datatype declarations).