syntax error: inserting LPAREN - sml

This is my first time with sml.
I don't understand what is wrong with this syntax:
fun merge (l1 : int list , l2 : int list) : int list =
if ([] , l2) then l2
else if (l1 , []) then l1
else (x :: xs , y :: ys)
if x < y then x :: (merge (xs , l2))
else y :: (merge (l1 , ys)));
Please help

The problem is that the if / then / else syntax is not used for pattern-matching. (You've melded two unrelated syntaxes.)
So, for example, if ([] , l2) does not work, because the condition in an if expression needs to have type bool, which ([], l2) does not.
Instead, you want to write:
fun merge ([], l2) = l2
| merge (l1, []) = l1
| merge (l1 as x :: xs, l2 as y :: ys) =
if x < y
then x :: merge (xs, l2)
else y :: merge (l1, ys)

Related

What's wrong with my guard-based haskell code for halving a list?

Here is the code:
listhalve :: [a] -> ([a],[a])
listhalve (x:xs)
| length [x] == length xs = ([x],xs)
| length [x] < length xs = listhalve ([x] ++ head xs : tail xs)
| length [x] > length xs = ([x],xs)
There are no error messages when I run or compile it, it just runs forever in the case of non-pair lists.
I'm aware of different ways to write this function that work. I just want to know what's wrong with this code specifically.
Upon taking your comments to heart, I came up with this code here:
listhalve :: [a] -> ([a],[a])
listhalve xs = listhalve' [] xs
where
listhalve' :: [a] -> [a] -> ([a],[a])
listhalve' x y
| length x == length y = (x, y)
| length x < length y = listhalve' (x ++ (head y)) (tail y)
| length x > length y = (x, y)
This gives me an error reading:
test.hs:7:56: error:
* Occurs check: cannot construct the infinite type: a1 ~ [a1]
* In the second argument of `(++)', namely `(head y)'
In the first argument of listhalve', namely `(x ++ (head y))'
In the expression: listhalve' (x ++ (head y)) (tail y)
* Relevant bindings include
y :: [a1] (bound at test.hs:5:22)
x :: [a1] (bound at test.hs:5:20)
listhalve' :: [a1] -> [a1] -> ([a1], [a1]) (bound at test.hs:5:9)
|
7 | | length x < length y = listhalve' (x ++ (head y)) (tail y)
|
What's the problem with this code?
Consider that listhalve ([x] ++ head xs : tail xs) is the same as listhalve ([x] ++ xs) which is the same as listhalve (x:xs) which is what you went in with, so endless recursion results.
The error is fixed, and the second function works, when you specify head y to be a list, i.e. [head y]. The full, corrected function looks like this:
listhalve :: [a] -> ([a],[a])
listhalve xs = listhalve' [] xs
where
listhalve' :: [a] -> [a] -> ([a],[a])
listhalve' x y
| length x == length y = (x, y)
| length x < length y = listhalve' (x ++ [head y]) (tail y)
| length x > length y = (x, y)

Standard ML :How to cycle through a list?

I am trying to write a program that cycle through a list n times.
Suppose that L = [a1, a2, ... , an]
What I am trying to achieve is [ai+1, a i+2, ... , an, a1, a2, ... , ai].
I referenced to a previous post about this exact problem. However, I am not sure how to obtain the output or [ai+1, a i+2, ... , an, a1, a2, ... , ai].
For the output: I tried
-cycle([1,2,3,4], 5);
However the error that I am getting is that the operand and operator don't match
This is the code I found from the previous post:
fun cycle n i =
if i = 0 then n
else cycle (tl n) (i-1) # [hd(n)];
A way to do this using if-then-else:
fun cycle xs n =
if n = 0
then []
else xs # cycle xs (n - 1)
You might instead like to use pattern matching:
fun cycle xs 0 = []
| cycle xs n = xs # cycle xs (n - 1)
But the most elegant solution, I think, is using higher-order functions:
fun cycle xs n =
List.concat (List.tabulate (n, fn _ => xs))
A slightly harder task is how to write a cycle for lazy lists that cycles infinitely...
datatype 'a lazylist = Cons of 'a * (unit -> 'a lazylist) | Nil
fun fromList [] = Nil
| fromList (x::xs) = Cons (x, fn () => fromList xs)
fun take 0 _ = []
| take _ Nil = []
| take n (Cons (x, tail)) = x :: take (n - 1) (tail ())
local
fun append' (Nil, ys) = ys
| append' (Cons (x, xtail), ys) =
Cons (x, fn () => append' (xtail (), ys))
in
fun append (xs, Nil) = xs
| append (xs, ys) = append' (xs, ys)
end
fun cycle xs = ...
where take 5 (cycle (fromList [1,2])) = [1,2,1,2,1].

Split list with map

How can I replicate the function of the List module: "List.split", with map?
I've found a way to do it with fold_right, but I don't quite understand how to do it with map...
let split l =
List.fold_right(fun (x, y) (xs, ys) -> (x :: xs, y :: ys)) l ([], []);;
It could be something as simple as:
let split l =
(List.map (fun (a, _) -> a) l,
List.map (fun (_, b) -> b) l)

Haskell own function to merge two lists

I need to write a function to merge two lists. Exactly like '++' is working.
let x = merge [1,2,3] [3,3,4] -- should output [1,2,3,3,3,4]
How should it be done?
Edit: solution is
merge :: [a] -> [a] -> [a]
merge [] ys = ys
merge (x:xs) ys = x : (merge xs ys)
Maybe something like this.
merge :: (a -> a -> Bool) -> [a] -> [a] -> [a]
merge pred xs [] = xs
merge pred [] ys = ys
merge pred (x:xs) (y:ys) =
case pred x y of
True -> x: merge pred xs (y:ys)
False -> y: merge pred (x:xs) ys
(++) xs ys = merge (\x y -> compare x y == LT) xs ys
Or, if you just need to repeat the functionality of (++), you can look up it's definition with hoogle which eventually leads you to the source code
(++) [] ys = ys
(++) (x:xs) ys = x : xs ++ ys

F# continuations goes on StackOverflowException

Hi guys I'm implementing an F# function that takes two lists of type : (int*float) list. These two lists have different lentgths.
The int element of the couple is an increasing code.
What I wanted to do is create a new list that will contain a couple (int*float) for each two elements of the two lists that have the same code. It's important to note that codes in lists are in increasing order.
These lists are probably a little long, like 2-3000 elements., so I tried to implement this function using continuation passing style in order to avoid StackOverflowExceptions. but sadly i failed.
This is the function, i hope you will give me any hints!
let identifiedDifference list1 list2 =
let rec produceResult (l1, l2) k =
match l1,l2 with
| [],[]
| _,[]
| [],_ -> k []
| (code,rate:float)::xs, (code2,rate2)::ys ->
if code = code2
then
produceResult (xs, ys) (fun c -> (code,Math.Abs(rate-rate2))::(k c))
elif code > code2
then produceResult (l1, ys) k
else produceResult (xs, l2) k
produceResult (list1, list2) id
I've done something wrong?
(fun c -> (code,Math.Abs(rate-rate2))::(k c))
should be
(fun c -> k ((code,Math.Abs(rate-rate2))::c))
to make it tail-recursive:
let identifiedDifference list1 list2 =
let rec produceResult (l1, l2) k =
match l1,l2 with
| [],[]
| _,[]
| [],_ -> k []
| (code,rate:float)::xs, (code2,rate2)::ys ->
if code = code2 then produceResult (xs, ys) (fun c -> k ((code,Math.Abs(rate-rate2))::c))
elif code > code2 then produceResult (l1, ys) k
else produceResult (xs, l2) k
produceResult (list1, list2) id
This will also fix your results being returned in reverse order.
The problem lies in this line
produceResult (xs, ys) (fun c -> (code,Math.Abs(rate-rate2))::(k c))
Here you invoke continuation but this call is not tail because you still need to cons (code,Math.Abs(rate-rate2)) to the result of (k c)
I guess you can build result list from the inside out and just reverse final result:
let identifiedDifference list1 list2 =
let rec produceResult (l1, l2) k =
match l1,l2 with
| [],[]
| _,[]
| [],_ -> k []
| (code,rate:float)::xs, (code2,rate2)::ys ->
if code = code2
then
produceResult (xs, ys) (fun c -> k((code,Math.Abs(rate-rate2))::c))
elif code > code2
then produceResult (l1, ys) k
else produceResult (xs, l2) k
produceResult (list1, list2) List.rev
EDIT:
after second look I think CPS is not needed here and using accumulator should do the trick:
let identifiedDifference list1 list2 =
let rec run l1 l2 acc =
match l1, l2 with
| [], _ | _, [] -> List.rev acc
| (code1, rate1 : float)::xs, (code2, rate2)::ys ->
if code1 = code2 then
run xs ys ((code1, abs (rate1 - rate2))::acc)
elif code1 > code2 then
run l1 ys acc
else
run xs l2 acc
run list1 list2 []
For an alternative answer, take a look at this: http://fssnip.net/75
The function takes a couple of sequences and returns pairs which match according to some matching function. I haven't volume-tested it.
The function is actually used in the larger snippet here: http://fssnip.net/76