Updating List Elements, Haskell - list

I have homework where I am to update a list using a function that takes two elements and returns a value of part of the first element given in the function. So it's required to update the entire listing by going through each element and update its value by applying the function against all other elements in the list (including itself).
So far I've been trying to firstly map the list (so that each element is done the same) and then specifically update each elements value by mapping again just the value of the specified element however in trying to map just the specific value through: the function, the specific element and the entire list I keep getting complaints that I'm inferring the list of values made from the 'map function p#list list' rather than simply giving the value at p#list.
Here is a sample of what I've been trying to implement:
res :: X -> X -> Z -- function given
myf :: [X] -> [X] -- Here is my function
myf ps = map newf ps
where
newf p#(X oldz) = X newz
newz = map (res p) ps
Is this the correct method to try to update a list against the entire list itself?
EDIT: spelling mistakes and grammar- my apologies on not also putting the homework tag on it

Is this the correct method to try to update a list against the entire list itself?
I'm not sure that code is correct for any task.
Looks like you assumes that p#(X oldz) is taking element from list with constructor X oldz and names it p. But...
You need to describe how to behave when your list get changed after map (res p) is applied.
If all your "changes" to list should be made only based on initial values of list and be applied in order from first element to last:
myf ps = (buildPlan ps) ps where
buildPlan [] = id
buildPlan (x:xs) = map (res x) . buildPlan xs
Some may prefer:
myf ps = changesPlan ps where
change x = map (res x)
changesPlan = foldr (.) id (map change ps)
If your "changes" to list should take changes from previous map (res x) (in non-func language while walking through list you change all elements even those which will be taken at next iteration):
myf ps0 = rebuildFrom 0 ps0 where
rebuildFrom n ps | n >= length ps = ps
rebuildFrom n ps = rebuildFrom (n+1) ps' where
x = ps !! n
ps' = map (res x) ps

Related

Insert number into sorted list using List.fold_right

I am trying to insert a number x into a sorted list l using Ocaml's List.fold_right and return the list with the inserted element. I have figured out a way to insert it if the element is to go at the front of the list or in the middle of the list, however I cannot figure out how to code the case where the element is larger than every element in the list and thus must go at the end.
Here is what I have so far:
let insert_number (x: int) (l: int list): int list =
List.fold_right l ~f:(
fun cur -> fun acc ->
if x < cur then cur::x::accum
else cur::accum
) ~init: []
Using this with a test case like:
insert_number (3) ([1; 2; 4]);;
- : int list = [1; 2; 3; 4]
gives the correct answer. However, with a test case like this:
insert_number (3) ([1; 2]);;
- : int list = [1; 2]
the number is not inserted because it should be added to the end of the list.
Could someone help me understand how I am supposed to integrate this case into the function used with List.fold_right.
A fold works by passing along a set of state as it iterates over each element in a list (or other foldable data structure). The function passed in takes both the current element and that state.
I think you're really really close, but you need as Jeffrey suggests a boolean flag to indicate whether or not the value has been inserted. This will prevent multiple insertions and if the flag is still false when the fold is done, we can detect that and add the value to insert.
This match also serves the purpose of giving us an opportunity to discard the no longer needed boolean flag.
let insert v lst =
match List.fold_right
(fun x (inserted, acc) ->
if v > x && not inserted then (true, x::v::acc)
else (inserted, x::acc))
lst
(false, []) with
| (true, lst) -> lst
| (_, lst) -> v::lst
One way to look at List.fold_right is that it looks at each element of the list in turn, but in reverse order. For each element it transforms the current accumulated result to a new one.
Thinking backward from the end of the list, what you want to do, in essence, is look for the first element of the list that's less than x, then insert x at that point.
So the core of the code might look something like this:
if element < x then element :: x :: accum else element :: accum
However, all the earlier elements of the list will also be less than x. So (it seems to me) you need to keep track of whether you've inserted x into the list or not. This makes the accumulated state a little more complicated.
I coded this up and it works for me after fixing up the case where x goes at the front of the list.
Perhaps there is a simpler way to get it to work, but I couldn't come up with one.
As I alluded to in a comment, it's possible to avoid the extra state and post-processing by always inserting the element and effectively doing a "local sort" of the last two elements:
let insert_number x l =
List.fold_right (
fun cur -> function
| [] when x > cur -> [cur; x]
| [] -> [x; cur]
| x::rest when x > cur -> cur::x::rest
| x::rest -> x::cur::rest
) l []
Also, since folding doesn't seem to actually be a requirement, here's a version using simple recursion instead, which I think is far more comprehensible:
let rec insert_number x = function
| [] -> [x]
| cur::rest when cur > x -> x::cur::rest
| cur::rest -> cur::insert_number x rest

Using monad for cumulative sum on list of pairs (haskell)

