I am new in Haskell programming.
While practicing I was asked to make a recursive function that looks like this:
repeat1 5 [1,2,3] = [[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3]]
which is
repeat1 :: Int -> a -> [a]
repeat1 0 x = []
repeat1 num x = x : repeat1 (num-1) x
I want to convert it into a foldr function but I can't :(
I have read about the lambda functions and the folding(foldr and foldl) functions from http://en.wikibooks.org/wiki/Haskell/List_processing
Can anybody help please?
Thanks in advance
foldr is for functions that consume lists. For producing lists, unfoldr is a more natural choice:
repeat1 :: Int -> a -> [a]
repeat1 n x = unfoldr f n
where f 0 = Nothing
f n = Just (x, n-1)
That said, I think writing it as a plain recursion is more clear in this case.
As hammar pointed out, foldr isn't the right tool here, as you first need a list to work on. Why not simply...
repeat1 n = take n . repeat
If you really want to use foldr, you could do something like that:
repeat' n x = foldr (\_ acc -> x:acc) [] [1..n]
You basically create a list of size n with [1..n] and for each element of that list, you append x to your accumulator (base value []). In the end you have a n-elements list of x.
Related
I am a newbie to Haskell and I wrote the following code
module RememberMap (rememberMap) where
rememberMap :: (a -> b -> (a, c)) -> a -> [b] -> [c]
rememberMap f acc xs = go acc xs []
where
go acc [x] carry = carry <> [step]
where
(_, step) = f acc x
go acc (x:xs) carry = go accStep xs (carry <> [step])
where
(accStep, step) = f acc x
I wrote this contaminator with the Intent to help me with the most Common difficulty that i have when writing my Haskell code, That is that I recurrently find myself willing to map something (specially in CodeWarrior's Katas) like to map something, but that something required knowledge of the elements before it. But it had the problem of being non-streaming, ergo, it does no allow me to use lazy proprieties of Haskell with it, thus I would like to know if (a) there is already a solution to this problem (preferably Arrows) or (b) how to make it lazy.
To make the function stream you need to have the cons operator outside the recursive call, so a caller can see the first element without the whole recursion needing to happen. So you expect it to look something like:
rememberMap f acc (x:xs) = element : ... recursion ...
Once you understand this there is not much more to do:
rememberMap _ _ [] = []
rememberMap f acc (x:xs) = y : rememberMap f acc' xs
where
(acc', y) = f acc x
You can make an auxiliary function to avoid passing f around if you want, but there's no reason for it to have the extra list that you called carry.
There are mapAccumL and traverse with the lazy State monad.
I'm having difficulty try to write a function to find the sum of two lists using recursion, that possibly could be Nothing if any list is empty.
The math of the following functions are:
Σw[i]x[i]
where w and x are equal length int arrays
Here is my working code:
example :: [Int] -> [Int] -> Int
example [] [] = 0
example (x:xs) (l:ls) = ((x*l) + (example xs ls))
Here is the idea of what I want to work:
example :: [Int] -> [Int] -> Maybe Int
example [] [] = Nothing
example (x:xs) (l:ls) = Just((x*l) + (example xs ls))
Thanks
I'm guessing at what your intent is here, not sure whether I read it correctly: You want the function to produce Nothing when the two input lists have difference lengths?
The "happy" base case is 0 just like in the first attempt, but lifted into Maybe.
example [] [] = Just 0
To handle situations where the lists have different lengths, include the cases where only one of the lists is empty. You should have gotten a compiler warning about a non-exhaustive pattern match for not including these cases.
example [] _ = Nothing
example _ [] = Nothing
The final case, then, is where you have two nonempty lists. It looks a lot like that line from your first attempt, except rather than applying the addition directly to example xs ys, we fmap the addition over example xs ys, taking advantage of the fact that Maybe is a Functor.
example (x : xs) (y : ys) = fmap (x * y +) (example xs ys)
Example usage:
λ> example [1,2] [3,4]
Just 11
λ> example [1,2] [3,4,5]
Nothing
By the way, if you wanted to use a library this, safe would be a nice choice to turn this into a one-liner.
import Safe.Exact
example xs ys = fmap sum (zipWithExactMay (*) xs ys)
You're close, but your recursive call to example xs ls returns a Maybe Int, and you can't add an Int and a Maybe Int (in x*l + example xs ls), hence your error on the last line.
You can use fromMaybe to deal with this case, using 0 as the default sum:
example :: [Int] -> [Int] -> Maybe Int
example [] [] = Nothing
example (x:xs) (l:ls) = Just $ x * l + fromMaybe 0 (example xs ls)
Alternatively (and more neatly), you can avoid the explicit recursion using something like this:
example [] [] = Nothing
example xl yl = Just $ sum $ zipWith (*) xl yl
Note that you have non-exhaustive patterns in your pattern match. Two lists of different lengths will cause a pattern-match exception.
I'm totally new to Haskell so apologies if the question is silly.
What I want to do is recursively build a list while at the same time building up an accumulated value based on the recursive calls. This is for a problem I'm doing for a Coursera course, so I won't post the exact problem but something analogous.
Say for example I wanted to take a list of ints and double each one (ignoring for the purpose of the example that I could just use map), but I also wanted to count up how many times the number '5' appears in the list.
So to do the doubling I could do this:
foo [] = []
foo (x:xs) = x * 2 : foo xs
So far so easy. But how can I also maintain a count of how many times x is a five? The best solution I've got is to use an explicit accumulator like this, which I don't like as it reverses the list, so you need to do a reverse at the end:
foo total acc [] = (total, reverse acc)
foo total acc (x:xs) = foo (if x == 5 then total + 1 else total) (x*2 : acc) xs
But I feel like this should be able to be handled nicer by the State monad, which I haven't used before, but when I try to construct a function that will fit the pattern I've seen I get stuck because of the recursive call to foo. Is there a nicer way to do this?
EDIT: I need this to work for very long lists, so any recursive calls need to be tail-recursive too. (The example I have here manages to be tail-recursive thanks to Haskell's 'tail recursion modulo cons').
Using State monad it can be something like:
foo :: [Int] -> State Int [Int]
foo [] = return []
foo (x:xs) = do
i <- get
put $ if x==5 then (i+1) else i
r <- foo xs
return $ (x*2):r
main = do
let (lst,count) = runState (foo [1,2,5,6,5,5]) 0 in
putStr $ show count
This is a simple fold
foo :: [Integer] -> ([Integer], Int)
foo [] = ([], 0)
foo (x : xs) = let (rs, n) = foo xs
in (2 * x : rs, if x == 5 then n + 1 else n)
or expressed using foldr
foo' :: [Integer] -> ([Integer], Int)
foo' = foldr f ([], 0)
where
f x (rs, n) = (2 * x : rs, if x == 5 then n + 1 else n)
The accumulated value is a pair of both the operations.
Notes:
Have a look at Beautiful folding. It shows a nice way how to make such computations composable.
You can use State for the same thing as well, by viewing each element as a stateful computation. This is a bit overkill, but certainly possible. In fact, any fold can be expressed as a sequence of State computations:
import Control.Monad
import Control.Monad.State
-- I used a slightly non-standard signature for a left fold
-- for simplicity.
foldl' :: (b -> a -> a) -> a -> [b] -> a
foldl' f z xs = execState (mapM_ (modify . f) xs) z
Function mapM_ first maps each element of xs to a stateful computation by modify . f :: b -> State a (). Then it combines a list of such computations into one of type State a () (it discards the results of the monadic computations, just keeps the effects). Finally we run this stateful computation on z.
I have this simple function which returns a list of pairs with the adjacents elements of a list.
adjacents :: [a] -> [(a,a)]
adjacents (x:y:xs) = [(x,y)] ++ adjacents (y:xs)
adjacents (x:xs) = []
I'm having problems trying to write adjacents using foldr. I've done some research but nothing seems to give me a hint. How can it be done?
Tricky folds like this one can often be solved by having the fold build up a function rather than try to build the result directly.
adjacents :: [a] -> [(a, a)]
adjacents xs = foldr f (const []) xs Nothing
where f curr g (Just prev) = (prev, curr) : g (Just curr)
f curr g Nothing = g (Just curr)
Here, the idea is to let the result be a function of type Maybe a -> [(a, a)] where the Maybe contains the previous element, or Nothing if we're at the beginning of the list.
Let's take a closer look at what's going on here:
If we have both a previous and a current element, we make a pair and pass the current element to the result of the recursion, which is the function which will generate the tail of the list.
f curr g (Just prev) = (prev, curr) : g (Just curr)
If there is no previous element, we just pass the current one to the next step.
f curr g Nothing = g (Just curr)
The base case const [] at the end of the list just ignores the previous element.
By doing it this way, the result is as lazy as your original definition:
> adjacents (1 : 2 : 3 : 4 : undefined)
[(1,2),(2,3),(3,4)*** Exception: Prelude.undefined
I don't think your function is a good fit for a fold, because it looks at two elements rather than one.
I think the best solution to the problem is
adjacents [] = []
adjacents xs = zip xs (tail xs)
But we can shoehorn it into a travesty of a fold if you like. First an auxilliary function.
prependPair :: a -> [(a,a)] -> [(a,a)]
prependPair x [] = [(x,b)] where b = error "I don't need this value."
prependPair x ((y,z):ys) = ((x,y):(y,z):ys)
adjacents' xs = init $ foldr prependPair [] xs
I feel like I've cheated slightly by making and throwing
away the last element with the error value, but hey ho, I already said I don't think
foldr is a good way of doing this, so I guess this hack is an example of it not being a fold.
You can also try unfoldr instead of foldr.
import Data.List
adjacents xs = unfoldr f xs where
f (x:rest#(y:_)) = Just ((x,y), rest)
f _ = Nothing
im searching for a solution for my Haskell class.
I have a list of numbers and i need to return SUM for every part of list. Parts are divided by 0. I need to use FOLDL function.
Example:
initial list: [1,2,3,0,3,4,0,5,2,1]
sublist [[1,2,3],[3,4],[5,2,1]]
result [6,7,7]
I have a function for finding 0 in initial list:
findPos list = [index+1 | (index, e) <- zip [0..] list, e == 0]
(returns [4,6] for initial list from example)
and function for making SUM with FOLDL:
sumList list = foldl (+) 0 list
But I completely failed to put it together :/
---- MY SOLUTION
In the end I found something completely different that you guys suggested.
Took me whole day to make it :/
groups :: [Int] -> [Int]
groups list = [sum x | x <- makelist list]
makelist :: [Int] -> [[Int]]
makelist xs = reverse (foldl (\acc x -> zero x acc) [[]] xs)
zero :: Int -> [[Int]] -> [[Int]]
zero x acc | x == 0 = addnewtolist acc
| otherwise = addtolist x acc
addtolist :: Int -> [[Int]] -> [[Int]]
addtolist i listlist = (i : (head listlist)) : (drop 1 listlist)
addnewtolist :: [[Int]] -> [[Int]]
addnewtolist listlist = [] : listlist
I'm going to give you some hints, rather than a complete solution, since this sounds like it may be a homework assignment.
I like the breakdown of steps you've suggested. For the first step (going from a list of numbers with zero markers to a list of lists), I suggest doing an explicit recursion; try this for a template:
splits [] = {- ... -}
splits (0:xs) = {- ... -}
splits (x:xs) = {- ... -}
You can also abuse groupBy if you're careful.
For the second step, it looks like you're almost there; the last step you need is to take a look at the map :: (a -> b) -> ([a] -> [b]) function, which takes a normal function and runs it on each element of a list.
As a bonus exercise, you might want to think about how you might do the whole thing in one shot as a single fold. It's possible -- and even not too difficult, if you track through what the types of the various arguments to foldr/foldl would have to be!
Additions since the question changed:
Since it looks like you've worked out a solution, I now feel comfortable giving some spoilers. =)
I suggested two possible implementations; one that goes step-by-step, as you suggested, and another that goes all at once. The step-by-step one could look like this:
splits [] = []
splits (0:xs) = [] : splits xs
splits (x:xs) = case splits xs of
[] -> [[x]]
(ys:yss) -> ((x:ys):yss)
groups' = map sum . splits
Or like this:
splits' = groupBy (\x y -> y /= 0)
groups'' = map sum . splits'
The all-at-once version might look like this:
accumulate 0 xs = 0:xs
accumulate n (x:xs) = (n+x):xs
groups''' = foldr accumulate [0]
To check that you understand these, here are a few exercises you might like to try:
What do splits and splits' do with [1,2,3,0,4,5]? [1,2,0,3,4,0]? [0]? []? Check your predictions in ghci.
Predict what each of the four versions of groups (including yours) output for inputs like [] or [1,2,0,3,4,0], and then test your prediction in ghci.
Modify groups''' to exhibit the behavior of one of the other implementations.
Modify groups''' to use foldl instead of foldr.
Now that you've completed the problem on your own, I am showing you a slightly less verbose version. Foldr seems better in my opinion to this problem*, but because you asked for foldl I will show you my solution using both functions.
Also, your example appears to be incorrect, the sum of [5,2,1] is 8, not 7.
The foldr version.
makelist' l = foldr (\x (n:ns) -> if x == 0 then 0:(n:ns) else (x + n):ns) [0] l
In this version, we traverse the list, if the current element (x) is a 0, we add a new element to the accumulator list (n:ns). Otherwise, we add the value of the current element to the value of the front element of the accumulator, and replace the front value of the accumulator with this value.
Step by step:
acc = [0], x = 1. Result is [0+1]
acc = [1], x = 2. Result is [1+2]
acc = [3], x = 5. Result is [3+5]
acc = [8], x = 0. Result is 0:[8]
acc = [0,8], x = 4. Result is [0+4,8]
acc = [4,8], x = 3. Result is [4+3,8]
acc = [7,8], x = 0. Result is 0:[7,8]
acc = [0,7,8], x = 3. Result is [0+3,7,8]
acc = [3,7,8], x = 2. Result is [3+2,7,8]
acc = [5,7,8], x = 1. Result is [5+1,7,8] = [6,7,8]
There you have it!
And the foldl version. Works similarly as above, but produces a reversed list, hence the use of reverse at the beginning of this function to unreverse the list.
makelist l = reverse $ foldl (\(n:ns) x -> if x == 0 then 0:(n:ns) else (x + n):ns) [0] l
*Folding the list from the right allows the cons (:) function to be used naturally, using my method with a left fold produces a reversed list. (There is likely a simpler way to do the left fold version that I did not think of that eliminates this triviality.)
As you already solved it, another version:
subListSums list = reverse $ foldl subSum [0] list where
subSum xs 0 = 0 : xs
subSum (x:xs) n = (x+n) : xs
(Assuming that you have only non-negative numbers in the list)