ML. How to correctly work with sequences - sml

So I have this "new" two way sequence:
datatype direction = Back | Forward;
datatype 'a bseq = bNil
| bCons of 'a * (direction -> 'a bseq);
and I need a function seq2bseq : 'a seq -> 'a seq -> 'a bseq that "appends" two regular sequences into one like so:
if seqUp is 0 1 2 3 4 ... and seqDown is -1 -2 -3 -4 ... then seq2bseq will create .. -4 -3 -2 -1 0 1 2 3 4 .. . In other words the starter element is the first of seqUp(0) so if I move Back I will get to the first element of seqDown(-1) and two the second of the seqUp(1) if I move Forward.
So far I wrote the following:
fun appendq (Nil, yq) = yq
| appendq (Cons(x,xf), yq) = Cons(x,fn()=>appendq(xf(),yq));
fun seq2bseq (DownSeq) (UpSeq) =
bCons(head(UpSeq), fn (Forward) => seq2bseq appendq(head(UpSeq), DownSeq) tail(UpSeq)
| (Back) => seq2bseq tail(DownSeq) appendq(head(DownSeq), UpSeq) );
for which I get the following errors:
stdIn:28.101-28.153 Error: operator and operand don't agree [tycon mismatch]
operator domain: 'Z seq * 'Z seq -> 'Z seq
operand: 'Y seq -> 'Y seq
in expression:
seq2bseq tail
stdIn:27.5-28.155 Error: right-hand-side of clause doesn't agree with function result type [tycon mismatch]
expression: _ seq -> _ bseq
result type: _ * _ -> ('Z seq -> 'Z seq) -> _ seq -> _
in declaration:
seq2bseq = (fn arg => (fn <pat> => <exp>))
I can't figure out what's wrong(:/). Help!
Thanks!
Edit: working(?) code at: http://www.beetxt.com/mkX/.

Your type errors appear to be coming from a lack of parenthesization.
If you have functions foo and bar, and want to call foo on the result of calling bar on the value baz, then you need to write this as foo (bar baz) or foo (bar (baz)), if you prefer.
Writing foo bar(baz) will cause foo to be called with the argument bar, which will likely not type-check.
Try:
fun seq2bseq (DownSeq) (UpSeq) =
bCons(head(UpSeq),
fn Forward => seq2bseq (appendq(head(UpSeq), DownSeq)) (tail(UpSeq))
| Back => seq2bseq (tail(DownSeq)) (appendq(head(DownSeq), UpSeq))
)

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

operator and operand do not agree [tycon mismatch]

I am trying to write a function in sml that takes in a list of pairs and returns pair of two list of all the elements
Meaning if the input is [(1, 2.0), (2, 3.0)]
The output should be ([1, 2], (2.0, 3.0))
fun divide nil = (nil , nil)
| divide [(a, b)::nil] = ([a], [b])
| divide [(a, b)::myTl] =
let
val (x, y) = divide myTl
in
(a::x, b::y)
end
;
Never the less the sml interpreter returns the following err
Error: operator and operand do not agree [tycon mismatch]
operator domain: ('Z * 'Y) list list
operand: ('Z * 'Y) list
in expression:
divide myTl
The error message you're seeing is because you've (inadvertently) declared a function with domain ('a * 'b) list list due to your input patterns, so your recursive call is not well typed.
The most straightforward fix is to correct for the incorrect use of [ ] around the argument to the function---this is making a singleton list, instead of just grouping the pattern. Thus you'd want to use ( ) instead.
fun divide nil = (nil , nil)
| divide ((a, b)::nil) = ([a], [b])
| divide ((a, b)::myTl) =
let
val (x, y) = divide myTl
in
(a::x, b::y)
end
Your second base case is also extraneous, so we could further revise this to
fun divide [] = ([], [])
| divide ((a, b)::xs) =
let
val (x, y) = divide xs
in
(a::x, b::y)
end

Product of Tree Elements SMLNJ

