Some sml codes but i don't know how that work - sml

fun map f nil = nil
| map f (hd::tl) = f(hd) :: map f tl;
fun everywhere e nil = [[e]]
| everywhere e (y::ys) =
(e::y::ys) :: (map (fn u => y::ys) (everywhere e ys));
I don't know how those sml codes work.
I know map function.
But about everywhere code, I don't know how much I think about that.
Please let me know
Thank you

First, I guess "everywhere" should be fixed to get the behavior expected from its name:
fun everywhere e nil = [[e]]
| everywhere e (y::ys) =
(e::y::ys) :: (map (fn u => y::u) (everywhere e ys));
This modified version provides a list of list. For example,
- everywhere 4 [1,2,3] ;
val it = [[4,1,2,3],[1,4,2,3],[1,2,4,3],[1,2,3,4]] : int list list
So, You may know that "everywhere e xs" enumerates all possible lists which are made by inserting item "e" into somewhere of the original list xs.
Then, how can you enumerate the insertion? It is divided into two cases:
insert at the top: [1,2,3] -> [4, 1,2,3]
insert between the first and the second or later: [1, 4 ,2,3], [1,2, 4 ,3],...
Case 1 is realized by just (e::y::ys).
Case 2 is further split into two steps:
A) get all possibilities of insertion of "e" to the sub list "ys" of the second and the following items: [4, 2, 3], [2, 4, 3], ...
B) add the first item "y" of the original list into EACH of the outcome of step A:
1 :: [4,2,3], 1::[2,4,3], ...
Step 2A can be done by calling "everywhere" itself with the sub list as an argument. Then, appending item "y" into each of (everywhere e ys), you have done Step 2B.
For this (doing the same thing for items), you can use "map".

Related

Haskell recurse and add to a list

I'm a Haskell beginner,
I have a function
func :: Num a => [a] -> [a]
func [] = []
func (x:xs) = x + func xs
Each recursion I want to append the value to a list for my output. This function will sum consecutive indexes in a list so that the input [1, 2, 3, 4] produces [1, 3, 6, 10].
How do I append the value generated each time to my list?
Your problem here isn't how to append, but rather how to calculate the value in the first place. Each item needs to be substituted with a sum of itself with all the items preceding it.
Here is one way to do it:
Prelude> func (x:xs) = x:map (+ x) (func xs); func [] = []
Prelude> func [1, 2, 3, 4]
[1,3,6,10]
How does this work? We're given a list that starts with the element x and has the remaining elements xs. We want to increment every item in xs by x, after recursively applying the algorithm to xs.
This is what x:map (+ x) (func xs) does. It reads as "prepend x to the result of mapping every element in func xs through an increment by x".
E.g. for [1, 2, 3, 4], we want 1 to be added to every member of the result of recursively applying the algorithm to [2, 3, 4], then prepended. For [2, 3, 4] we want 2 to be ... to [3, 4]. And so on, until eventually for [4] we want 4 to be added and prepended to the result of applying the algorithm to [].
This is where our base case (func [] = []) kicks in: the algorithm is defined so that it returns an empty list unchanged. Hence func [4] is [4], func [3, 4] is [3, 7], and you keep incrementing and prepending until you get [1,3,6,10].
I think in this particular case, you could use scanl1 like:
scanl1 (+) [1,2,3,4] -- [1,3,6,10]
When iterating over lists, we often use folds, which is a way of reducing the list to a particular value.
There's also another type of operation, which is a fold that collects all results along the way, and that's called a scan (from the docs):
scanl = scanlGo
where
scanlGo :: (b -> a -> b) -> b -> [a] -> [b]
scanlGo f q ls = q : (case ls of
[] -> []
x:xs -> scanlGo f (f q x) xs)
So the scan takes three arguments: a function that takes two values and returns a value, a starter value, and a list of values.
The scan will then return a list.
Thus, what you need is a function that takes two values and returns something of the same type as the first (it's okay if both are the same). Binary addition would work here: +.
You also need a value to start off with (the b, which is the second argument to our function), and 0 is the identity for integer addition, so we should use that.
Finally, we pass your list to get the result.
Try to figure out how to write you function as a fold and then as a scan and you will discover the answer.

SML: how to listify list to sublist

I found this question from CS 217.
Divide a list into one or more sublists so that each sublist contains integers in nondecreasing (sorted) order.
[3,5,1,8,9,2,1,0] returns [[3,5],[1,8,9],[2],[1],[0]]
[1,2,3,4,5,6] returns [[1,2,3,4,5,6]]
[5,4,3,2,1] returns [[5],[4],[3],[2],[1]]
below code works:
val Q1 = [ 3, 5, 1, 8, 9, 2, 1, 0 ]
val A1 = foldl (
fn (x, a) =>
if x > hd (hd a) then (x::hd a)::tl a
else [x]::a
) [ [ hd Q1 ] ] (tl Q1)
val A1 = map rev (rev A1)
or like this: use 2 temporary list to collect.
fun split l = let
fun split' tmp subset =
fn [] => []
| [x] => (x::tmp)::subset
| (a::(c as b::_)) =>
if a < b then split' (a::tmp) subset c
else split' [] ((a::tmp)::subset) c
in (rev o map rev) (split' [] [] l) end
So many solutions for this question,
But I still want to know how to code it as a pattern match function?
maybe something like below:
(Not sure if it is possible?)
fun split [] = [[]]
| split [x] = [[x]]
| split [a, b] = if a < b then (* here *) else (* here *)
| split (a::b) = if a < hd b then (* here *) else (* here *)
This question really stuck me.
Under the assumption that this is homework, I hesitate to give a complete answer, but here are a few hints:
1) In the empty basis case I think that you want to return [[]] rather than []. Your specification doesn't address this, but since the empty list is the longest list of nondecreasing integers which can be pulled from the front of the empty list, the return value should be the list consisting of the empty list. This is somewhat similar to the fact that the powerset (set of all subsets) of the empty set is the set containing the empty set rather than the empty set itself. It shouldn't really matter how you define this particular case, since the real basis case is ...
2) In the [x] case you really need to return [[x]] rather than [x] since the type of the function that you are trying to write is int list -> int list list
3) In the remaining case you can write the pattern like
| split (x::y::zs) = (* fill this in *)
then test if x <= y to decide what to do. Since both x <= y and x > y will involve split (y::zs) you could compute this once, giving this a name in a let binding and have the if in the scope of that binding, though that is mostly a matter of taste.
Note how the pattern works in this last case. Explicit use of hd should be fairly rare in function definitions which use pattern-matching (though if you flesh out the last case without using a pattern-matching let binding you will be forced to use it in at least one of the branches of the if).
On Edit: Since this isn't homework, here is a complete implementation:
fun split [] = [[]]
| split [x] = [[x]]
| split (x::y::zs) =
let val first::rest = split (y::zs) in
if x <= y then
(x::first) :: rest
else
[x]::first::rest
end;

