Haskel '!!' defined in foldl - haskell

I just started learning Haskell and I'm trying to define the "Get n'th element of list" (with the !! operator) in a function which uses foldl. I now defined it without foldl, just making use of recursion. I wondered if anybody could tell me how to change the code I have to a function with foldl, and could describe what is happening. Thanks in advance!
get 1 (x:_) = x
get i (_:xs) = elementAt'' (i - 1) xs

A couple of notes:
First note that you want get 1 to return the first element in your list, that's not the common choice in many languages including Haskell ([2, 3, 5] !! 1 = 3).
Second, although elementAt is a recursive function over lists, it can be defined more efficiently in the old fashion recursive way. fold functions are not good choices here, because fold goes through every element of the list. But we want elementAt recursion to stop the moment that we find the element.
Given this, here is how you can implement elementAt recursively:
elementAt :: Int -> [a] -> a
elementAt i (x:xs) = if i == 1 then x else elementAt (i-1) xs
And here's the implementation using foldl:
elementAt' :: Int -> [a] -> a
elementAt' i (x:xs) =
snd $
foldl
(\(j, a) b ->
if j < 1 then (j-1, a) else (j-1, b))
(i-1, x)
xs
The seed value of foldl is a tuple: (i-1, x) where x is the head of the list.
Note that the return result of fold functions must be of the same type of their seed. Hence here foldl returns a tuple: (j-1, a) where a is the final result, if the index is found; otherwise (j-1, b) where b is the current element of the list.
You can see how foldl goes through every element of the list even after it found the element at index that we were looking for (it keeps returning the previous result a that will be the final result).
PS. These elementAt functions are not handling the case for empty lists or when i is greater than the length of the list; hence they're not exhaustive.

I can see the following, a bit cryptic way of using foldl for your purpose (it is using zero-based indexing, but can be changed easily to 1-based):
get i lst=
snd $
foldl (\p (j, y) -> if j == i then (j,y) else p ) (0, 0) (zip [0,1..] lst)
The foldl part is working with tuples (index, element), whose list is generated by zipping the given list with indices list. The function passed to foldl as first argument is comparing the index of the desired element with the index with currently passed, and returning the current element if the index is matching, or the previous element otherwise. Then, in the end by using snd only the element part of the tuple is returned.

Related

Partial functions application and folds in haskell

I'm trying to learn Haskell by solving exercises and looking at others solutions when i'm stuck. Been having trouble understanding as functions get more complex.
-- Ex 5: given a list of lists, return the longest list. If there
-- are multiple lists of the same length, return the list that has
-- the smallest _first element_.
--
-- (If multiple lists have the same length and same first element,
-- you can return any one of them.)
--
-- Give the longest function a suitable type.
--
-- Examples:
-- longest [[1,2,3],[4,5],[6]] ==> [1,2,3]
-- longest ["bcd","def","ab"] ==> "bcd"
longest :: (Foldable t, Ord a) => t [a] -> [a]
longest xs = foldl1 comp xs
where
comp acc x | length acc > length x = acc
| length acc == length x = if head acc < head x then acc else x
| otherwise = x
So foldl1 works as follows - input: foldl1 (+) [1,2,3,4] output: 10. As I understand it, it takes a function applies it to a list and "folds" it. The thing I don't understand is that comp acc x compares two lists and outputs the larger length list.
The thing I don't understand is with longest xs = foldl1 comp xs. How are two lists provided to comp to compare and what is foldl1 "folding" and what is the start accumulator?
Here is another shorter example of another fold that I thought I understood.
foldl - input: foldl (\x y -> x + y) 0 [1,2,3] output: 6
It starts at 0 and adds each element from left one by one. How does foldl exactly apply the two variables in the anonymous function. For instance if the anonymous function was (\x y z-> x + y + z) it would fail which I don't yet understand why.
I think your current notion of what foldl1/foldl does is not quite accurate. As others already explained foldl1 f (x:xs) == foldl f x xs so the first value in the list is taken as an accumulator.
You say that foldl1 (+) list takes each value of the list "one by one" and computes the sum. I think this notion is misleaing: Actually you do always take two values, add them and get an intermediate result. And you repeat that over and over again with one of the values being the intermediate result of the last. I really like following illustration:
Source
If you start to think about these intermediate values, it will make more sense that you always get the largets one.
I think it is easiest to understand if you look at a symbolic example:
foldl k z [a, b, c] = k (k (k z a) b) c
foldl1 k [a, b, c] = k (k a b) c
As you can see foldl1 just starts with the first two arguments and then adds on the rest one by one using k to combine it with the accumulator.
And foldl starts by applying k to the initial accumulator z and the first element a and then adds on the rest one by one.
The k function only ever gets two arguments, so you cannot use a function with three arguments for that.

fold function keep switching var locations