I have the following qtree datatype:
datatype 'a qtree = Leaf of 'a
| Node of 'a branches
and 'a branches = Empty
| Branch of 'a qtree * 'a branches
An example tree is defined as follows:
val tr1 =
Node(Branch(Leaf(2),
Branch(Node(Branch(Leaf(6),
Branch(Leaf(5),Empty))),
Branch(Node(Empty),Empty))))
Here is a visual representation of tr1:
/|\
/ | \
2 / \
/ \
6 5
I have defined the following function tree_prod to find the product of the values in a qtree:
fun tree_prod(Leaf(n)) = n
| tree_prod(Empty) = 1
| tree_prod(Node(br)) = tree_prod(br)
| tree_prod(Branch(n, br)) = tree_prod(n) * tree_prod(br)
But I am receiving the following errors, which seem to occur due to a type mixup between qtree and branches:
stdIn:10.5-13.42 Error: parameter or result constraints of clauses don't
agree [tycon mismatch]
this clause: 'Z branches -> 'Y
previous clauses: 'X qtree -> 'Y
in declaration:
tree_prod =
(fn Leaf n => n
| Empty => 1
| Node br => tree_prod br
| Branch (<pat>,<pat>) => tree_prod <exp> * tree_prod <exp>)
stdIn:10.5-13.42 Error: parameter or result constraints of clauses don't
agree [tycon mismatch]
this clause: 'Z branches -> 'Y
previous clauses: 'X qtree -> 'Y
in declaration:
tree_prod =
(fn Leaf n => n
| Empty => 1
| Node br => tree_prod br
| Branch (<pat>,<pat>) => tree_prod <exp> * tree_prod <exp>)
stdIn:12.19-12.27 Error: operator and operand don't agree [tycon mismatch]
operator domain: [int ty] qtree
operand: [int ty] branches
in expression:
tree_prod br
stdIn:13.24-13.42 Error: operator and operand don't agree [tycon mismatch]
operator domain: [int ty] qtree
operand: [int ty] branches
in expression:
tree_prod br
How do I fix these errors?
Bonus: How do I implement this function using fold?
Your tree_prod attempts to apply to both types, which won't work - you need two functions.
If it's possible for you to change the type, you can use the fact that 'a branches is isomorphic to a list of 'a qtree (with Empty as nil and Branch as cons).
datatype 'a qtree = Leaf of 'a
| Node of ('a qtree) list
and then you can fold over the branches:
fun tree_prod (Leaf n) = n
| tree_prod (Node br) = List.foldl (fn (tree, acc) => tree_prod tree * acc) 1 br
val tr1 = Node [Leaf 2, Node [Leaf 6, Leaf 5], Node []]
- tree_prod tr1;
val it = 60 : int
If you don't want to change the type, you can write your own fold over 'a branches, following the same form as a list-fold.
Something like this might do it:
fun branch_fold f x Empty = x
| branch_fold f x (Branch t bs) = branch_fold f (f (t, x)) bs
and would give an almost identical "product":
fun tree_prod (Leaf n) = n
| tree_prod (Node br) = branch_fold (fn (tree, acc) => tree_prod tree * acc) 1 br
I have located the answer on my own. By dividing this into two separate functions, I am able to specify which types I am wanting to work with.
Here is the working solution:
fun tree_prod (Leaf(n)) = n
| tree_prod (Node(br)) = branches_prod(br)
and branches_prod (Empty) = 1
| branches_prod (Branch(n, br)) =
tree_prod(n) * branches_prod(br)

ERROR: String list list instead of string list

I have this function that results a string list:
fun get_substitutions1 ([],_) = []
| get_substitutions1 (x::xs,s) = case all_except_option(s,x) of
NONE => [] #get_substitutions1(xs,s)
| SOME lst => lst #get_substitutions1(xs,s)
And this function that takes a string list list and a type:
fun similar_names(slist,full_name:{first:string,middle:string,last:string})=
let
fun aux(slist,acc)=
case full_name of
{first=a,middle=b,last=c} => case get_substitutions1(slist,a) of
[] => full_name::acc
| x::xs' => full_name:: aux(xs',{first=x,middle=b,last=c}::acc)
in aux(slist,[])
end
And i get an error:
Error: operator and operand don't agree.
operator domain: string list list *
{first:string, last:string, middle:string} list
operand: string list *
{first:string, last:string, middle:string} list
in expression:
aux (xs',{first=x,middle=b,last=c} :: acc)
Is there any other way?
Well first of all you might wan't to indent your code so that it is readable.
It is quite obvious why you get the error you do. The function
fun get_substitutions1 ([],_) = []
| get_substitutions1 (x::xs,s) =
case all_except_option(s,x) of
NONE => []#get_substitutions1(xs,s)
| SOME lst => lst #get_substitutions1(xs,s)
has the type
val get_substitutions1 = fn : ''a list list * ''a -> ''a list
and you are trying to use the result of this function in your inner case expression where you take the tail of the returned list (type 'a list) and use them in the recursive function call.
fun similar_names(slist,full_name:{first:string,middle:string,last:string})=
let
fun aux(slist,acc)=
case full_name of
{first=a,middle=b,last=c} =>
case get_substitutions1(slist,a) of
[] => full_name::acc
| x::xs' => full_name:: aux(xs',{first=x,middle=b,last=c}::acc)
in aux(slist,[])
end
However since your first argument of aux is used in get_substitutions1, that argument must be of type 'a list list, but the xs' you use down in the recursive call is only of type 'a list.

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