I'm having a hard time getting Haskell and functional programming together in my head. What I am trying to do is manipulate a string so that I am printing/returning specific characters each time based on a number given. For example:
printing "testing" 2 = "etn"
printing "testing" 3 = "sn"
I've read a lot online, and from what I understand I can achieve this with filtering and cycling, but I cannot get/understand the syntax of this language to get a working program.
I'll try to describe my thought process so you can follow. This function fits the pattern of creating an output list (here a string) from an input seed (here a string) by repeated function application (here dropping some elements). Thus I choose an implementation with Data.List.unfoldr.
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
Okay so, I need to turn the seed b into (Maybe) an output a and the rest of the string. I'll call this subfunction f and pass it into unfoldr.
printing s n = unfoldr f s
where f b = case drop n b of
[] -> Nothing
(x:xs) -> Just (x,xs)
It turns out that attempting to take the head off the front of the list and returning a Maybe is also a common pattern. It's Data.List.uncons, so
printing s n = unfoldr (uncons . drop n) s
Very smooth! So I test it out, and the output is wrong! Your specified output actually eg. for n=2 selects every 2nd character, ie. drops (n-1) characters.
printing s n = unfoldr (uncons . drop (n-1)) s
I test it again and it matches the desired output. Phew!
To demonstrate the Haskell language some alternative solutions to the accepted answer.
Using list comprehension:
printing :: Int -> String -> String
printing j ls = [s | (i, s) <- zip [1 .. ] ls, mod i j == 0]
Using recursion:
printing' :: Int -> String -> String
printing' n ls
| null ls' = []
| otherwise = x : printing' n xs
where
ls' = drop (n - 1) ls
(x : xs) = ls'
In both cases I flipped the arguments so it is easier to do partial application: printing 5 for example is a new function and will give each 5th character when applied to a string.
Note with a minor modification they will work for any list
takeEvery :: Int -> [a] -> [a]
I have a recursive Haskell function that takes a number n and generates a list that is n long of squared numbers from 1 up.
The code works but instead of the list for n=3 being [9,4,1] I want it to be [1,4,9].
sqNList :: Int -> [Int]
sqNList 0 = []
sqNList n = n*n : sqNList (n-1)
I've tried swappig the : for a ++ but then the pattern matching doesn't work. I have only just started Haskell today so may be obvious
The best approach is to implement sqNList in terms of a helper function that counts from 1 up to n. That way you can just generate the list in the correct order in the first place.
sqNList :: Int -> [Int]
sqNList n = sqNListHelper 1 n
sqNListHelper :: Int -> Int -> [Int]
sqNListHelper current end = ...
There are a wide variety of more sophisticated approaches, but this is the easiest approach to debug/test interactively that also has you figuring out how to do everything yourself.
More sophisticated approaches can include list comprehensions or composing functions like map and enumFromTo to build up the logic from simpler pieces.
The easiest approach that consumes probably the least amount of memory is to work with an accumulator: a parameter you pass and update through every recursive call.
Right now you use n as an accumulator, and decrement that, but we can decide to use an accumulator i instead that starts at 1, and keeps incrementing:
helper :: Int -> Int -> [Int]
helper i n | i > n = []
| otherwise = i*i : helper (i+1) n
Now we of course have to call it with i = 1 ourselves, which is not ideal, but we can use a where clause that scopes the helper in the sqNList:
sqNList :: Int -> [Int]
sqNList n = helper 1 n
where helper :: Int -> Int -> [Int]
helper i n | i > n = []
| otherwise = i*i : helper (i+1) n
Now we can improve this a bit. For instanc there is no need to pass n through the helper calls, since it does not change, and is defined at the top level:
sqNList :: Int -> [Int]
sqNList n = helper 1
where helper :: Int -> [Int]
helper i | i > n = []
| otherwise = i*i : helper (i+1)
There is furthermore no need to only work with Ints: we can use any type a for which Num a and Ord a:
sqNList :: (Num a, Ord a) => a -> [a]
sqNList n = helper 1
where helper i | i > n = []
| otherwise = i*i : helper (i+1)
This is a more advanced technique, so you may want to just save this for future study.
Most recursive functions tend to use one of the same general forms of recursion, so knowing which higher-order function to use saves you the effort of reimplementing (possibly incorrectly) the recursion, and lets you focus on the work that is unique to your problem.
This particular type of recursion is captured by the unfoldr function, defined in Data.List, which lets you generate a (possibly infinite) list using a generator function and an initial seed value.
Its definition can be as simple as
unfoldr f x = case f x of
Nothing -> []
Just (new, next) = new : unfoldr f next
although the actual definition is slightly more complicated for efficiency.
Essentially, you just call the generator f on the seed value x. If the result is Nothing, return an empty list. Otherwise, build a list containing a result and the list produced by a recursive call with a new seed value.
Applying this to your problem, we produce a square and the next integer as long as the input is still small enough.
import Data.List (unfoldr)
sqNList n = unfoldr generator 1
where generator x = if x > n then Nothing else Just (x*x, x+1)
So for a simple example like sqNList 3, it proceeds as follows:
Call generator 1 and get back Just (1, 2); the accumulator is now [1].
Call generator 2 and get back Just (4, 3); the accumulator is now
[1,4].
Call generator 3 and get back Just (9, 4); the accumulator is now [1,4,9].
Call generator 4 and get back Nothing. Return the accumulator [1,4,9] as the result.
Note that you generate the infinite list of all squares simply by never returning Nothing:
allSquares = unfoldr (\x -> Just (x*x, x+1)) 1
Haskell, being lazy, only generates elements in the list as you need them, so you could also define sqNList by taking only the first n items of the infinite list.
sqNList n = take n (unfoldr (\x -> Just (x*x, x+1)) 1)
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.
I'm new to Haskell. I need a function to swap two elements in a list when I know only the values.
For example:
swap 5 6 [1,5,7,6,4,3,2] -> [1,6,7,5,4,3,2]
5 and 6 are the values not the index, and the index of the values can be any.
It might help if you think about this task as reconstructing the list with the values swapped. The type signature is going to be like this. You're taking in two numbers to be swapped, and a list.
swap :: Int -> Int -> [Int] -> [Int]
You've got a couple of cases now. If the list is empty, that's easy. This is your base case.
swap _ _ [] = []
If the list isn't empty, then you've got two choices. Either the head of the list is a number you are interested in, or it's not. In the case where it matches, swap the value, otherwise just rebuild the list.
swap n m (x:xs)
| n == x = m : (swap n m xs)
| m == x = n : (swap n m xs)
| otherwise = x : (swap n m xs)
Once you've got this situation, you can see that you're doing an operation on every element. Now you can convert it over to the map solution (which is far more idiomatic!).
swap a b = map (\x -> if x == a then b else if x == b then a else x)
EDIT: Ah, I am afraid I only noticed that this question was answered in a comment above in the exact same way after I posted my answer. Apologies.
The question is to compute the mode (the value that occurs most frequently) of a sorted list of integers.
[1,1,1,1,2,2,3,3] -> 1
[2,2,3,3,3,3,4,4,8,8,8,8] -> 3 or 8
[3,3,3,3,4,4,5,5,6,6] -> 3
Just use the Prelude library.
Are the functions filter, map, foldr in Prelude library?
Starting from the beginning.
You want to make a pass through a sequence and get the maximum frequency of an integer.
This sounds like a job for fold, as fold goes through a sequence aggregating a value along the way before giving you a final result.
foldl :: (a -> b -> a) -> a -> [b] -> a
The type of foldl is shown above. We can fill in some of that already (I find that helps me work out what types I need)
foldl :: (a -> Int -> a) -> a -> [Int] -> a
We need to fold something through that to get the value. We have to keep track of the current run and the current count
data BestRun = BestRun {
currentNum :: Int,
occurrences :: Int,
bestNum :: Int,
bestOccurrences :: Int
}
So now we can fill in a bit more:
foldl :: (BestRun -> Int -> BestRun) -> BestRun -> [Int] -> BestRun
So we want a function that does the aggregation
f :: BestRun -> Int -> BestRun
f (BestRun current occ best bestOcc) x
| x == current = (BestRun current (occ + 1) best bestOcc) -- continuing current sequence
| occ > bestOcc = (BestRun x 1 current occ) -- a new best sequence
| otherwise = (BestRun x 1 best bestOcc) -- new sequence
So now we can write the function using foldl as
bestRun :: [Int] -> Int
bestRun xs = bestNum (foldl f (BestRun 0 0 0 0) xs)
Are the functions filter, map, foldr in Prelude library?
Stop...Hoogle time!
Did you know Hoogle tells you which module a function is from? Hoolging map results in this information on the search page:
map :: (a -> b) -> [a] -> [b]
base Prelude, base Data.List
This means map is defined both in Prelude and in Data.List. You can hoogle the other functions and likewise see that they are indeed in Prelude.
You can also look at Haskell 2010 > Standard Prelude or the Prelude hackage docs.
So we are allowed to map, filter, and foldr, as well as anything else in Prelude. That's good. Let's start with Landei's idea, to turn the list into a list of lists.
groupSorted :: [a] -> [[a]]
groupSorted = undefined
-- groupSorted [1,1,2,2,3,3] ==> [[1,1],[2,2],[3,3]]
How are we supposed to implement groupSorted? Well, I dunno. Let's think about that later. Pretend that we've implemented it. How would we use it to get the correct solution? I'm assuming it is OK to choose just one correct solution, in the event that there is more than one (as in your second example).
mode :: [a] -> a
mode xs = doSomething (groupSorted xs)
where doSomething :: [[a]] -> a
doSomething = undefined
-- doSomething [[1],[2],[3,3]] ==> 3
-- mode [1,2,3,3] ==> 3
We need to do something after we use groupSorted on the list. But what? Well...we should find the longest list in the list of lists. Right? That would tell us which element appears the most in the original list. Then, once we find the longest sublist, we want to return the element inside it.
chooseLongest :: [[a]] -> a
chooseLongest xs = head $ chooseBy (\ys -> length ys) xs
where chooseBy :: ([a] -> b) -> [[a]] -> a
chooseBy f zs = undefined
-- chooseBy length [[1],[2],[3,3]] ==> [3,3]
-- chooseLongest [[1],[2],[3,3]] ==> 3
chooseLongest is the doSomething from before. The idea is that we want to choose the best list in the list of lists xs, and then take one of its elements (its head does just fine). I defined this by creating a more general function, chooseBy, which uses a function (in this case, we use the length function) to determine which choice is best.
Now we're at the "hard" part. Folds. chooseBy and groupSorted are both folds. I'll step you through groupSorted, and leave chooseBy up to you.
How to write your own folds
We know groupSorted is a fold, because it consumes the entire list, and produces something entirely new.
groupSorted :: [Int] -> [[Int]]
groupSorted xs = foldr step start xs
where step :: Int -> [[Int]] -> [[Int]]
step = undefined
start :: [[Int]]
start = undefined
We need to choose an initial value, start, and a stepping function step. We know their types because the type of foldr is (a -> b -> b) -> b -> [a] -> b, and in this case, a is Int (because xs is [Int], which lines up with [a]), and the b we want to end up with is [[Int]].
Now remember, the stepping function will inspect the elements of the list, one by one, and use step to fuse them into an accumulator. I will call the currently inspected element v, and the accumulator acc.
step v acc = undefined
Remember, in theory, foldr works its way from right to left. So suppose we have the list [1,2,3,3]. Let's step through the algorithm, starting with the rightmost 3 and working our way left.
step 3 start = [[3]]
Whatever start is, when we combine it with 3 it should end up as [[3]]. We know this because if the original input list to groupSorted were simply [3], then we would want [[3]] as a result. However, it isn't just [3]. Let's pretend now that it's just [3,3]. [[3]] is the new accumulator, and the result we would want is [[3,3]].
step 3 [[3]] = [[3,3]]
What should we do with these inputs? Well, we should tack the 3 onto that inner list. But what about the next step?
step 2 [[3,3]] = [[2],[3,3]]
In this case, we should create a new list with 2 in it.
step 1 [[2],[3,3]] = [[1],[2],[3,3]]
Just like last time, in this case we should create a new list with 1 inside of it.
At this point we have traversed the entire input list, and have our final result. So how do we define step? There appear to be two cases, depending on a comparison between v and acc.
step v acc#((x:xs):xss) | v == x = (v:x:xs) : xss
| otherwise = [v] : acc
In one case, v is the same as the head of the first sublist in acc. In that case we prepend v to that same sublist. But if such is not the case, then we put v in its own list and prepend that to acc. So what should start be? Well, it needs special treatment; let's just use [] and add a special pattern match for it.
step elem [] = [[elem]]
start = []
And there you have it. All you have to do to write your on fold is determine what start and step are, and you're done. With some cleanup and eta reduction:
groupSorted = foldr step []
where step v [] = [[v]]
step v acc#((x:xs):xss)
| v == x = (v:x:xs) : xss
| otherwise = [v] : acc
This may not be the most efficient solution, but it works, and if you later need to optimize, you at least have an idea of how this function works.
I don't want to spoil all the fun, but a group function would be helpful. Unfortunately it is defined in Data.List, so you need to write your own. One possible way would be:
-- corrected version, see comments
grp [] = []
grp (x:xs) = let a = takeWhile (==x) xs
b = dropWhile (==x) xs
in (x : a) : grp b
E.g. grp [1,1,2,2,3,3,3] gives [[1,1],[2,2],[3,3,3]]. I think from there you can find the solution yourself.
I'd try the following:
mostFrequent = snd . foldl1 max . map mark . group
where
mark (a:as) = (1 + length as, a)
mark [] = error "cannot happen" -- because made by group
Note that it works for any finite list that contains orderable elements, not just integers.