I have the following function that determines the maximum element of a given list.
maxList :: Ord a => [a] -> a
maxList l =
let iMaxList :: Ord a => [a] -> a
iMaxList [] = error( "Empty list" )
iMaxList [x] = x
iMaxList ( x:xs )
| x > t = x
| otherwise = t
where t = iMaxList xs
in iMaxList l
Yet, it doesn't use tail recursion and I'd like it to do so.
I tried to use an accumulator to comply with the tail recursion principle in Haskell.
maxList :: Ord a => [a] -> a
maxList ( x:xs ) = loop( xs, x )
where loop( x:xs, m )
| ( null xs ) = m
| ( x >= m ) = loop( xs, x )
| otherwise = loop( xs, m )
Yet, it logically fails because of this guard (null xs) = m. Indeed, if we take the list [1,2,3,4], 4will never be evaluated.
How can I fix that?
listMax :: Ord a => [a] -> a
listMax [] = error "Tried to find maximum of an empty list."
listMax (x:xs) = listMax' xs x where
listMax' :: Ord a => [a] -> a -> a
listMax' [] y = y
listMax' (x:xs) y | x > y = listMax' xs x
| otherwise = listMax' xs y
In this case, y is the accumulating parameter that holds the maximum value found so far. Brief proof of correctness: the algorithm terminates because each tail-recursive call removes one element from the input list until it is empty. The final value of y it returns is the maximum because, for every other element x in the input, either y > x or y > z > x for some z after x and before y. (This assumes that > is transitive.)
You could also write the helper function this way:
listMax' :: Ord a => [a] -> a -> a
listMax' [] y = y
listMax' (x:xs) y = listMax' xs (max x y)
And this implementation does the same thing:
listMax2 :: Ord a => [a] -> a
listMax2 [] = error "Tried to find maximum of an empty list."
listMax2 list = foldl1 max list
The foldl1 function is a tail-recursive lazy evaluation from front to back, but the strict foldl1' version or foldr1 might be more efficient in this case. The first version is closer to strict evaluation than lazy.
I guess this is what your are searching for:
maxList' :: Ord a => [a] -> a
maxList' [] = error "Empty List"
maxList' [x] = x
maxList' (x:y:xs) = maxList' (max x y:xs)
The function uses the same list that is processing to store the biggest number found so far. It seems to comply with the tail recursion definition, ie: the recursive call is the very last thing in the computation of the function.
Don't worry about it.
I wrote the following in a file:
module MaxList (maxList) where
import Data.List
maxList :: Ord a => [a] -> a
maxList = foldl1' max
Then I compiled it with -O2 -ddump-simpl, to have a look at the optimised Core. After a bit of cleaning up - GHC generates a lot of variables with names that are difficult to read - the generated code looks like this:
maxList [] = error "empty list"
maxList (x:xs) = go xs x
where go ys y =
case ys of
[] -> y;
(z:zs) -> case y of -- force y to WHNF before continuing
_ -> go zs (max y z)
go is tail recursive. In fact it's the same as the code in #Davislor's answer! I used foldl1' - a high-level control structure - and GHC generated exactly the code that you would've written by hand if you wanted to write a tail recursive loop.
Haskell's philosophy is that you should use high-level tools like folds, unfolds, monads, classes, etc, and rely on the compiler to generate good code. There certainly is an art to writing code which GHC will do a good job of optimising - you don't always get it for free - but you usually shouldn't need to unroll high-level structures into low-level loops because GHC is good at that.
Related
You must use recursion to define rmax2 and you must do so from “scratch”. That is, other than the cons operator, head, tail, and comparisons, you should not use any functions from the Haskell library.
I created a function that removes all instances of the largest item, using list comprehension. How do I remove the last instance of the largest number using recursion?
ved :: Ord a => [a] -> [a]
ved [] =[]
ved as = [ a | a <- as, m /= a ]
where m= maximum as
An easy way to split the problem into two easier subproblems consists in:
get the position index of the rightmost maximum value
write a general purpose function del that eliminates the element of a list at a given position. This does not require an Ord constraint.
If we were permitted to use regular library functions, ved could be written like this:
ved0 :: Ord a => [a] -> [a]
ved0 [] = []
ved0 (x:xs) =
let
(maxVal,maxPos) = maximum (zip (x:xs) [0..])
del k ys = let (ys0,ys1) = splitAt k ys in (ys0 ++ tail ys1)
in
del maxPos (x:xs)
where the pairs produced by zip are lexicographically ordered, thus ensuring the rightmost maximum gets picked.
We need to replace the library functions by manual recursion.
Regarding step 1, that is finding the position of the rightmost maximum, as is commonly done, we can use a recursive stepping function and a wrapper above it.
The recursive step function takes as arguments the whole context of the computation, that is:
current candidate for maximum value, mxv
current rightmost position of maximum value, mxp
current depth into the original list, d
rest of original list, xs
and it returns a pair: (currentMaxValue, currentMaxPos)
-- recursive stepping function:
findMax :: Ord a => a -> Int -> Int -> [a] -> (a, Int)
findMax mxv mxp d [] = (mxv,mxp)
findMax mxv mxp d (x:xs) = if (x >= mxv) then (findMax x d (d+1) xs)
else (findMax mxv mxp (d+1) xs)
-- top wrapper:
lastMaxPos :: Ord a => [a] -> Int
lastMaxPos [] = (-1)
lastMaxPos (x:xs) = snd (findMax x 0 1 xs)
Step 2, eliminating the list element at position k, can be handled in very similar fashion:
-- recursive stepping function:
del1 :: Int -> Int -> [a] -> [a]
del1 k d [] = []
del1 k d (x:xs) = if (d==k) then xs else x : del1 k (d+1) xs
-- top wrapper:
del :: Int -> [a] -> [a]
del k xs = del1 k 0 xs
Putting it all together:
We are now able to write our final recursion-based version of ved. For simplicity, we inline the content of wrapper functions instead of calling them.
-- ensure we're only using authorized functionality:
{-# LANGUAGE NoImplicitPrelude #-}
import Prelude (Ord, Eq, (==), (>=), (+), ($), head, tail,
IO, putStrLn, show, (++)) -- for testing only
ved :: Ord a => [a] -> [a]
ved [] = []
ved (x:xs) =
let
findMax mxv mxp d [] = (mxv,mxp)
findMax mxv mxp d (y:ys) = if (y >= mxv) then (findMax y d (d+1) ys)
else (findMax mxv mxp (d+1) ys)
(maxVal,maxPos) = findMax x 0 1 xs
del1 k d (y:ys) = if (d==k) then ys else y : del1 k (d+1) ys
del1 k d [] = []
in
del1 maxPos 0 (x:xs)
main :: IO ()
main = do
let xs = [1,2,3,7,3,2,1,7,3,5,7,5,4,3]
res = ved xs
putStrLn $ "input=" ++ (show xs) ++ "\n" ++ " res=" ++ (show res)
If you are strictly required to use recursion, you can use 2 helper functions: One to reverse the list and the second to remove the first largest while reversing the reversed list.
This result in a list where the last occurrence of the largest element is removed.
We also use a boolean flag to make sure we don't remove more than one element.
This is ugly code and I really don't like it. A way to make things cleaner would be to move the reversal of the list to a helper function outside of the current function so that there is only one helper function to the main function. Another way is to use the built-in reverse function and use recursion only for the removal.
removeLastLargest :: Ord a => [a] -> [a]
removeLastLargest xs = go (maximum xs) [] xs where
go n xs [] = go' n True [] xs
go n xs (y:ys) = go n (y:xs) ys
go' n f xs [] = xs
go' n f xs (y:ys)
| f && y == n = go' n False xs ys
| otherwise = go' n f (y:xs) ys
Borrowing the implementation of dropWhileEnd from Hackage, we can implement a helper function splitWhileEnd:
splitWhileEnd :: (a -> Bool) -> [a] -> ([a], [a])
splitWhileEnd p = foldr (\x (xs, ys) -> if p x && null xs then ([], x:ys) else (x:xs, ys)) ([],[])
splitWhileEnd splits a list according to a predictor from the end. For example:
ghci> xs = [1,2,3,4,3,2,4,3,2]
ghci> splitWhileEnd (< maximum xs) xs
([1,2,3,4,3,2,4],[3,2])
With this helper function, you can write ven as:
ven :: Ord a => [a] -> [a]
ven xs =
let (x, y) = splitWhileEnd (< maximum xs) xs
in init x ++ y
ghci> ven xs
[1,2,3,4,3,2,3,2]
For your case, you can refactor splitWhileEnd as:
fun p = \x (xs, ys) -> if p x && null xs then ([], x:ys) else (x:xs, ys)
splitWhileEnd' p [] = ([], [])
splitWhileEnd' p (x : xs) = fun p x (splitWhileEnd' p xs)
ven' xs = let (x, y) = splitWhileEnd' (< maximum xs) xs in init x ++ y
If init and ++ are not allowed, you can implement them manually. It's easy!
BTW, I guess this may be your homework for Haskell course. I think it's ridiculous if your teacher gives the limitations. Who is programming from scratch nowadays?
Anyway, you can always work around this kind of limitations by reimplementing the built-in function manually. Good luck!
I need some kind of fold which can terminate if I already have the data I want.
For example I need to find first 3 numbers which are greater than 5. I decided to use Either for termination and my code looks like this:
terminatingFold :: ([b] -> a -> Either [b] [b]) -> [a] -> [b]
terminatingFold f l = reverse $ either id id $ fold [] l
where fold acc [] = Right acc
fold acc (x:xs) = f acc x >>= flip fold xs
first3NumsGreater5 acc x =
if length acc >= 3
then Left acc
else Right (if x > 5 then (x : acc) else acc)
Are there some more clever/generic approaches?
The result of your function is a list, and it would be desirable if it were produced lazily, that is, extracting one item from the result should only require evaluating the input list up until the item is found there.
Unfolds are under-appreciated for these kinds of tasks. Instead of focusing on "consuming" the input list, let's think of it as a seed from which (paired with some internal accumulator) we can produce the result, element by element.
Let's define a Seed type that contains a generic accumulator paired with the as-yet unconsumed parts of the input:
{-# LANGUAGE NamedFieldPuns #-}
import Data.List (unfoldr)
data Seed acc input = Seed {acc :: acc, pending :: [input]}
Now let's reformulate first3NumsGreater5 as a function that either produces the next output element from the Seed, of signals that there aren't any more elements:
type Counter = Int
first3NumsGreater5 :: Seed Counter Int -> Maybe (Int, Seed Counter Int)
first3NumsGreater5 (Seed {acc, pending})
| acc >= 3 =
Nothing
| otherwise =
case dropWhile (<= 5) pending of
[] -> Nothing
x : xs -> Just (x, Seed {acc = succ acc, pending = xs})
Now our main function can be written in terms of unfoldr:
unfoldFromList ::
(Seed acc input -> Maybe (output, Seed acc input)) ->
acc ->
[input] ->
[output]
unfoldFromList next acc pending = unfoldr next (Seed {acc, pending})
Putting it to work:
main :: IO ()
main = print $ unfoldFromList first3NumsGreater5 0 [0, 6, 2, 7, 9, 10, 11]
-- [6,7,9]
Normally an early termination-capable fold is foldr with the combining function which is non-strict in its second argument. But, its information flow is right-to-left (if any), while you want it left-to-right.
A possible solution is to make foldr function as a left fold, which can then be made to stop early:
foldlWhile :: Foldable t
=> (a -> Bool) -> (r -> a -> r) -> r
-> t a -> r
foldlWhile t f a xs = foldr cons (\acc -> acc) xs a
where
cons x r acc | t x = r (f acc x)
| otherwise = acc
You will need to tweak this for t to test the acc instead of x, to fit your purposes.
This function is foldlWhile from https://wiki.haskell.org/Foldl_as_foldr_alternative, re-written a little. foldl'Breaking from there might fit the bill a bit better.
foldr with the lazy reducer function can express corecursion perfectly fine just like unfoldr does.
And your code is already lazy: terminatingFold (\acc x -> Left acc) [1..] => []. That's why I'm not sure if this answer is "more clever", as you've requested.
edit: following a comment by #danidiaz, to make it properly lazy you'd have to code it as e.g.
first3above5 :: (Foldable t, Ord a, Num a)
=> t a -> [a]
first3above5 xs = foldr cons (const []) xs 0
where
cons x r i | x > 5 = if i==2 then [x]
else x : r (i+1)
| otherwise = r i
This can be generalized further by abstracting the test and the count.
Of course it's just reimplementing take 3 . filter (> 5), but shows how to do it in general with foldr.
my title might be a bit off and i'll try to explain a bit better what i'm trying to achieve.
Basically let's say i have a list:
["1234x4","253x4",2839",2845"]
Now i'd like to add all the positions of the strings which contain element 5 to a new list. On a current example the result list would be:
[1,3]
For that i've done similar function for elem:
myElem [] _ = False
myElem [x] number =
if (firstCheck x) then if digitToInt(x) == number then True else False else False
myElem (x:xs) number =
if (firstCheck x) then (if digitToInt(x) == number then True else myElem xs number) else myElem xs number
where firstCheck x checks that the checked element isn't 'x' or '#'
Now in my current function i get the first element position which contains the element, however my head is stuck around on how to get the full list:
findBlock (x:xs) number arv =
if myElem x number then arv else findBlock xs number arv+1
Where arv is 0 and number is the number i'm looking for.
For example on input:
findBlock ["1234x4","253x4",2839",2845"] 5 0
The result would be 1
Any help would be appreciated.
The function you want already exists in the Data.List module, by the name of findIndices. You can simply use (elem '5') as the predicate.
http://hackage.haskell.org/package/base-4.8.1.0/docs/Data-List.html#v:findIndices
If, for some reason, you're not allowed to use the built-in one, it comes with a very pretty definition (although the one actually used has a more complicated, more efficient one):
findIndices p xs = [ i | (x,i) <- zip xs [0..], p x]
By the way, I found this function by searching Hoogle for the type [a] -> (a -> Bool) -> [Int], which (modulo parameter ordering) is obviously the type such a function must have. The best way to find out of Haskell has something is to think about the type it would need to have and search Hoogle or Hayoo for the type. Hoogle is better IMO because it does slightly fuzzy matching on the type; e.g. Hayoo wouldn't find the function here by the type I've given, because it take the arguments in the reverse order.
An implementation of findIndices, for instructional purposes:
findIndices ok list = f list 0 where
f [] _ = []
f (x:xs) ix
| ok x = ix : f xs (ix+1)
| otherwise = f xs (ix+1)
Use it like findIndices (elem '5') my_list_o_strings
You're trying to work your way through a list, keeping track of where you are in the list. The simplest function for doing this is
mapWithIndex :: (Int -> a -> b) -> [a] -> [b]
mapWithIndex = mwi 0 where
mwi i _f [] = i `seq` []
mwi i f (x:xs) = i `seq` f i x : mwi (i+1) f xs
This takes a function and a list, and applies the function to each index and element. So
mapWithIndex (\i x -> (i, x)) ['a', 'b', 'c'] =
[(0,'a'), (1,'b'),(2,'c')]
Once you've done that, you can filter the list to get just the pairs you want:
filter (elem '5' . snd)
and then map fst over it to get the list of indices.
A more integrated approach is to use foldrWithIndex.
foldrWithIndex :: (Int -> a -> b -> b) -> b -> [a] -> b
foldrWithIndex = fis 0 where
fis i _c n [] = i `seq` n
fis i c n (x:xs) = i `seq` c i x (fis (i+1) c n xs)
This lets you do everything in one step.
It turns out that you can implement foldrWithIndex using foldr pretty neatly, which makes it available for any Foldable container:
foldrWithIndex :: (Foldable f, Integral i) =>
(i -> a -> b -> b) -> b -> f a -> b
foldrWithIndex c n xs = foldr go (`seq` n) xs 0 where
go x r i = i `seq` c i x (r (i + 1))
Anyway,
findIndices p = foldrWithIndex go [] where
go i x r | p x = i : r
| otherwise = r
I'm trying to write function and i dont know why i cannot make it in that way
ssm' = foldr (\x acc -> if acc == [] then [x]++acc else if (x > (maximum acc)) then [x]++acc else acc) []
give me a clue please.
By the way, your code looks way too complicated. You overuse if, and [x]++acc is just x:acc. Scanning acc in every step using maximum is wasteful, as its biggest element must be its head. Alltogether I'd write:
ssm' :: Ord a => [a] -> [a]
ssm' = foldr go [] where
go x [] = [x]
go x ms#(m:_)
| x > m = x:ms
| otherwise = ms
If you really like one-liners, try
import Data.List
ssm' xs = reverse $ map head $ groupBy (>) (reverse xs)
You've run into the monomorphism restriction. You can fix it by adding a type signature.
ssm' :: Ord a => [a] -> [a]
ssm' = ...
I have recently been teaching myself Haskell, and one of my exercises was to re-implement the filter function. However, of all the exercises I have performed, my answer for this one seems to me the most ugly and long. How could I improve it? Are there any Haskell tricks I don't yet know?
myfilter :: (a -> Bool) -> [a] -> [a]
myfilter f (x:xs) = if f x
then x : myfilter f xs
else myfilter f xs
myfilter _ [] = []
Thank You
The simplest way to neaten your implementation is to use guards. Instead of pattern = value, you can write write pattern | boolean = value; this will only match when boolean is true. Thus, we can get
filter1 :: (a -> Bool) -> [a] -> [a]
filter1 p (x:xs) | p x = x : filter1 p xs
| otherwise = filter1 p xs
filter1 _ [] = []
(Note that otherwise is just a synonym for True.) Now, we have filter p xs in two places, so we can move it out into a where clause; these are shared by everything which shares a common pattern, even if it has a different guard:
filter2 :: (a -> Bool) -> [a] -> [a]
filter2 p (x:xs) | p x = x : xs'
| otherwise = xs'
where xs' = filter2 p xs
filter2 _ [] = []
(This implementation is the one used by GHCs Prelude.)
Now, neither of these are tail-recursive. This can be disadvantageous, but it does make the function lazy. If we want a tail-recursive version, we could write
filter3 :: (a -> Bool) -> [a] -> [a]
filter3 p xs = let filter3' p (x:xs) ys | p x = next $! x:ys
| otherwise = next $! ys
where next = filter3' p xs
filter3' _ [] ys = reverse ys
in filter3' p xs []
Note, however, that this would fail on infinite lists (though all the other implementations will work), thanks to the reverse, so we make it strict with $!. (I think I did this right—I could have forced the wrong variable. I think I got this one right, though.)
Those implementations all look like yours. There are, of course, others. One is based on foldr:
filter4 :: (a -> Bool) -> [a] -> [a]
filter4 p = let check x | p x = (x :)
| otherwise = id
in foldr check []
We take advantage of point-free style here; since xs would be the last argument to both filter4 and foldr check [], we can elide it, and similarly with the last argument of check.
You could also take advantage of the list monad:
import Control.Monad
filter5 :: MonadPlus m => (a -> Bool) -> m a -> m a
filter5 p xs = do x <- xs
guard $ p x
return x
The list monad represents nondeterminism. You pick an element x from xs, make sure that it satisfies p, and then return it if it does. All of these results are then collected together. But note that this is now more general; this works for any MonadPlus (a monad which is also a monoid; that is, which has an associative binary operation mplus—++ for lists—and an identity element mzero—[] for lists), such as [] or Maybe. For instance, filter5 even $ Just 1 == Nothing, and filter5 even $ Just 2 == Just 2.
We can also adapt the foldr-based version to get a different generic type signature:
import Control.Monad
import qualified Data.Foldable as F
import qualified Data.Monoid as M
filter6 :: (F.Foldable f, MonadPlus m, M.Monoid (m a))
=> (a -> Bool) -> f a -> m a
filter6 p = let check x | p x = return x
| otherwise = mzero
in F.foldMap check
The Data.Foldable module provides the Foldable type class, which represents any structure which can be folded like a list (placing the result in a generic Monoid instead.) Our filter requires a MonadPlus constraint on the result as well so that we can write return x. The foldMap function requires a function which converts everything to elements of a Monoid, and then concatenates all of them together. The mismatch between the f a on the left and the m a on the right means you could, for instance, filter6 a Maybe and get back a list.
I'm sure that there are (many!) other implementations of filter, but these are the 6 that I could think of relatively quickly. Now, which of these do I actually like best? It's a tossup between the straightforward filter2 and the foldr-based filter4. And filter5 is nice for its generic type signature. (I don't think I've ever needed a type signature like filter6's.) The fact that filter2 is used by GHC is a plus, but GHC also uses some funky rewrite rules, so it's not obvious to me that it's superior without those. Personally, I would probably go with filter4 (or filter5 if I needed the genericity), but filter2 is definitely fine.
How about a list comprehension?
myfilter f xs = [x | x <- xs, f x]
You could at least DRY it up a bit by pulling out that common myfilter f xs code:
myfilter :: (a -> Bool) -> [a] -> [a]
myfilter f (x:xs) = if f x
then x : rest
else rest
where rest = myfilter f xs
myfilter _ [] = []
For comparison, here's Wikipedia's implementation:
myfilter :: (a -> Bool) -> [a] -> [a]
myfilter _ [] = []
myfilter f (x:xs) | f x = x : myfilter f xs
| otherwise = myfilter f xs
In Haskell, most of the time you can (and should) use guards instead of if-then-else:
myfilter :: (a -> Bool) -> [a] -> [a]
myfilter f (x:xs)
| f x = x : myfilter f xs
| otherwise = myfilter f xs
myfilter _ [] = []
This ends up being basically the same definition as used in the standard library.