I have the following function:
blockToPicture :: Int -> [Picture] -> Picture
blockToPicture n [pic1,pic2,pic3] | n==0 = ...
| n==1 = ...
| otherwise = ...
If n==0 I want to select pic1, if n==1 I want to select pic2. Otherwise I want to select pic3. The problem is when one of the pictures doesn't load, so it doesn't appear on the list.
Instead of [pic1,pic2,pic3] I have something like [Pic1,Pic3].
When the function is supposed to select a picture that isn't on the list I want it to write "X" instead. For that I'll use the function
text "X" instead. The problem is that I don't know how to make it write the "X" instead of selecting the wrong picture.
Edit:
I've created the following function but for some reason I'm getting the error "Variable not in scope" to the pictures.
blocoParaPicture :: Int -> [Picture] -> Picture
blocoParaPicture b l | b==0 = if elem pic1 l then pic1 else text "X"
| b==1 = if elem pic2 l then pic2 else text "X"
| otherwise = if elem pic3 l then pic3 else text "X"
You can't just discard a picture that doesn't load; if you tried to load 3 pictures and end up with [some_pic, some_other_pic], how do you know which one didn't load? You need a list of type [Maybe Picture], with Just pic representing a successfully loaded picture and Nothing a failure. Then your function would look like
blockToPicture :: Int -> [Maybe Picture] -> Maybe Picture
blockToPicture _ [] = Nothing -- No pictures to choose from
blockToPicture 0 (Nothing:_) = Nothing -- Desired picture failed to load
blockToPicutre 0 (x:_) = x -- Found desired picture!
blockToPicture n (_:xs) = blockToPicture (n-1) xs -- This isn't it; try the next one
Adapting Jorge Adriano's suggestion to use lookup (which is a good one)
import Control.Monad
blockToPicture :: Int -> [Maybe Picture] -> Maybe Picture
blockToPicture n pics = join (lookup n (zip [0..] pics))
Since lookup :: a -> [(a,b)] -> Maybe b and b here is Maybe Picture, we have
a scenario where lookup returns Nothing if n is too big; Just Nothing if the desired picture fails to load, and Just (Just pic) if the desired picture is found. The join function from Control.Monad reduces the Maybe (Maybe Picture) value that lookup returns to the "regular" Maybe Picture that we want.
blocoParaPicture :: Int -> [Picture] -> Picture
blocoParaPicture b l | b==0 = if elem pic1 l then pic1 else text "X"
| b==1 = if elem pic2 l then pic2 else text "X"
| otherwise = if elem pic3 l then pic3 else text "X"
I'm getting the error "Variable not in scope" to the pictures.
The expression elem x xs checks if a given x is in a list xs. In your code when you write pic1, there's no such variable in scope, it isn't defined anywhere. In any case you don't want to search for a specific value in the list, rather you want to know if a given position "exists", that is if the list is long enough.
Also you can't just "write" inside a function with this type. In Haskell input and output is reflected on the types. This is a pure function, that takes some arguments and calculates a result, no side effects.
So what you can do here is return a Maybe Picture, which has values Nothing or Just pic depending whether you can return a picture or not. Or you can use Either String Picture, where values are of the form Left string or Right pic. Lets go for this latter option.
blocoParaPicture :: Int -> [Picture] -> Either String Picture
In terms of implementation we could diverge from the subject to get into a discussion of error management (since the problem is that access to a position may fail). But at this point I think it's best to avoid that detour so lets keep it (relatively) simple.
direct recursion (simplest)
The simplest most direct method would be direct recursion (as suggested by #chepner in the comments below).
blocoParaPicture :: Int -> [Picture] -> Either String Picture
blocoParaPicture _ [] = Left "X"
blocoParaPicture 0 (x:_) = Right x
blocoParaPicture n (x:xs) = safe (n-1) xs
making sure !! succeds
If you do want to use the standard access function !!, one way to go about it (but potentially inefficient in the general case) would be to construct a "safe" infinite list.
import Data.List
blocoParaPicture :: Int -> [Picture] -> Either String Picture
blocoParaPicture n xs = zs !! n
where zs = [Right x | x <- xs] ++ repeat (Left "X")
The list zs is an infinite list made up of two lists. First [Right x | x <- xs] which just like your original list, but each element x becomes Right x. Then from then onwards all elements are of the form Left "X" to indicate failure. In general the above approach can be inefficient. If you look for a big n in a list:
[Right 1, Right 2] ++ [Left "X", Left "X", ...
you are doing many unnecessary steps, since you could stop when the first list ends. But works just fine for small n.
using lookup
Yet another possibility, similar to your attempt to use the elem function, would be to use lookup on indices. This function is safe by design.
lookup :: Eq a => a -> [(a, b)] -> Maybe b
Following this approach you first construct the list,
[(0,x0), (1,x1), (2,x2) ...(k,xk)]
and then look for your given n to return the associated xn (or Nothing).
blocoParaPicture' :: Int -> [Picture] -> Maybe Picture
blocoParaPicture' n xs = lookup n (zip [1..] xs)
This returns Nothing when not found though. But if you wish to, you can convert to Either via maybe :: b -> (a -> b) -> Maybe a -> b.
blocoParaPicture :: Int -> [Picture] -> Either String Picture
blocoParaPicture n xs = maybe (Left "X") Right (lookup n (zip [1..] xs))
This is certainly a bit too complex when all you want is a simple access function. But can be handy in situations where things are not as simple.
Related
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'm trying to understand how the Select monad works. Apparently, it is a cousin of Cont and it can be used for backtracking search.
I have this list-based solution to the n-queens problem:
-- All the ways of extracting an element from a list.
oneOf :: [Int] -> [(Int,[Int])]
oneOf [] = []
oneOf (x:xs) = (x,xs) : map (\(y,ys) -> (y,x:ys)) (oneOf xs)
-- Adding a new queen at col x, is it threathened diagonally by any of the
-- existing queens?
safeDiag :: Int -> [Int] -> Bool
safeDiag x xs = all (\(y,i) -> abs (x-y) /= i) (zip xs [1..])
nqueens :: Int -> [[Int]]
nqueens queenCount = go [] [1..queenCount]
where
-- cps = columsn of already positioned queens.
-- fps = columns that are still available
go :: [Int] -> [Int] -> [[Int]]
go cps [] = [cps]
go cps fps = [ps | (p,nfps) <- oneOf fps, ps <- go (p:cps) nfps, safeDiag p cps]
I'm struggling to adapt this solution to use Select instead.
It seems that Select lets you abstract over the "evaluation function" that is used to compare answers. That function is passed to runSelect. I have the feeling that something like safeDiag in my solution could work as the evaluation function, but how to structure the Select computation itself?
Also, is it enough to use the Select monad alone, or do I need to use the transformer version over lists?
I realize this is question is almost 4 years old and already has an answer, but I wanted to chime in with some additional information for the sake of anyone who comes across this question in the future. Specifically, I want to try to answer 2 questions:
how are multiple Selects that return single values combined to create a single Select that returns a sequence of values?
is it possible to return early when a solution path is destined to fail?
Chaining Selects
Select is implemented as a monad transformer in the transformers library (go figure), but let's take a look at how one might implement >>= for Select by itself:
(>>=) :: Select r a -> (a -> Select r b) -> Select r b
Select g >>= f = Select $ \k ->
let choose x = runSelect (f x) k
in choose $ g (k . choose)
We start by defining a new Select which takes an input k of type a -> r (recall that Select wraps a function of type (a -> r) -> a). You can think of k as a function that returns a "score" of type r for a given a, which the Select function may use to determine which a to return.
Inside our new Select, we define a function called choose. This function passes some x to the function f, which is the a -> m b portion of monadic binding: it transforms the result of the m a computation into a new computation m b. So f is going to take that x and return a new Select, which choose then runs using our scoring function k. You can think of choose as a function that asks "what would the final result be if I selected x and passed it downstream?"
On the second line, we return choose $ g (k . choose). The function k . choose is the composition of choose and our original scoring function k: it takes in a value, calculates the downstream result of selecting that value, and returns the score of that downstream result. In other words, we've created a kind of "clairvoyant" scoring function: instead of returning the score of a given value, it returns the score of the final result we would get if we selected that value. By passing in our "clairvoyant" scoring function to g (the original Select that we're binding to), we're able to select the intermediate value that leads to the final result we're looking for. Once we have that intermediate value, we simply pass it back into choose and return the result.
That's how we're able to string together single-value Selects while passing in a scoring function that operates on an array of values: each Select is scoring the hypothetical final result of selecting a value, not necessarily the value itself. The applicative instance follows the same strategy, the only difference being how the downstream Select is computed (instead of passing a candidate value into the a -> m b function, it maps a candidate function over the 2nd Select.)
Returning Early
So, how can we use Select while returning early? We need some way of accessing the scoring function within the scope of the code that constructs the Select. One way to do that is to construct each Select within another Select, like so:
sequenceSelect :: Eq a => [a] -> Select Bool [a]
sequenceSelect [] = return []
sequenceSelect domain#(x:xs) = select $ \k ->
if k [] then runSelect s k else []
where
s = do
choice <- elementSelect (x:|xs)
fmap (choice:) $ sequenceSelect (filter (/= choice) domain)
This allows us to test the sequence in progress and short-circuit the recursion if it fails. (We can test the sequence by calling k [] because the scoring function includes all of the prepends that we've recursively lined up.)
Here's the whole solution:
import Data.List
import Data.List.NonEmpty (NonEmpty(..))
import Control.Monad.Trans.Select
validBoard :: [Int] -> Bool
validBoard qs = all verify (tails qs)
where
verify [] = True
verify (x:xs) = and $ zipWith (\i y -> x /= y && abs (x - y) /= i) [1..] xs
nqueens :: Int -> [Int]
nqueens boardSize = runSelect (sequenceSelect [1..boardSize]) validBoard
sequenceSelect :: Eq a => [a] -> Select Bool [a]
sequenceSelect [] = return []
sequenceSelect domain#(x:xs) = select $ \k ->
if k [] then runSelect s k else []
where
s = do
choice <- elementSelect (x:|xs)
fmap (choice:) $ sequenceSelect (filter (/= choice) domain)
elementSelect :: NonEmpty a -> Select Bool a
elementSelect domain = select $ \p -> epsilon p domain
-- like find, but will always return something
epsilon :: (a -> Bool) -> NonEmpty a -> a
epsilon _ (x:|[]) = x
epsilon p (x:|y:ys) = if p x then x else epsilon p (y:|ys)
In short: we construct a Select recursively, removing elements from the domain as we use them and terminating the recursion if the domain has been exhausted or if we're on the wrong track.
One other addition is the epsilon function (based on Hilbert's epsilon operator). For a domain of size N it will check at most N - 1 items... it might not sound like a huge savings, but as you know from the above explanation, p will usually kick off the remainder of the entire computation, so it's best to keep predicate calls to a minimum.
The nice thing about sequenceSelect is how generic it is: it can be used to create any Select Bool [a] where
we're searching within a finite domain of distinct elements
we want to create a sequence that includes every element exactly once (i.e. a permutation of the domain)
we want to test partial sequences and abandon them if they fail the predicate
Hope this helps clarify things!
P.S. Here's a link to an Observable notebook in which I implemented the Select monad in Javascript along with a demonstration of the n-queens solver: https://observablehq.com/#mattdiamond/the-select-monad
Select can be viewed as an abstraction of a search in a "compact" space, guided by some predicate. You mentioned SAT in your comments, have you tried modelling the problem as a SAT instance and throw it at a solver based on Select (in the spirit of this paper)? You can specialise the search to hardwire the N-queens specific constraints inside your and turn the SAT solver into a N-queens solver.
Inspired by jd823592's answer, and after looking at the SAT example in the paper, I have written this code:
import Data.List
import Control.Monad.Trans.Select
validBoard :: [Int] -> Bool
validBoard qs = all verify (tails qs)
where
verify [] = True
verify (x : xs) = and $ zipWith (\i y -> x /= y && abs (x-y) /= i) [1..] xs
nqueens :: Int -> [Int]
nqueens boardSize = runSelect (traverse selectColumn columns) validBoard
where
columns = replicate boardSize [1..boardSize]
selectColumn candidates = select $ \s -> head $ filter s candidates ++ candidates
It seems to arrive (albeit slowly) to a valid solution:
ghci> nqueens 8
[1,5,8,6,3,7,2,4]
I don't understand it very well, however. In particular, the way sequence works for Select, transmuting a function (validBoard) that works over a whole board into functions that take a single column index, seems quite magical.
The sequence-based solution has the defect that putting a queen in a column doesn't rule out the possibility of choosing the same column for subsequent queens; we end up unnecesarily exploring doomed branches.
If we want our column choices to be affected by previous decisions, we need to go beyond Applicative and use the power of Monad:
nqueens :: Int -> [Int]
nqueens boardSize = fst $ runSelect (go ([],[1..boardSize])) (validBoard . fst)
where
go (cps,[]) = return (cps,[])
go (cps,fps) = (select $ \s ->
let candidates = map (\(z,zs) -> (z:cps,zs)) (oneOf fps)
in head $ filter s candidates ++ candidates) >>= go
The monadic version still has the problem that it only checks completed boards, when the original list-based solution backtracked as soon as a partially completed board was found to be have a conflict. I don't know how to do that using Select.
I came across this very old sudoku code which seems greek to me coz of mainly this ugly type
type T = (Int,Int) -> [Int]
To understand this function for instance
mark :: ((Int,Int),Int) -> T -> T
mark (p#(i,j),n) s q#(x,y) =
if p==q then [n] else
if x==i || y==j || e x i && e y j then delete n $ s q else s q
where e a b = div (a-1) 3==div (b-1) 3
I can replace the T with the actual type
mark :: ((Int,Int),Int) -> (Int,Int)->[Int] -> (Int,Int)->[Int]
mark (p#(i,j),n) s q#(x,y) =
Now the type arguments don't seem to line up properly. p matches perfectly, but i get confused with "s". If I jump into the call for mark it's like this.....here the list I can easily see it's array of key value pairs with keys like (1,2) etc. These have been filtered for blanks or zeros in sudoku.
input :: String -> (Int,Int) -> [Int]
input s = foldr mark (const [1..9]) $
[(p,n) | (p,n) <- zip idx $ map read $ lines s >>= words, n>0]
The mark function is called with this list and accumulator which is a function (const [1..9]). This doesn't fit the type signature.
mark :: ((Int,Int),Int) -> (Int,Int)->[Int] -> (Int,Int)->[Int]
Problem with the code is that I can't see the actual result of the mark function which I still don't understand. When it's passed to a third function it gets some output. Any explanation on how to understand this sphagetti code?
A value of this type
type T = (Int,Int) -> [Int]
maps the coordinates of any sudoku cell (x,y) :: (Int,Int) into a set of the possible values such cell might have (represented as a list of digits [Int]).
The function const [0..9] maps any cell into the set of all digits. It acts as the initial state for a sudoku solver: at the beginning, assume any cell may have any digit.
I have the following list (it’s a length 2 list, but in my assignment I have a length +n list)
xxs = [(11,22,[(33,33,33),(44,44,44)]),(55,66,[(77,77,77),(88,88,88)])]
I’m trying to “replace” one 3-tuple (p1 or p2 or p3 or p4 from the image bellow) by list index (n) and by sub-list index (p).
The function, at the end, should be like:
fooo newtuple n p = (…)
For example: (replace p3 for (98,98,98):
fooo (98,98,98) 2 1
[(11, 22, [(33,33,33) , (44,44,44)]) , (55, 66, [(98,98,98),(88,88,88)])]
I planned the code like following this steps:
Access the pn that I want to change. I manage to achieve it by:
fob n p = ((aux2 xxs)!!n)!!p
where aux2 [] = []
aux2 ((_,_,c):xs) = c:aux2 xs
“replace” the 3-tuple. I really need some help here. I’m stuck. the best code (in my head it makes some sense) that I’ve done: (remember: please don’t be too bad on my code, I’ve only been studying Haskell only for 5 weeks)
foo n p newtuple = fooAux newtuple fob
where fooAux _ [] = []
fooAux m ((_):ds) = m:ds
fob n p = ((aux2 xxs)!!n)!!p
where aux2 [] = []
aux2 ((_,_,c):xs) = c:aux2 xs
Finally I will put all back together, using splitAt.
Is my approach to the problem correct? I really would appreciate some help on step 2.
I'm a bit new to Haskell too, but lets see if we can't come up with a decent way of doing this.
So, fundamentally what we're trying to do is modify something in a list. Using functional programming I'd like to keep it a bit general, so lets make a function update.
update :: Int -> (a -> a) -> [a] -> [a]
update n f xs = pre ++ (f val) : post
where (pre, val:post) = splitAt n xs
That will now take an index, a function and a list and replace the nth element in the list with the result of the function being applied to it.
In our bigger problem, however, we need to update in a nested context. Luckily our update function takes a function as an argument, so we can call update within that one, too!
type Triple a = (a,a,a)
type Item = (Int, Int, [Triple Int])
fooo :: Triple Int -> Int -> Int -> [Item] -> [Item]
fooo new n p = update (n-1) upFn
where upFn (x,y,ps) = (x,y, update (p-1) objFn ps)
objFn _ = new
All fooo has to do is call update twice (once within the other call) and do a little "housekeeping" work (putting the result in the tuple correctly). The (n-1) and (p-1) were because you seem to be indexing starting at 1, whereas Haskell starts at 0.
Lets just see if that works with our test case:
*Main> fooo (98,98,98) 2 1 [(11,22,[(33,33,33),(44,44,44)]),(55,66,[(77,77,77),(88,88,88)])]
[(11,22,[(33,33,33),(44,44,44)]),(55,66,[(98,98,98),(88,88,88)])]
First, we need a general function to map a certain element of a list, e.g.:
mapN :: (a -> a) -> Int -> [a] -> [a]
mapN f index list = zipWith replace list [1..] where
replace x i | i == index = f x
| otherwise = x
We can use this function twice, for the outer list and the inner lists. There is a little complication as the inner list is part of a tuple, so we need another helper function:
mapTuple3 :: (c -> c) -> (a,b,c) -> (a,b,c)
mapTuple3 f (x,y,z) = (x,y,f z)
Now we have everything we need to apply the replace function to our use case:
fooo :: Int -> Int -> (Int,Int,Int) -> [(Int,Int,[(Int,Int,Int)])]
fooo n p newTuple = mapN (mapTuple3 (mapN (const newTuple) p)) n xxs
Of course in the inner list, we don't need to consider the old value, so we can use const :: a -> (b -> a) to ignore that argument.
So you've tried using some ready-made function, (!!). It could access an item in a list for you, but forgot its place there, so couldn't update. You've got a solution offered, using another ready-made function split, that tears a list into two pieces, and (++) which glues them back into one.
But to get a real feel for it, what I suspect your assignment was aiming at in the first place (it's easy to forget a function name, and it's equally easy to write yourself a new one instead), you could try to write the first one, (!!), yourself. Then you'd see it's real easy to modify it so it's able to update the list too.
To write your function, best think of it as an equivalence equation:
myAt 1 (x:xs) = x
myAt n (x:xs) | n > 1 = ...
when n is zero, we just take away the head element. What do we do when it's not? We try to get nearer towards the zero. You can fill in the blanks.
So here we returned the element found. What if we wanted to replace it? Replace it with what? - this calls another parameter into existence,
myRepl 1 (x:xs) y = (y:xs)
myRepl n (x:xs) y | n > 1 = x : myRepl ...
Now you can complete the rest, I think.
Lastly, Haskell is a lazy language. That means it only calls into existence the elements of a list that are needed, eventually. What if you replace the 7-th element, but only first 3 are later asked for? The code using split will actually demand the 7 elements, so it can return the first 3 when later asked for them.
Now in your case you want to replace in a nested fashion, and the value to replace the old one with is dependent on the old value: newVal = let (a,b,ls)=oldVal in (a,b,myRepl p ls newtuple). So indeed you need to re-write using functions instead of values (so that where y was used before, const y would go):
myUpd 1 (x:xs) f = (f x:xs)
myUpd n ... = ...
and your whole call becomes myUpd n xxs (\(a,b,c)->(a,b,myUpd ... (const ...) )).
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.