I want to write a function which takes a list of integers and returns a list where every element is negative.
negate :: [Int] -> [Int]
negate xs = foldl (\x xs -> (abs x * (-1)) : xs) [] xs
This function negate all the array objects but also reverse the locations of all variables in the array. What make this function reverse the locations?
foldl does! foldl is a left fold, so it works on your list by starting with its initial state (which you provide as []) and the leftmost element of the list, and calls your function which prepends the negation of that element to the state. Then it takes the next leftmost element and does the same thing. But you're prepending each time, which means that the first element of your input ends up corresponding to the last element of the output, because it was the first to get prepended.
You might want foldr for this, which is a fold that starts with the rightmost element. Alternatively, using map would be a simpler approach for this particular problem.
Sample code:
makeAllNegative = map (negate . abs)

Haskell delete largest number from a list

I am trying to figure out how to create a recursive function that will find the largest element in the list and delete it then return the list. This is what i have so far but the problem is that every time i run it it returns the list without any of the values that are assigned to x.
deleteMax :: (Ord a) => [a] -> [a]
deleteMax [] = []
deleteMax [x] = []
deleteMax (x:y:xs)
|x == y = y: deleteMax xs
|x >= y = y: deleteMax xs
|x < y = x: deleteMax xs
This is not your answer
So you are a beginner and as such would like the simple solution of "how do I find the largest element in a list" followed by "how do I remove (one of the) largest element(s) in the list". This isn't that answer but it is me avoiding a long comment while also giving you something to come back to in 3 months.
The Lazy Way
One solution, which #n.m. and I were sparring about in comments, is to tie the knot (Googleable term). In this method you only need one logical pass over the list. In this case it is basically a trick to hide the pass that constructs the result list.
The idea is that during your pass over the list you do both tasks of 1. Compute the maximum element and 2. Compare with the maximum element and construct the list. There is nothing here that requires a monad but it can be easiest to see as part of a state monad:
deleteMaxState :: (Ord a) => [a] -> [a]
deleteMaxState [] = []
First we handle the base cases so we have a candidate 'maximum' (x) for our recursive operation.
deleteMaxState xs#(fstElem:_) =
let (r,(m,_)) = runState (go xs) (fstElem, notMax m)
notMax mx v = if (mx > v) then (v:) else id
go [] = return []
go (x:xs) =
do (curr,f) <- get
when (x > curr) (put (x,f))
f x <$> go xs
in r
In the loopwe track two values the first, curr, is the largest observed value by this point in our traversal of the list. The second value, f, is the trick - it is (a function including) the maximum value provided to the computation after the traversal has completed.
The magic is all here:
(r,(m,_)) = runState (go xs) (fstElem, m)
The left element of the result state (m,_) was our running maximum. Once the traversal ends we use that value - it becomes the right element (fstElem, m) and thus represents the maximum of the whole list.
We can use f to create thunks that populate portions of the list or just in-line construct our list as a bunch of unevaluated cons computations.
Making this one iota simpler, we can remove the higher-order function f and just have a number (untested):
deleteMaxState xs#(fstElem:_) =
let (r,(m,_)) = runState (go xs) (fstElem, m)
go [] = return []
go (x:xs) =
do (curr,theMax) <- get
when (x > curr) (put (x,theMax))
((if x >= theMax then Nothing else Just x) :) <$> go xs
in catMaybes r
Now we can see the second pass pretty explicitly not just as an unevaluated set of "some computation involving max, consed on the result" but as an actual pass via catMaybes.
The tying of the knot allows the programmer to write one logical traversal. This can be nice since it requires only one pattern match and recursive call per constructor of the list elements but at the cost of reasoning about evaluation order.

Haskell: min distance between neighbor numbers on a list

I'm trying to define a functino that finds the minimum distance between to neighbor numbers on a list
something like this:
minNeighborsDistance [2,3,6,2,0,1,9,8] => 1
My code looks like this:
minNeighborsDistance [] = []
minNeighborsDistance (x:xs) = minimum[minNeighborsDistance xs ++ [subtract x (head xs)]]
Although this seems to run, once I enter a list I receive an Exception error.
I'm new to Haskell I would appreciate any help in this matter.
If you pass a singleton list to minNeighborsDistance then
It'll fail to match [] in the first line, then
it'll successfully match (x:xs) assigning the single value to x and the empty like to xs, then
it'll throw an error when you try to access the head of an empty list.
Further, since you call minNeighborsDistance recursively then you'll always eventually call it on a singleton list excepting when you pass it an empty list.
Here's what I came up with:
minDistance l = minimum . map abs . zipWith (-) l $ tail l
Try this:
minDistance list = minimum (distance list)
where
distance list = map abs $ zipWith (-) list (tail list)
distance calculates the absolute value of the list being subtracted with itself shifted by 1 position:
[2,3,6,2,0,1,9,8] -- the 8 is skipped but it does not make a difference
- [3,6,2,0,1,9,8]
= [1,3,4,2,1,8,1]
minDistance now just gets the smallest element of the resulting list.
Your question is a bit unclear (a type signature would really help here), but if you're wanting to calculate the difference between adjacent elements of the list, then find the minimum of those numbers, I would say the most clear way is to use some extra pattern matching:
-- Is this type you want the function to have?
minNeighborsDistance :: [Int] -> Int
minNeighborsDistance list = minimum $ go list
where
go (x:y:rest) = (x - y) : go (y:rest)
go anythingElse = [] -- Or just go _ = []
However, this won't quite give you the answer you want, because the actual minimum for your example list would be -4 when you go from 6 to 2. But this is an easy fix, just apply abs:
minNeighborsDistance :: [Int] -> Int
minNeighborsDistance list = minimum $ go list
where
go (x:y:rest) = abs (x - y) : go (y:rest)
go anythingElse = []
I've used a helper function to calculate the differences from element to element, then the top-level definition calls minimum on that result to get the final answer.
There is an easier way, though, if you exploit a few functions in Prelude, namely zipWith, map, and drop:
minNeighborsDistance :: [Int] -> Int
minNeighborsDistance list
= minimum -- Calculates the minimum of all the distances
$ (maxBound:) -- Ensures we have at least 1 number to pass to
-- minimum by consing the maximum possible Int
$ map abs -- Ensure all differences are non-negative
-- Compute the difference between each element. I use "drop 1"
-- instead of tail because it won't error on an empty list
$ zipWith (-) list (drop 1 list)
So combined into one line without comments:
minNeighborsDistance list = minimum $ (maxBound:) $ map abs $ zipWith (-) list $ drop 1 list