Process Haskell list from right to left keeping origin order

Need increment every second item starting from the right in Haskell list but keeping origin order (e.g. reverse is not a case). For example:
f [1, 2, 3] -- [1, 3, 3]
f [1, 2, 3, 4] -- [2, 2, 4, 4]
I've tried something like a following:
fc ([]) = []
fc (x:[]) = [x]
fc (x:[y]) = [x+1,y]
fc( x:xs ) = fc [x] : ( fc xs ) -- this line is wrong
p.s. Obviously I could reverse (but prefer to understand original task) the list twice and apply something like:
helper (x:y:tail) = [x, y+1] ++ tail
fc x = reverse (helper (reverse x) )
The typical way to process a Haskell list from right to left would be to reverse it. Since you want to have the original order for the result, you would simply reverse again:
f1 = reverse . zipWith (+) (cycle [0,1]) . reverse
But if you really want to, you can have each recursive call return both the updated tail and a flag that indicates whether that position is even when counted from the end so you know whether to increase the element at that position or not:
f2 = snd . g
where
g [] = (False, [])
g (x:xs) = let (addOne, xs') = g xs
x' = if addOne then x + 1 else x
in (not addOne, x':xs')
We're basically mapping a function over the list, but this function requires an extra parameter that gets computed starting from the right end of the list. There's a standard function we can use:
import Data.List (mapAccumR)
f2' = snd . mapAccumR g False
where
g addOne x = (not addOne, if addOne then x + 1 else x)
I think a cleaner specification for what you want is that you increment even indicies if the length is even and odd indicies if the length is odd. For example, when indexing from zero, the list of length 3 resulted in index 1 being incremented. One way to do this is with the obvious two pass solution:
f xs = zipWith (+) (cycle sol) xs
where sol = map fromEnum [even len, odd len]
len = length xs
This can be done in one pass (without relying on the compiler fusion rules) by "tying the knot". For example (using manual recursive style as means of communication).
f2 xs = let (isEven, result) = go isEven xs in result
where
go _ [] = (True, [])
go e (x:xs) = let (ne,rest) = go (not e) xs
in (not ne, x+fromEnum e : rest)
This can be done efficiently using a left fold:
inc :: Num a => [a] -> [a]
inc xs = foldl go (\_ _ acc -> acc) xs id (+ 1) []
where go run x f g acc = run g f (f x: acc)
Note that even thought this is a left fold, the list is built using cons (:) operator; and it will perform linearly and not quadratic (similar construct as in difference lists).
\> inc [1, 2, 3]
[1,3,3]
\> inc [1, 2, 3, 4]
[2,2,4,4]
It can also be generalized to alternating functions other than id and (+ 1).
I like Thomas's solution. However, I think a simple foldr is enough here.
process = snd . foldr (\x (b,xs) -> (not b, x + fromEnum b:xs)) (False,[])

List of lists, take next element

I have [[Integer]] -> [Integer] and want to take the first element of the first sub-list, the second element of the second sub-list and .. the n-th element of the n-th sub-list and so on.
I am trying to achieve this using list comprehensions. However, I first drop an incrementing number of elements and the take the head of the remaining. But there again I don't know how to use drop (inc z) where z = 0 with inc c = c + 1 as an already defined function, in presumably this:
getNext :: [[Integer]] -> [Integer]
getNext xs = [y | drop (inc z) (y:ys) <- xs, (y:_) <- xs]
where z = 0
I know that the code above is not working, but again I had only so far come up to this and hit a wall.
You can do it like this:
getNext :: [[a]] -> [a]
getNext xs = [ head $ drop y x | (x,y) <- zip xs [0..]]
Although note that this function is partial because of head.
As the other answers suggest, you can use a zip function and zip with the list of indices.
The Glasgow Haskell Compiler (GHC) however offers the Parallel List Comp extension:
{-# LANGUAGE ParallelListComp #-}
diagonal :: [[a]] -> [a]
diagonal ls = [l !! i | l <- ls | i <- [0..]]
The (!!) operator gets the i-th element from a list.
Furthermore it is always advisable to use the most generic function signature; so [[a]] -> [a] instead of [[Integer]] -> [Integer]. This can be useful if you later decide to take the diagonal of a matrix of Double's, String, lists, custom types,...
You can zip the actual list of list of integers and another list which runs from 0 to infinity and get the corresponding elements, like this
picker :: [[Integer]] -> [Integer]
picker xs = [(x !! y) | (x, y) <- (zip xs [0..])]
main = print $ picker [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
-- [1,5,9]
The expression [0..] will create an infinite list, lazily, starting from 0 and we zip it with xs. So, on every iteration, the result of zip would be used like this
[1, 2, 3] !! 0
[4, 5, 6] !! 1
[7, 8, 9] !! 2
We get element at index 0, which is 1, on the first iteration and 5 and 9 on the following iterations.

Update a list of a list of elements in a single list?

I have some code which is designed to replace a value in a list
replaceNth n newVal (x:xs)
| n == 0 = newVal:xs
| otherwise = x:replaceNth (n-1) newVal xs
For example, when I load the function into GHCI, I enter and get the following:
*Main> replaceNth 3 4 [3,3,3,3,3]
[3,3,3,4,3]
However I am trying to use this function for a multiple lists within a list and can't seem to do so (e.g.).
What I want is to get a result like this:
[[3,3,3,3,3],[3,3,3,**2**,3],[3,3,3,3,3]]
From this [[3,3,3,3,3],[3,3,3,3,3],[3,3,3,3,3]]
using something like the function above.
Your function is not general enough to handle the task you wish it to preform. In particular, you need to know what the replacement value will be before you call the function. To get this working you might either:
Select the nth list, compute the new list then use your function to put that replacement in the list of lists. OR (and better)
Make a more general function that instead of taking a new value takes a function from the old value to the new:
Example
replaceNth' :: Int -> (a -> a) -> [a] -> [a]
replaceNth' n f (x:xs)
| n == 0 = (f x):xs
| otherwise = x:replace (n-1) f xs
Now to solve you second problem:
let ls = [[3,3,3,3,3],[3,3,3,3,3],[3,3,3,3,3]]
in replaceNth' 1 (replaceNth' 3 (const 2)) ls
That is replace the second list with a list made by taking the fourth element of that list and replacing what ever it is with 2.
Make a function that applies a function to the nth element of a list instead. Then you can easily get what you want by composing that with itself and using const for the inner replacement.
perhaps this does what you want (applied to the list of lists):
replaceNth 1 (replaceNth 3 4 [3,3,3,3,3])
Using your existing definition:
ghci> let arg = [[3,3,3,3,3],[3,3,3,3,3],[3,3,3,3,3]]
ghci> replaceNth 1 (replaceNth 3 2 (arg !! 1)) arg
[[3,3,3,3,3],[3,3,3,2,3],[3,3,3,3,3]]
ghci>
To refactor it into a function:
replaceMthNth m n v arg = replaceNth m (replaceNth n v (arg !! m)) arg