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

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.

Related

SML recursive type error when converting numbers to nat form

I am practicing SML and getting the following recursive type error. Is ML complaining about type recursive and needs some type hints? I am confused.
datatype 'a nat =
Zero
| Succ of 'a
;
fun to_nat(v) = if v = 0 then Zero else Succ(to_nat(v - 1));
fun plus(n1,n2) =
case n1 of
Zero => n2
| Succ(v) => Succ(plus(v, n2))
;
fun multiply(n1,n2) =
case n1 of
Zero => Zero
| Succ(v) => plus(multiply(v, n2), n2)
;
val five = to_nat(5);
val six = to_nat(6);
val eleven = plus(five, six);
val thirty = multiply(five, six);
Error:
Standard ML of New Jersey v110.79 [built: Sat Oct 26 12:27:04 2019]
[opening lambda.sml]
datatype 'a num = Succ of 'a | Zero
lambda.sml:6.5-6.60 Error: right-hand-side of clause doesn't agree with function result type [circularity]
expression: 'Z num
result type: 'Z
in declaration:
to_num = (fn v => if <exp> = <exp> then Zero else Succ <exp>)
/usr/lib/smlnj/bin/sml: Fatal error -- Uncaught exception Error with 0
raised at ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
I believe you made a mistake in defining your data type. You want Succ to take a value of type 'a nat rather than 'a.
datatype 'a nat = Zero | Succ of 'a nat;
The 'a parameter makes no sense, and is probably what lead you down the wrong path.
(For instance, Succ "hello" or Succ ([1], true, "world") seem very odd constructs of natural numbers.)
You want just
datatype nat =
Zero
| Succ of nat

Ocaml : Function with 'a option error

I have this simple function which drives me crazy:
it should be a function of this type :
myfunction : (int * int list) list -> int -> int
For each tuples of the first argument :
When the second argument matches the first element of the tuple then the function return the last element of the list in the tuple.
If no matches it should return -1.
let rec myfunction alist anum =
let last_e l =
let len = List.length l in
List.nth l (len - 1) in
match alist with
| [] -> -1
| (n , ln) :: q -> if n = anum then last_e ln
else myfunction q anum
But my function does not work and I have this error message in utop:
Error: This expression has type 'a option but an expression was expected of type int
I don't know where the "option" type comes from.
This can happen if you are using some OCaml toplevel (e.g. utop) and you have these lines in your .ocamlinit file
#require "core.top" ;;
open Core.Std ;;
This enables the Core libraries, where List.nth has type:
μ> List.nth;;
- : 'a list -> int -> 'a option = <fun>
instead of standard OCaml's List.nth : 'a list -> int -> 'a.
So, when you fire up your toplevel and say:
μ> #use "myfunction.ml";;
you get the same error you cited in the question.
By the way, if you'd like to keep using Core, there is a List.last function.

Error: This expression has type (int * int) option but an expression was expected of type 'a * 'b

If i put this code to utop line by line, then it works, but if I compile it as programm, then I see error.
module List = Core.Std.List;;
let () =
let shifts = [ (-1, -1); (0, -1) ] in
let first = List.nth shifts 0 in
let (a, b) = first in
Printf.printf "%d %d\n" a b;
;;
And error message:
Error: This expression has type (int * int) option
but an expression was expected of type 'a * 'b
What wrong with types and why it works in utop?
It looks to me like Core.Std.List.nth has the type 'a list -> int -> 'a option in order to handle the case when the int is out of range. The standard library List.nth has the type 'a list -> int -> 'a. It raises an exception for an out-of-range int.
If you're using Core.Std.List in one case but the standard List in the other, this would explain the difference.

How to check recursive call results in CPS codes

So I'm working on a function to find some valid arithmetic operations to a target number from an int list. It's not allowed to use throw/callac. Only add and mul are valid arithmetic operations here and they are left associative.
datatype operation = ADD | MULT
(* find_op: int -> int list -> (operatino list -> 'a) -> (unit -> 'a) -> 'a *)
fun find_op x [] s k = k()
| find_op x [y] s k = if x=y then s([]) else k()
| find_op x (y1::y2::ys) s k =
let
val add = find_op x ((y1+y2)::ys) (fn a => s(ADD::a)) k
val mul = find_op x ((y1*y2)::ys) (fn a => s(MULT::a)) k
in
need some work here
end
The function should work like below:
Given list [1,1,2,~1] and target number ~4, the accpeted operation list should be [ADD,ADD,MULT] or [ADD,MULT,MULT], because (((1+1)+2)*~1) = ((1+1)2~1) = ~4. But [MULT,ADD,MULT] will not be valid since (((1*1)+2)*~1) = ~3.
I'm confused how to check whether returned results are k(). Using = to check return value is not possible since it is polymorphic. Is there any method to handle this?
What you have to do is use the two strategies, first try reducing the numbers via ADD, then reduce the numbers via MULT, but sequentially. In order to do this you need to provide a custom failure continuation (k) to the result of the first chosen strategy. If that strategy fails, you try the second strategy in the continuation failure.
You can't try both strategies at the same time and have them both succeed. The function type does not permit returning multiple correct answers. For that you'd need the success continuation's type to be operation list list.
datatype operation = ADD | MULT
fun opToString ADD = "ADD"
| opToString MULT = "MULT"
(* find_op: int -> int list -> (operation list -> 'a) -> (unit -> 'a) -> 'a *)
fun find_op x [] s k = k ()
| find_op x [y] s k = if x = y then s [] else k ()
| find_op x (y1 :: y2 :: ys) s k =
let
(* You need a custom failure continuation that tries the MULT variant
* if the ADD one fails.
*)
fun whenAddFails () =
find_op x ((y1 * y2) :: ys) (fn a => s (MULT :: a)) k
val add =
find_op x ((y1 + y2) :: ys) (fn a => s (ADD :: a)) whenAddFails
in
add
end
fun test () =
let
val opList = [1,1,2,~1]
val target = ~4
fun success ops =
"success: " ^ (String.concatWith " " (List.map opToString ops))
fun failure () =
"couldn't parse numbers as an operation list"
in
find_op target opList success failure
end

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).