Change a variable in standard ml list - list

I wonder when working with list in ml, how to change a variable with specific location of the list. For instance, when I have a list [1,2,3,4], I want to change the list to [1,2,5,4] with the 5 subtitle for the 3. What i'm thinking is to write a function that take a location, the variable and the list, return the new list with the update variable. For example,
change(i, var, list) = let val valup = var in (list # [i]) end
So with this code, if my input is change(2, 5, [1,2,3,4]), my out put will be [1,2,3,4,2] which incorrect compare to [1,2,5,4]. I'm new with ml and not good with the list setup in the language so any help would be really appreciate.

You have to realise that values are not mutable in ML. This means that once you create a value, you can't change it!
So if we have these two statements
x = [2,3,4]
y = 1::x
then y and x live in seperate memory locations on the computer.
What you can do is the following:
fun swapFirst [] y = raise Empty
| swapFirst (x::xs) y = y::xs
val test_swapFirst_00 = [1,2,3,4] = swapFirst [2,2,3,4] 1
which will swap the first element of a list out with something else.
Now I have a feeling that this could be for an answer for some course work, so I'm not going to give a complete code that solves your problem, but this information should at least clear some things up, and make it easier for you to solve the problem!

I come up with the solution for the problem.
fun change(i,v,[]) = raise Error
| change(0, v, x::xs) = v :: xs
| change(i, v, x::xs) = if i < 0 then raise Error
else x :: change((i-1), v, xs)

Related

Why do i get syntax error at end problem with pattern matching

I have to make a function that takes list a list and returns list of pairs of first and last element,2nd and 2nd last and so forth It doesn't matter if the list has even or odd number of elements because if its odd i will just ignore the middle element.The idea i have is that make a new rec fun that takes old list and its revers as input i think i finished the code but i get Syntax error for ;;
let lip l =
if [] then []
else let l1=l l2=List.rev l in
let rec lp l1 l2 = match l1,l2 with
| [],[] ->[]
| [],h2::t2->[]
| h1::_,h2::_ ->
if (List.length l -2) >= 0 then [(h1,h2)]# lp(List.tl l1) t2
else [] ;;
There are quite a few errors in your code.
I think the specific error you're seeing is caused by the fact that there is no in after let rec lp ....
Every let that's not at the top level of a module needs to be followed by in. One way to think of it is that it's a way of declaring a local variable for use in the expression that appears after in. But you need to have the in expr.
Another way to look at it is that you're defining a function named lp but you're not calling it anywhere.
As #lambda.xy.x points out, you can't say if [] then ... because [] isn't of type bool. And you can't say let x = e1 y = e2 in .... The correct form for this is let x = e1 in let y = e2 in ...
(Or you can write let x, y = e1, e2 in ..., which looks nicer for defining two similar variables to two similar values.)
The following code should at least compile:
let lip list1 =
if list1 = [] then []
else
let list2=List.rev list1 in
let rec lp l1 l2 = match l1,l2 with
| [], [] ->[]
| [], _::_->[]
| h1::_::_, h2::t2 -> (* l1 length >= 2*)
(h1,h2) :: lp(List.tl l1) t2
| h1::_,h2::t2 -> (* l1 length = 1 *)
[]
in
[]
I have made the following changes:
renamed the arguments of lip to make clear they are different from the arguments of lp
removed the alias let l1 = l
changed the if condition to a term of type boolean -- there's not much to compare, so I assume you are checking list1
replaced the list length condition by a pattern match against two heads
the else path is the second match - it might be better to rewrite that one to | [h1, _] -> ...
the definition of lp needs to be followed with the actual body of lip - to make it compile, we just return [] at the moment but you probably would like something else there
As #Jeffrey Scofield already mentioned, you are not using lp in your code. It could help if you added a comment that explains what you'd like to achieve and what the intended role of lp is.

Updating a list of 2-tuples in SML

I'm trying to update a running list of 2-tuples in SML. This is the same problem as: How can I update lists in SML using functions?
Unfortunately, the answer doesn't help. First, here is my code:
fun member(a, []) = false
| member((a, b), (c, d)::cds) = a = c orelse member((a, b), cds);
fun update([], (loc, v)) = [(loc, v)]
| update((y, z)::yzs, (loc, v)) =
if member((loc, v), (y, z)::yzs) then
if loc = y then (loc, v)::yzs
else (y, z)::update(yzs, (loc, v))
else (y, z)::yzs#[(loc, v)];
I am able to call the update function on FLR to create new values, but can only update the last value. In addition, when the last value is added and I call the update function again, it has not appended to FLR. Here's my example:
- val FLR = [(1,1),(2,4),(3,9),(4,16),(5,25)];
val FLR = [(1,1),(2,4),(3,9),(4,16),(5,25)] : (int * int) list
- update(FLR, (6,36));
val it = [(1,1),(2,4),(3,9),(4,16),(5,25),(6,36)] : (int * int) list
- update(FLR, (7,42));
val it = [(1,1),(2,4),(3,9),(4,16),(5,25),(7,42)] : (int * int) list
Instead of assigning the value to "it," is there a way for me to assign the value of the new list to FLR? In addition, I'm not able to add new values to an empty list? Any suggestions on that?
As Yawar pointed out, your code seems to work, but the idea of mutating variables to see updates must be replaced with shadowing bindings with newly created values that slightly different.
Your code can be simplified:
fun member ((x,_), xs) = List.exists (fn (y,_) => x = y) xs
fun update ([], (x,v)) = [(x,v)]
| update ((y,w)::pairs, (x,v)) =
if x = y
then (x,v) :: pairs (* replace (y,w) with (x,v), stop *)
else (y,w) :: update (pairs, (x,v)) (* keep (y,w), continue *)
That is, you don't need memberinside update to tell you whether the list needs updating or not, since that will require member to recurse through the list and return true or false with not much else to show for where the insert/replace should occur.
It seems a little asymmetric that member takes the pair first and the list second, while update takes the list first and the pair second. When designing APIs, try and make things consistent.
Doing yzs#[(loc, v)] is bad and probably, in your case, unnecessary. This insertion of a single element will loop through the entire list with the effect of the new pair ending at the end of the list. Instead of (y, z)::yzs#[(loc, v)] you could do (loc, v)::(y, z)::yzs to reduce this to a constant-time operation.

ML a real list return a real number

I am currently working on a ML small project and learning how to work with it, but here are some problems that I'm facing but cannot find any source online.
I want to have a function to return the last number of the list, which is a real number list. I wrote a code to return a single element real list, but i will it to be a real number but not a list. here is my code:
fun last [] = nil
| last(head::nil) = [head]
| last(head::list) = last(list)
I thought
last(head::nil)=head
would help get the real number but it just give me an error that:
operator domain: 'Z list list
operand: real list
Thank you!
As melpomene says, nil isn't a value of type real, so it can't be the return type for the empty list. In fact, no value can be returned, because the list is empty! This makes the function last partial. You want to avoid partial functions, because they may crash at runtime. You can define an alternative function, lastOpt:
fun lastOpt [] = NONE
| lastOpt [x] = SOME x
| lastOpt (_::xs) = lastOpt xs
For example,
- lastOpt [1,2,3];
> val it = SOME 3 : int option
- lastOpt [];
> val it = NONE : 'a option
This passes responsibility for handling empty lists explicitly to the caller of lastOpt.
The built-in function List.last was made unsafely with exceptions:
fun last [] = raise Empty
| last [x] = x
| last (_::xs) = last xs
I wouldn't recommend using this.

Writing multiple functions in SML - Sequential Composition

I would like to understand how sequential composition works much better than I do now in SML. I have to write a program that takes a list of integers and moves the integer at index zero to the last index in the list. ie. [4, 5, 6] -> [5, 6, 4].
The code I have right now is:
- fun cycle3 x =
= if length(x) = 1 then x
= else (List.drop(x, 1);
= x # [hd(x)]);
val cycle3 = fn : 'a list -> 'a list
The question lies in my else statement, what I want to happen is first concatenate the first term to the end, and then second drop the first term. It seems simple enough, I just don't understand how to perform multiple functions in a particular order using SML. My understanding was that the first function called has the scope of the second function that would have the scope of the third function.. etc etc.. What am I doing wrong here?
Most things in SML are immutable -- your function, rather than modifying the list, is building a new list. List.drop(x,1) evaluates to a new list consisting of all but the first element of x, but does not modify x.
To use your method, you would bind the result of List.drop(x,1) to a variable, as in the following:
fun cycle3 x = if length x = 1
then x
else let
val y = List.drop(x,1)
in
y # [hd(x)]
end
Alternately, a cleaner way of doing this same thing, that also handles the possibility of an empty list:
fun cycle3 [] = []
| cycle3 (x::xs) = xs # [x]

Update 'x'th element of list - Haskell [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Replace individual list elements in Haskell?
I have managed to make some progress in this part of my assignment but have attached part of the code below that I have made:
module Grid where
data State = On | Off deriving (Eq, Show)
next :: State -> State
next On = Off
next Off = On
type Row = [State]
updateRow :: Row -> Int -> Row
updateRow (r:rs) x
| x == 0 = next r:rs
-- | otherwise = ........????
As shown in the last line just above, I have managed to get updateRow to work for when x = 0, as shown below (with the 0th element inverted).
*Grid> updateRow [Off,Off,Off,Off] 0
[On,Off,Off,Off]
*Grid>
It all comes unstuck however when I try inverting other elements of this list. I can't seem to 'genralise' a formula in this function.
I also MUST follow THIS type convention:
updateRow :: Row -> Int -> Row
Thanks in advance.
Something like that:
module Grid where
data State = On | Off deriving (Eq, Show)
next :: State -> State
next On = Off
next Off = On
type Row = [State]
updateRow :: Row -> Int -> Row
updateRow (r:rs) x
| x == 0 = next r:rs
| otherwise = r : (updateRow rs (x-1))
updateRow [] x = []
Use the function provided for you in the previous question you asked. It works for lists of any type and I think it does what you want to do here.
How about a general update function?
update i a as = map repl $ zip as [0..] where
repl (a',i') | i == i' = a
| otherwise = a'
I guess there are more performant versions, but this one is easy to understand and good enough for short lists. It replaces the ith element (if there is any) in as with a.
Actually the idea for the otherwise part of your updateRow function is similar to the what you have in the replace of your other question.
The idea is: if x is not zero, then you want to skip the element r (which is at position zero) and call updateRow on rs at a position that is x - something (where something takes into account the one position that you just skipped).
I hope this helps