I have a list of pairs structure [("oct",1),("nov",1),("dec",1)]
I want to calculate sum within pairs: [("oct",1),("nov",2),("dec",3)]. I think this is a good case for monadic implementation, but can't figure out how to preserve containers.
I tried to make function on lists (I already know about scanl1, just showing effort here :)
csm (x:[]) = [x]
csm (x:y:xs) = x : csm ((x + y) : xs)
And then try something like:
sumOnPairs l = do
pair <- l
return (csm (snd pair))
My solution is not working, please point me in the right direction
The list monad models nondetermism: do the same thing to each element of the list, then collect the results in a new list.
For the type of sequential traversal you want (do something to an element, then use the result to do something to the next element, etc), you can use the State monad to do something like
import Control.Monad.Trans.State
import Data.Bifunctor
type Pair = (String, Int)
foo :: Pair -> State Pair Pair
foo (month, y) = do
-- bimap f g (x,y) == (f x, g y)
-- The new month replaces the old month,
-- and y is added to the sum.
modify (bimap (const month) (+y))
-- Return a snapshot of the state
get
sumOnPairs :: [Pair] -> [Pair]
sumOnPairs = flip evalState ("", 0) . traverse foo
At each step, the new state is the current month and the sum
of the old state's number and the current number. traverse accumulates
those states in a list while traversing the original list.
> sumOnPairs [("oct",1),("nov",1),("dec",1)]
[("oct",1),("nov",2),("dec",3)]
You can also keep only the sum in the state, rather than a month that just gets replaced and the sum.
foo' :: Pair -> State Int Pair
foo' x#(_, count) = do
modify (+ count)
fmap (<$ x) get
sumOnPairs' :: [Pair] -> [Pair]
sumOnPairs' = flip evalState 0 . traverse bar
In this case, only the current sum is kept in the state; the new pair is generated by using the <$ operator, which the Functor instance of (,) String to replace the number in the current pair with the sum in the state
> 6 <$ ("foo", 3)
("foo", 6)
I think using Data.Functor.($>) (the flipped version of <$) might be more readable, if you choose this route.
foo' x#(_, count) = do
modify (+ count)
fmap (x $>) get
Visually, it's more similar to what you could write if you didn't need to map over get: x $> y == (fst x, y).

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.

Saving an appended list in Ocaml

Context:
I am trying to define a function in ocaml that inserts an element x in a list, at either the head or the tail of the list, based off of whether the new element is less than the current head of the list.
The Problem:
The problem is that when I run some code that I created (shown at bottom), my list is going back to its original state and not saving the append that was previously done. I realize that I can just do this with an easy let statement of a new variable or the same, but I would like to just save the new list as its current form. Can this even be done in ocaml without the creation of a new list?
My question is: How can I append to a list, and save it in its new form, without the creating of a new list or variable.
Research:
I was looking at this answer on SO, and have incorporated it in my code already. However, when I run this code:
let rec insertion x y =
match y with
| [] -> x::y
| h::tl -> if h >= x then x::y
else y#[x]
;;
, accompanied by:
let y = [1;2;3];;
insertion 0 y ;;
y ;;
I return:
val y : int list = [1; 2; 3]
- : int list = [0; 1; 2; 3]
- : int list = [1; 2; 3]
It is impossible. OCaml's list is immutable, you can't change it. You can't change its values, you can't change its length.

SML: get index of item in list

I'm new to SML and I'm attempting to get the index of an item in a list. I know that using List.nth will give me the value of an item at a index position, but I want the index value. There may even be a built in function that I'm not aware of. In my case, the list will not contain duplicates so if the item is in the list I get the index, if not it returns ~1. Here is the code I have so far. It works, but I don't think it is very clean:
val L=[1,2,3,4,5];
val m=length L-1;
fun Index(item, m, L)=if m<0 then ~1 else
if List.nth(L, m)=item then m else Index(item,m-1,L);
To elaborate on my previous comment, I suggest some changes for an implementation that fits better in the ML idiom:
fun index(item, xs) =
let
fun index'(m, nil) = NONE
| index'(m, x::xr) = if x = item then SOME m else index'(m + 1, xr)
in
index'(0, xs)
end
The individual changes are:
Have index return a value of type int option. NONE means the item is not in the list, SOME i means it is in the list, and the index of its first occurrence is i. This way, no special values (~1) need be used and the function's intended usage can be inferred from its type.
Hide the parameter m by renaming the function to index' and wrapping it into an outer function index that calls it with the appropriate arguments. The prime character (`) often indicates auxiliary values.
Use pattern matching on the list to get to the individual elements, eliminating the need for List.nth.
Also note that most commonly, function and variable names begin with a lowercase letter (index rather than Index), while capital letters are used for constructor constants (SOME) and the like.
I would like to propose a simpler and less efficient version of this index function. I agree that it is not as desirable to use exceptions rather than int option, and that it is not tail-recursive. But it is certainly easier to read and thus may serve as learning material:
fun index (x, []) = raise Subscript
| index (x, y::ys) =
if x = y then 0 else 1 + index (x, ys)
fun index(list,n)=
= if n=0 then hd(list) else index(tl(list),n-1);
val index = fn : 'a list * int -> 'a
index([1,2,3,4,5],2);
val it = 3 : int
index([1,2,3,4,5],0);
val it = 1 : int