Nested Loop Formatting - haskell

I am trying to produce an output where the input list is split each time f x is true. I use two variables to keep track of the substring and the final list, and this function will be called by another that provides empty lists for two tracking variables. Example desired output:
separate odd [1,2,3,4] = [[2],[4]]
Below is what I have so far - although I keep running into type errors because lists all have to be of the same type - can anyone advise what changes need to be made to produce the desired output?
separate f (x:xs) sublist finalstr
| f x = (finalstr ++ sublist) : separate f xs sublist finalstr
| otherwise = (sublist ++ x) : separate f xs sublist finalstr
separate f [] sublist finalstr = []

You could divide your problem into the following sub-problems:
Group each element in the list by what f returns:
groupOn :: Eq b => (a -> b) -> [a] -> [[a]]
groupOn f = ...
For example,
> groupOn odd [1,3,3,4,5,6,8]
[[1,3,3],[4],[5],[6,8]]
Filter out sub-lists in which the first element satisfies f:
separate :: (a -> Bool) -> [a] -> [[a]]
separate f xs = filter (\ys -> ...) (groupOn f xs)
where ys would be [1,3,3], [4], [5] and [6,8] in the above example.

Related

Haskell Nested Loops

I am trying to split a list whenever f returns true, for example:
separate even [1,2,3,4] = [[2],[4]]
Current code:
separate f (x:xs) currentstr finalstr
| f x = (finalstr ++ currentstr) : separate f xs [] finalstr
| otherwise = (currentstr ++ x) : separate f xs (currentstr + x) finalstr
separate f [] currentstr finalstr = []
Can anyone provide some insight on how to fix this? Values for currentstr and finalstr will be provided as [] in another function always, so this is not a concern.
You could divide your problem into the following sub-problems:
Split a list in two where the first sequence is equivalent when applying f to each element:
splitOn :: Eq b => (a -> b) -> [a] -> ([a], [a])
splitOn f [] = ...
splitOn f (x:xs) = ...
For example,
> splitOn odd [1,3,3,4,5]
([1,3,3], [4,5])
Group each element in the list by what f returns:
groupOn :: Eq b => (a -> b) -> [a] -> [[a]]
groupOn f [] = ...
groupOn f xs = ...
For example,
> groupOn odd [1,3,3,4,5,6,8]
[[1,3,3],[4],[5],[6,8]]
You can do this by applying splitOn recursively. Think case-of.
Filter out sub-lists in which the first element satisfies f:
separate :: (a -> Bool) -> [a] -> [[a]]
separate f xs = filter (\ys -> ...) (groupOn f xs)
where ys would be [1,3,3], [4], [5] and [6,8] in the above example.

Why isn't the pattern in this code exhaustive?

splitWith :: (a -> Bool) -> [a] -> [[a]]
splitWith f [] = []
splitWith f list = pre : (splitWith f suf)
where (pre, suf) = break f list
This function should split a list according to a predicate. But I get an infinite recursion.
break is defined as:
break :: (a -> Bool) -> [a] -> ([a], [a])
break, applied to a predicate p and a list xs, returns a tuple
where first element is longest prefix (possibly empty) of xs of
elements that do not satisfy p and second element is the remainder
of the list:
break (> 3) [1,2,3,4,1,2,3,4] == ([1,2,3],[4,1,2,3,4])
break (< 9) [1,2,3] == ([],[1,2,3])
break (> 9) [1,2,3] == ([1,2,3],[])
So once you have done the first break, all the remaining breaks will simply split the list into an empty list and the original list. As a result, there is no progress in the pattern so to speak. Unless all the elements do not satisfy the predicate, you will keep iterating over a list where the first element satisifies the predicate, and never get rid of it.
What you probably want is to interleave the break with the span:
splitWith :: (a -> Bool) -> [a] -> [[a]]
splitWith f [] = []
splitWith f list = pre1 : pre2 : (splitWith f suf2)
where (pre1, suf1) = break f list
(pre2, suf2) = span f suf1
This will split the given list interleaved in a list of elements where the predicate is not satisfied, and a list where it is satisfied.
In case you do not want the latter, you can simply dropWhile these:
splitWith :: (a -> Bool) -> [a] -> [[a]]
splitWith f [] = []
splitWith f list = pre : (splitWith f $ dropWhile f suf)
where (pre1, suf) = break f list
It'd be because this will continually add an empty list to the end.
You can see this is if you take some arbitrary quantity of values from the infinite collection:
*Main> take 10 $ splitWith (==5) [1,2,3,4,5]
[[1,2,3,4],[],[],[],[],[],[],[],[],[]]
If you break (==5) [5], the result is ([],[5]) which gets pattern matched into pre as [] and suf as [5]. The next iteration gets the same break (==5) [5] to evaluate... and so it goes.
update:
I'm not sure of the exact semantics you're after, but this might be helpful in formulating the function you want:
splitWith :: (a -> Bool) -> [a] -> [[a]]
splitWith f [] = []
splitWith f xs = doSplitWith [] xs
where
doSplitWith first second # (y:ys) =
if f y
then (reverse first) : [second]
else doSplitWith (y:first) ys
splitWith' f xs = takeWhile (not . f) xs : [dropWhile (not . f) xs]
Tho I guess that'd be more like splitAt or something, wouldn't it?