Haskell: Minimum sum of list

So, I'm new here, and I would like to ask 2 questions about some code:
Duplicate each element in list by n times. For example, duplicate [1,2,3] should give [1,2,2,3,3,3]
duplicate1 xs = x*x ++ duplicate1 xs
What is wrong in here?
Take positive numbers from list and find the minimum positive subtraction. For example, [-2,-1,0,1,3] should give 1 because (1-0) is the lowest difference above 0.
For your first part, there are a few issues: you forgot the pattern in the first argument, you are trying to square the first element rather than replicate it, and there is no second case to end your recursion (it will crash). To help, here is a type signature:
replicate :: Int -> a -> [a]
For your second part, if it has been covered in your course, you could try a list comprehension to get all differences of the numbers, and then you can apply the minimum function. If you don't know list comprehensions, you can do something similar with concatMap.
Don't forget that you can check functions on http://www.haskell.org/hoogle/ (Hoogle) or similar search engines.
Tell me if you need a more thorough answer.
To your first question:
Use pattern matching. You can write something like duplicate (x:xs). This will deconstruct the first cell of the parameter list. If the list is empty, the next pattern is tried:
duplicate (x:xs) = ... -- list is not empty
duplicate [] = ... -- list is empty
the function replicate n x creates a list, that contains n items x. For instance replicate 3 'a' yields `['a','a','a'].
Use recursion. To understand, how recursion works, it is important to understand the concept of recursion first ;)
1)
dupe :: [Int] -> [Int]
dupe l = concat [replicate i i | i<-l]
Theres a few problems with yours, one being that you are squaring each term, not creating a new list. In addition, your pattern matching is off and you would create am infinite recursion. Note how you recurse on the exact same list as was input. I think you mean something along the lines of duplicate1 (x:xs) = (replicate x x) ++ duplicate1 xs and that would be fine, so long as you write a proper base case as well.
2)
This is pretty straight forward from your problem description, but probably not too efficient. First filters out negatives, thewn checks out all subtractions with non-negative results. Answer is the minumum of these
p2 l = let l2 = filter (\x -> x >= 0) l
in minimum [i-j | i<-l2, j<-l2, i >= j]
Problem here is that it will allow a number to be checkeed against itself, whichwiull lend to answers of always zero. Any ideas? I'd like to leave it to you, commenter has a point abou t spoon-feeding.
1) You can use the fact that list is a monad:
dup = (=<<) (\x -> replicate x x)
Or in do-notation:
dup xs = do x <- xs; replicate x x; return x
2) For getting only the positive numbers from a list, you can use filter:
filter (>= 0) [1,-1,0,-5,3]
-- [1,0,3]
To get all possible "pairings" you can use either monads or applicative functors:
import Control.Applicative
(,) <$> [1,2,3] <*> [1,2,3]
[(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]
Of course instead of creating pairs you can generate directly differences when replacing (,) by (-). Now you need to filter again, discarding all zero or negative differences. Then you only need to find the minimum of the list, but I think you can guess the name of that function.
Here, this should do the trick:
dup [] = []
dup (x:xs) = (replicate x x) ++ (dup xs)
We define dup recursively: for empty list it is just an empty list, for a non empty list, it is a list in which the first x elements are equal to x (the head of the initial list), and the rest is the list generated by recursively applying the dup function. It is easy to prove the correctness of this solution by induction (do it as an exercise).
Now, lets analyze your initial solution:
duplicate1 xs = x*x ++ duplicate1 xs
The first mistake: you did not define the list pattern properly. According to your definition, the function has just one argument - xs. To achieve the desired effect, you should use the correct pattern for matching the list's head and tail (x:xs, see my previous example). Read up on pattern matching.
But that's not all. Second mistake: x*x is actually x squared, not a list of two values. Which brings us to the third mistake: ++ expects both of its operands to be lists of values of the same type. While in your code, you're trying to apply ++ to two values of types Int and [Int].
As for the second task, the solution has already been given.
HTH

Resources