The goal is to find the Longest Increasing Subsequence (LIS) of a list in Haskell. I tried to run the following code, but the error of couldn't find modules appeared. I saw answers to This question and I understand that the ordered package is old and not used anymore.
import Data.Ord ( comparing )
import Data.List ( maximumBy, subsequences )
import Data.List.Ordered ( isSorted, nub )
lis :: Ord a => [a] -> [a]
lis = maximumBy (comparing length) . map nub . filter isSorted . subsequences
-- longest <-- unique <-- increasing <-- all
main = do
print $ lis [3,2,6,4,5,1]
print $ lis [0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15]
print $ lis [1,1,1,1]
Therefore, I tried to use only:
import Data.List
but I got the following error :
main.hs:3:18: error:
Variable not in scope:
comparing :: (t0 a0 -> Int) -> [a] -> [a] -> Ordering
|
3 | lis = maximumBy (comparing length) . map nub . filter isSorted . subsequences
| ^^^^^^^^^
main.hs:3:56: error: Variable not in scope: isSorted :: [a] -> Bool
|
3 | lis = maximumBy (comparing length) . map nub . filter isSorted . subsequences
| ^^^^^^^^
exit status 1
nub is now in Data.List. If an isSorted function is available in any normal library, Hoogle doesn't show it. You can easily write one yourself, though I haven't given much thought to whether the following suggestion is the most efficient implementation - and it probably doesn't work with infinite lists (I think that the answer to both questions is no):
isSorted :: Ord a => [a] -> Bool
isSorted l = sort l == l
(Using sort from Data.List.)
With these imports:
import Data.Ord (comparing)
import Data.List (maximumBy, subsequences, nub, sort)
the lis function now compiles.
Related
This is a function that produces an infinite list of random numbers
import System.Random
values :: [Int]
values = map fst $ scanl (\(r, gen) _ -> randomR (1,10) gen) (randomR (1,10) (mkStdGen 1)) $ repeat ()
I want to reduce sequences for duplicate elements into one element e.g
[2,3,4,1,7,7,7,3,4,1,1,1,3,..] -> [2,3,4,1,7,3,4,1,3,..]
So, I need some elegant function "f" from [Int] -> [Int] that do this.
Also, it must work with an infinite list lazily, so if I run
f values
it must not hang and output data in real-time
You can work with group :: Eq a => [a] -> [[a]] to make a list of groups. So for the given sample data, this will generate:
Prelude> import Data.List(group)
Prelude Data.List> group [2,3,4,1,7,7,7,3,4,1,1,1,3]
[[2],[3],[4],[1],[7,7,7],[3],[4],[1,1,1],[3]]
Then we can for each sublist only yield the first element with head, we know that such element exists, since otherwise it would never have constructed a new group in the first place:
Prelude Data.List> map head (group [2,3,4,1,7,7,7,3,4,1,1,1,3])
[2,3,4,1,7,3,4,1,3]
This thus means that you can define f as:
import Data.List(group)
f :: Eq a => [a] -> [a]
f = map head . group
This works on infinite lists as well. For example if we end the list with an infinite list of 5s, then it processes the list until that five and keeps looking for a new value:
Prelude Data.List> map head (group (2 : 3 : 4 : 1 : 7 : 7 : 7 : 3 : 4 : 1 : 1 : 1 : 3 : repeat 5))
[2,3,4,1,7,3,4,1,3,5
or we can make use of the group :: (Foldable f, Eq a) => f a -> [NonEmpty a] of Data.List.NonEmpty:
import Data.List.NonEmpty(group)
import qualified Data.List.NonEmpty as NE
f :: Eq a => [a] -> [a]
f = map NE.head . group
I have a list with some sublists and I need to order it by length.
For example:
[[1,3,4,9],[2,4],[5,4,7]] would become [[2,4],[5,4,7],[1,3,4,9]].
You can make use of sortOn :: Ord b => (a -> b) -> [a] -> [a] to sort items in a list based on the result of a function called on the elements, for example:
Prelude> import Data.List(sortOn)
Prelude Data.List> sortOn length [[1,3,4,9],[2,4],[5,4,7]]
[[2,4],[5,4,7],[1,3,4,9]]
You can use comparing to generate a custom comparison function with the length function, the sort the list with the builtin sortBy function:
import Data.List
import Data.Ord
x :: [[Int]]
x = sortBy (comparing length) [[1,3,4,9],[2,4],[5,4,7]]
-- x == [[2,4],[5,4,7],[1,3,4,9]]
I need to have both the elements of a list satisfying a predicate and the indices of these elements. I can achieve this as follows:
import Data.List (findIndices)
list :: [Int]
list = [3,2,4,1,9]
indices = findIndices (>2) list
elems = [list!!i | i <- indices]
-- same as: elems = filter (>2) list
Isn't there a package providing a function giving both the elements and their indices in "one shot" ? I'm surprised I don't find this function somewhere. Otherwise, how to do such a function, improving my above code ? I don't believe this code is optimal since it somehow accesses twice to the elements of the list. I took a quick look at the source code of findIndices but I don't understand it yet.
You can make it more efficient – avoid the !! access – by filtering a list of (index, element) tuples.
let (indices, elems) = unzip [(i, x) | (i, x) <- zip [0..] list, x > 2]
Split into an appropriate function:
findItems :: (a -> Bool) -> [a] -> [(Int, a)]
findItems predicate = filter (predicate . snd) . zip [0..]
let (indices, elems) = unzip $ findItems (>2) list
There might be a more straightforward way, and I’ll be happy to find out about it :)
I think Ry's suggestion is just fine. For a more direct, and in particular more generic one, you could use lens tooling:
Prelude> import Control.Lens as L
Prelude L> import Control.Arrow as A
Prelude L A> ifoldr (\i x -> if x>2 then (i:)***(x:) else id) ([],[]) [3,2,4,1,9]
([0,2,4],[3,4,9])
This can immediately be used also on arrays (where the index extraction is much more useful)
Prelude L A> import qualified Data.Vector as V
Prelude L A V> ifoldr (\i x -> if x>2 then (i:)***(x:) else id) ([],[]) $ V.fromList [3,2,4,1,9]
([0,2,4],[3,4,9])
...even on unboxed ones, though these aren't Foldable:
Prelude L A V> import qualified Data.Vector.Unboxed as VU
Prelude L A V VU> import Data.Vector.Generic.Lens as V
ifoldrOf vectorTraverse (\i x -> if x>2 then (i:)***(x:) else id) ([],[]) $ VU.fromList [3,2,4,1,9]
([0,2,4],[3.0,4.0,9.0])
(indices, elems) = unzip [ item | item <- zip [0..] ls, (snd item) > 2 ]
Not sure that it's any more efficient, but it gets it done in "one shot".
I wrote something using Data.List.groupBy. It didn't work as expected so I end up writting my own version of groupBy : after all I'm not sure that the Data.List one is supposed to do (there is no real documentation).
Anyway my tests passed with my version of groupBy whereas it fails with the Data.List.
I found (thanks quickcheck) a case where the two function behaves differently, and I still don't understand why there is a difference between the two versions. Is the Data.List version buggy or is is mine ? (Of course mine is a naive implementation and is probably not the most efficient way to do so).
Here is the code :
import qualified Data.List as DL
import Data.Function (on)
import Test.QuickCheck
groupBy' :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy' _ [] = []
groupBy' eq (x:xs) = xLike:(groupBy' eq xNotLike) where
xLike = x:[ e | e <- xs, x `eq` e ]
xNotLike = [ e | e <- xs, not $ x `eq` e ]
head' [] = Nothing
head' (x:xs) = Just x
prop_a s = (groupBy' by s) == (DL.groupBy by s) where
types = s :: [String]
by = (==) `on` head'
running in ghc quickCheck prop_a returns ["", "a", ""]
*Main> groupBy' ((==) `on` head') ["","a",""]
[["",""],["a"]] # correct in my opinion
*Main> DL.groupBy ((==) `on` head') ["","a",""]
[[""],["a"],[""]] # incorrect.
What's happening ? I can't believe there is a bug in the haskell-platform .
Your version is O (n2) – which can be unacceptably slow in real-world use1.
The standard version avoids this by only grouping adjacent elements if they are equivalent. Hence,
*Main> groupBy ((==) `on` head') ["", "", "a"]
will yield the result you're after.
A simple way to obtain "universal grouping" with groupBy is to first sort the list if that's feasible for the data type.
*Main> groupBy ((==) `on` head') $ DL.sort ["", "a", ""]
The complexity of this is only O (n log n).
1 This didn't prevent the committee from specifying nub as O (n2)...
Data.List.groupBy in Haskell is a usability mistake! A user friendly groupBy should behave like this:
groupByWellBehaved p = foldr (\x rest -> if null rest
then [[x]]
else if p x (head (head rest))
then (x : head rest) : (tail rest)
else [x] : rest) []
Perhaps there is a better implementation, but at least this is O(n).
I am trying to build a function that takes the first element of a string, and removes all other elements equal to it from the string. Then does the same for the second character.
Ie - "Heello" would become "Helo" and "Chocolate" "Chlate"
My original attempt
removeSuccessor :: String -> String
removeSuccessor x = [c | c <- x, x ! `elem` c]
But that doesn't seem to work.. suggestions?
You could keep a set of all elements seen and only keep the current one if it hasn't been seen yet:
import Data.Set
removeDups :: Ord a => [a] -> Set a -> [a]
removeDups [] sofar = []
removeDups (x:rest) sofar
| member x sofar = (removeDups rest sofar)
| otherwise = x:(removeDups rest (insert x sofar))
Usage:
removeDups "Heello" empty -- "Helo"
removeDups "Chocolate" empty -- "Choclate"
Run time is O(n log n), I think.
Or you can use nub from Data.List:
Prelude Data.List> import Data.List
Prelude Data.List> nub "Heello"
"Helo"
Prelude Data.List> nub "Chocolate"
"Choclate"
Run-time is O(n^2).