Haskell: Print elements of a list

I have a list
let a = [1,2,3,4]
I want to extract 2 elements at a time to perform computation. Can anyone tell me how this can be achieved? I am new to Haskell.
I am aware of take 2 a. But how can I put this in a loop so that 2 elements are extracted at a time. I am confused.
Here's an example. You are (or should become) familiar with the map function:
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xs
Here, you might have a function that takes two arguments, and want to apply it to two elements from a list at a time. Here's a function mapTwo that behaves like map, but with a two-argument function. For simplicity, we'll assume the list has an even number of elements.
mapTwo :: (a -> a -> b) -> [a] -> [b]
mapTwo f [] = []
mapTwo f (x1:x2:xs) = f x1 x2 : mapTwo f xs
You can write your own recursive function and pattern-match on elements you are interested in:
f (a:b:list) = doSomeThingWith a b : f list
Make sure to properly match on [] and [a] cases.

Apply a function to every element in a list to every element in another list - Haskell

My ultimate goal is to find if a list y contains all the elements of list x (I'm checking if x is a subset of y sort of thing)
subset x y =
and [out | z <- x
, out <- filter (==z) y ]
This doesn't work, and I know it's because z is a list still. I'm trying to make sense of this.
I think I may have to use the elem function, but I'm not sure how to split x into chars that I can compare separately through y.
I'm ashamed to say that I've been working on this simple problem for an hour and a half.
Checking whether all elements of xs are elements of ys is very straightforward. Loop through xs, and for each element, check if it is in ys:
subset xs ys = all (\x -> elem x ys) xs
You could also use the list difference function (\\). If you have list y and list x, and you want to check that all elements of x are in y, then x \\ y will return a new list with the elements of x that are not in y. If all the elements of x are in y, the returned list will be empty.
For example, if your list y is [1,2,3,4,5] and your list x is [2,4], you can do:
Prelude> [2,4] \\ [1,2,3,4,5]
[]
If list y is [1,2,3,4,5] and list x is [2,4,6], then:
Prelude> [2,4,6] \\ [1,2,3,4,5]
[6]
Easy way to reason about subsets is to use sets as the data type.
import qualified Data.Set as S
subset :: Ord a => [a] -> [a] -> Bool
subset xs ys = S.isSubsetOf (S.fromList xs) (S.fromList ys)
Then it's as simple as:
*Main> subset [1..5] [1..10]
True
*Main> subset [0..5] [1..10]
False
Let's break this down into two subproblems:
Find if a value is a member of a list;
Use the solution to #1 to test whether every value in a list is in the second one.
For the first subproblem there is a library function already:
elem :: (Eq a, Foldable t) => a -> t a -> Bool
Lists are a Foldable type, so you can use this function with lists for t and it would have the following type:
elem :: (Eq a) => a -> [a] -> Bool
EXERCISE: Write your own version of elem, specialized to work with lists (don't worry about the Foldable stuff now).
So now, to tackle #2, one first step would be this:
-- For each element of `xs`, test whether it's an element of `ys`.
-- Return a list of the results.
notYetSubset :: Eq a => [a] -> [a] -> [Bool]
notYetSubset xs ys = map (\x -> elem x ys) xs
After that, we need to go from the list of individual boolean results to just one boolean. There's a standard library function that does that as well:
-- Return true if and only if every element of the argument collection is
-- is true.
and :: Foldable t => t Bool -> Bool
EXERCISE: write your own version of and, specialized to lists:
myAnd :: [Bool] -> Bool
myAnd [] = _fillMeIn
myAnd (x:xs) = _fillMeIn
With these tools, now we can write subset:
subset :: Eq a => [a] -> [a] -> [Bool]
subset xs ys = and (map (\x -> elem x ys) xs)
Although a more experienced Haskeller would probably write it like this:
subset :: Eq a => [a] -> [a] -> [Bool]
subset xs ys = every (`elem` ys) xs
{- This:
(`elem` ys)
...is a syntactic shortcut for this:
\x -> x elem ys
-}
...where every is another standard library function that is just a shortcut for the combination of map and and:
-- Apply a boolean test to every element of the list, and
-- return `True` if and only if the test succeeds for all elements.
every :: (a -> Bool) -> [a] -> Bool
every p = and . map p

Haskell list: Replacing elements given their locations in the list

I'm fairly new to Haskell and trying to figure out how I would write a Function to do this and after combing Google for a few hours I'm at a loss on how to do it.
Given the following two lists in Haskell
[(500,False),(400,False),(952,True),(5,False),(42,False)]
[0,2,3]
How would I change the Boolean of the First list at each location given by the second list to a Value of True for an Output of
[(500,True),(400,False),(952,True),(5,True),(42,False)]
This is how I would do it (assumes the list of indexes to replace is sorted).
First we add an index list alongside the list of indexes to replace and the original list.
Then we recurse down the list and when we hit the next index to replace we replace the boolean and recurse on the tail of both all three lists. If this is not an index to
replace we recurse on the entire replacement index list and the tail of the other two lists.
setTrue :: [Int] -> [(a, Bool)] -> [(a, Bool)]
setTrue is xs = go is xs [0..] -- "Index" the list with a list starting at 0.
where
go [] xs _ = xs -- If we're out of indexes to replace return remaining list.
go _ [] _ = [] -- If we run out of list return the empty list.
go indexes#(i:is) (x:xs) (cur:cs)
| i == cur = (fst x, True) : go is xs cs -- At the next index to replace.
| otherwise = x : go indexes xs cs -- Otherwise, keep the current element.
This is basically the same as Andrew's approach, but it doesn't use an additional index list, and is a little bit more inspired by the traditional map. Note that unlike map, the provided function must be a -> a and cannot be a -> b.
restrictedMap :: (a -> a) -> [Int] -> [a] -> [a]
restrictedMap f is xs = go f is xs 0
where
go f [] xs _ = xs
go f _ [] _ = []
go f ind#(i:is) (x:xs) n
| i == n = f x : go f is xs (n+1)
| otherwise = x : go f ind xs (n+1)
setTrue = restrictedMap (\(x,_) -> (x, True))
Straightforward translation from the description will be:
setIndexTrue f a = [(x, p || i `elem` f) | (i, (x,p)) <- zip [0..] a]
Or using the fantastic lens library:
setTrue :: [(a,Bool)] -> Int -> [(a,Bool)]
setTrue xs i = xs & ix i . _2 .~ True
setTrues :: [(a,Bool)] -> [Int] -> [(a,Bool)]
setTrues = foldl setTrue
Since the approach I would use is not listed:
setTrue spots values = let
pattern n = replicate n False ++ [True] ++ Repeat False
toSet = foldl1 (zipWith (||)) $ map pattern spots
in zipWith (\s (v,o) -> (v, o || s)) toSet values

Resources