Haskell - using Until on a list - haskell

I've been trying to do a function that creates a list of n numbers ([1...n]) using an until. So far I haven't found any examples of until manipulating lists and I've been improvising:
sequence Int -> [Int]
sequence x = until (== x) (++ [ +1 ]) [1]
But keep getting the Syntax error in expression (unexpected token) error
I know I could simply use a [1..n] to create the list, but I really want to make this work out. Thanks in advance for any help.

Take note of the type of until:
until :: (a -> Bool) -> (a -> a) -> a -> a
For your case, a is [Int], so everything has to take a list as input and return a list.
sequence x = until (\y -> last y == x) (\y -> y ++ [last y + 1]) [1]
The predicate takes a list and checks if its last element is equal to x.
The modifier takes a list and adds a new element to the end, with that new element being one greater than the last element of the list.
This is not very efficient, as you are continually working with the wrong end of the list. You can make it a little more efficient by building the list backwards, then reversing it at the end. (Since we are guaranteed to be using non-empty lists, I use head in place of pattern matching for simplicity.)
sequence x = reverse $ until ((== x) . head) (\y -> (head y + 1) : y) [1]
or build the list down from x to 1:
sequence x = until ((==1) . head) (\y -> head y-1 : y) [x]

Related

Rendering values into items and intermediate items in Haskell

While doing user interface programming I often encounter the need to render a list of values and add some related information between the rendered values. In the following code example I'm rendering numerical values into strings where they appear in parenthesis and render the distance of two values into a string that gets placed between the renders of the values. The code works but I'm wondering if an implementation of the mystery function is available as part of the Haskell standard library. I'm also interested in names used for this function in other libraries, as using human readable words makes googling easier.
mystery :: (a -> b) -> (a -> a -> b) -> [a] -> [b]
mystery n d [] = []
mystery n d [x] = [n x]
mystery n d (x:xs) = (n x) : (d x (head xs)) : mystery n d xs
node x = "(" ++ show x ++ ")"
distance x y = "-" ++ (show $ abs $ x - y) ++ "-"
render xs = concat $ mystery node distance xs
-- render [25, 68, 54, 15] == "(25)-43-(68)-14-(54)-39-(15)"
Your mystery function is actually doing a couple things at once, and if you separate out the behaviors, it may be a little easier to see what's going on.
First, you're mapping n on all the elements. We can write that as fmap n xs. Next, you're constructing new elements d x y for all pairs of adjacent elements x and y. We can write that as zipWith d xs (tail xs).
The last step is taking these two constructions and making a new list with elements that alternate back and forth between them. Interestingly, this was a question asked 9 years ago, but still doesn't have a super satisfying answer. Probably the simplest answer is to define your own function:
alternate [] ys = ys
alternate (x:xs) ys = x : alternate ys xs
Then, we can define mystery as a one-liner:
mystery n d x = alternate (fmap n x) (zipWith d x (tail x))
If you really want it to be a one-liner, the best I could come up with was using concat and transpose in a bit of a funky way:
mystery n d x = concat $ transpose $ (pure $ fmap n x) <> (pure $ zipWith d x (tail x))
Basically, we're making singleton lists out of the two components using pure, fusing them together with <>, then transposeing this "list of lists" to get the elements properly interspersed, and concating the result.

Haskell naive duplicate filtering

I do not understand a sample solution for the following problem: given a list of elements, remove the duplicates. Then count the unique digits of a number. No explicit recursion may be used for either problem.
My code:
removeDuplicates :: Eq a => [a] -> [a]
removeDuplicates = foldr (\x ys -> x:(filter (x /=) ys)) []
differentDigits :: Int -> Int
differentDigits xs = length (removeDuplicates (show xs))
The solution I am trying to understand has a different definition for differentDigits, namely
differentDigits xs = foldr (\ _ x -> x + 1) 0 ( removeDuplicates ( filter (/= '_') ( show xs )))
Both approaches work, but I cannot grasp the sample solution. To break my question down into subquestions,
How does the first argument to filter work? I mean
(/= '_')
How does the lambda for foldr work? In
foldr (\ _ x -> x + 1)
^
the variable x should still be the Char list? How does Haskell figure out that actually 0 should be incremented?
filter (/= '_') is, I'm pretty sure, redundant. It filters out underscore characters, which shouldn't be present in the result of show xs, assuming xs is a number of some sort.
foldr (\ _ x -> x + 1) 0 is equivalent to length. The way foldr works, it takes the second argument (which in your example is zero) as the starting point, then applies the first argument (in your example, lambda) to it over and over for every element of the input list. The element of the input list is passed into the lambda as first argument (denoted _ in your example), and the running sum is passed as second argument (denoted x). Since the lambda just returns a "plus one" number on every pass, the result will be a number representing how many times the lambda was called - which is the length of the list.
First, note that (2) is written in so called point free style, leaving out the third argument of foldr.
https://en.wikipedia.org/wiki/Tacit_programming#Functional_programming
Also, the underscore in \_ x -> x + 1 is a wild card, that simply marks the place of a parameter but that does not give it a name (a wild card works as a nameless parameter).
Second, (2) is a really nothing else than a simple recursive function that folds to the right. foldr is a compact way to write such recursive functions (in your case length):
foldr :: (a -> b -> b) -> b -> [a]
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
If we write
foldr f c ls
ls is the list over which our recursive function should recur (a is the type of the elements).
c is the result in the base case (when the recursive recursive function is applied on an empty list).
f computes the result in the general case (when the recursive function is applied on a non-empty list). f takes two arguments:
The head of the list and
the result of the recursive call on the tail of the list.
So, given f and c, foldr will go through the list ls recursively.
A first example
The Wikipedia page about point free style gives the example of how we can compute the sum of all elements in a list using foldr:
Instead of writing
sum [] = 0
sum (x:xs) = x + sum xs
we can write
sum = foldr (+) 0
The operator section (+) is a 2-argument function that adds its arguments. The expression
sum [1,2,3,4]
is computed as
1 + (2 + (3 + (4)))
(hence "folding to the right").
Example: Multiplying all elements.
Instead of
prod [] = 1
prod (x:xs) = x * prod xs
we can write
prod = foldr (*) 1
Example: Remove all occurrences of a value from a list.
Instead of
remove _ [] = []
remove v (x:xs) = if x==v then remove v xs else x:remove v xs
we can write
remove v = foldr (\x r -> if x==v then r else x:r) []
Your case, (2)
We can now fully understand that
length = foldr (\ _ x -> x + 1) 0
in fact is the same as
length [] = 0
length (x:xs) = length xs + 1
that is, the length function.
Hope this recursive view on foldr helped you understand the code.

Map and Filter, Haskell

Hi I was wondering how to use the map and filter function in haskell to get the amount of a number in the list, That was confusing sorry here's an example.
let a = [[1,2,1,2,1,1,1],[1,2],[3,4],[3,2]]
And I want use map to find out how many 1s are in each sub-list so the outcome would be
[5,1,0,0]
Any idea how to do it, I'm guessing its easy and im just missing something, cheers, my approach is
let ones = map(\x length (filter (\z -> z == 1)x) )a
but this is getting errors
First get the filter function:
((==) 1)
This will filter all other elements than 1 from a list:
filter ((==) 1)
Then combine it with the length function through function composition:
(length . filter ((==) 1))
Finally, map the array of lists with that function and you're done!
map (length . filter ((==) 1))
Break the problem into small steps.
Step 1. Count the number of 1s in a list. Make a function count1s :: [Int] -> Int using length and filter.
Step 2. Use map to apply count1s to each list in the outer list.
You wrote:
let ones = map(\x length (filter (\z -> z == 1)x) )a
Very good attempt, and almost correct! Let's paste it into GHCi, it spouts back:
<interactive>:9:35: Parse error in pattern: \ z -> z == 1
So what does this mean? This means that it thinks it's looking at a pattern and that it's failed to read it (parsing its text). If we just look at that thing, it's not a pattern! Why does it think it's looking at a pattern?
Because of the earlier \x which was not followed by a ->. In the arguments of a function literal, you're allowed to pattern-match! You can write \(y:_) x -> y + x and that will be the same as (+) . head, taking the head of one list and adding it to the second number provided.
Inserting it we get:
let ones = map(\x -> length (filter (\z -> z == 1)x) )a
Which gives a further error:
<interactive>:10:55: Not in scope: ‘a’
This is because I forgot to explicitly define a, so it's easy to fix:
let ones a = map(\x -> length (filter (\z -> z == 1)x) )a
Compiles, and then:
Prelude> ones [[1,2,1,2,1,1,1],[1,2],[3,4],[3,2]]
[5,1,0,0]
as desired. But we're not done yet, let's simplify!
First off there is \z -> z == 1 which is easier written using operator sections as (1 ==). I would recommend always putting in that space so that it looks a little extra "incomplete".
Then \x -> length (filter (1 ==) x) is a little wordy too, we can instead use the function composition operator . to write this as length . filter (1 ==). If you get confused about precedence here, remember that parentheses always happen first, then functions, then operators... so this is (.) length (filter (1 ==)) if you really wrote it out.
Once you have that, give it a name and a type signature in a source file!
countOnes :: (Eq a, Num a) => [a] -> Int
countOnes = length . filter (1 ==)
Then I would write map countOnes wherever you're actually using this code.

Does Haskell have a takeUntil function?

Currently I am using
takeWhile (\x -> x /= 1 && x /= 89) l
to get the elements from a list up to either a 1 or 89. However, the result doesn't include these sentinel values. Does Haskell have a standard function that provides this variation on takeWhile that includes the sentinel in the result? My searches with Hoogle have been unfruitful so far.
Since you were asking about standard functions, no. But also there isn't a package containing a takeWhileInclusive, but that's really simple:
takeWhileInclusive :: (a -> Bool) -> [a] -> [a]
takeWhileInclusive _ [] = []
takeWhileInclusive p (x:xs) = x : if p x then takeWhileInclusive p xs
else []
The only thing you need to do is to take the value regardless whether the predicate returns True and only use the predicate as a continuation factor:
*Main> takeWhileInclusive (\x -> x /= 20) [10..]
[10,11,12,13,14,15,16,17,18,19,20]
Is span what you want?
matching, rest = span (\x -> x /= 1 && x /= 89) l
then look at the head of rest.
The shortest way I found to achieve that is using span and adding a function before it that takes the result of span and merges the first element of the resulting tuple with the head of the second element of the resulting tuple.
The whole expression would look something like this:
(\(f,s) -> f ++ [head s]) $ span (\x -> x /= 1 && x /= 89) [82..140]
The result of this expression is
[82,83,84,85,86,87,88,89]
The first element of the tuple returned by span is the list that takeWhile would return for those parameters, and the second element is the list with the remaining values, so we just add the head from the second list to our first list.

How do I split a list into sublists at certain points?

How do I manually split [1,2,4,5,6,7] into [[1],[2],[3],[4],[5],[6],[7]]? Manually means without using break.
Then, how do I split a list into sublists according to a predicate? Like so
f even [[1],[2],[3],[4],[5],[6],[7]] == [[1],[2,3],[4,5],[6,7]]
PS: this is not homework, and I've tried for hours to figure it out on my own.
To answer your first question, this is rather an element-wise transformation than a split. The appropriate function to do this is
map :: (a -> b) -> [a] -> [b]
Now, you need a function (a -> b) where b is [a], as you want to transform an element into a singleton list containing the same type. Here it is:
mkList :: a -> [a]
mkList a = [a]
so
map mkList [1,2,3,4,5,6,7] == [[1],[2],...]
As for your second question: If you are not allowed (homework?) to use break, are you then allowed to use takeWhile and dropWhile which form both halves of the result of break.
Anyway, for a solution without them ("manually"), just use simple recursion with an accumulator:
f p [] = []
f p (x:xs) = go [x] xs
where go acc [] = [acc]
go acc (y:ys) | p y = acc : go [y] ys
| otherwise = go (acc++[y]) ys
This will traverse your entire list tail recursively, always remembering what the current sublist is, and when you reach an element where p applies, outputting the current sublist and starting a new one.
Note that go first receives [x] instead of [] to provide for the case where the first element already satisfies p x and we don't want an empty first sublist to be output.
Also, this operates on the original list ([1..7]) instead of [[1],[2]...]. But you can use it on the transformed one as well:
> map concat $ f (odd . head) [[1],[2],[3],[4],[5],[6],[7]]
[[1,2],[3,4],[5,6],[7]]
For the first, you can use a list comprehension:
>>> [[x] | x <- [1,2,3,4,5,6]]
[[1], [2], [3], [4], [5], [6]]
For the second problem, you can use the Data.List.Split module provided by the split package:
import Data.List.Split
f :: (a -> Bool) -> [[a]] -> [[a]]
f predicate = split (keepDelimsL $ whenElt predicate) . concat
This first concats the list, because the functions from split work on lists and not list of lists. The resulting single list is the split again using functions from the split package.
First:
map (: [])
Second:
f p xs =
let rs = foldr (\[x] ~(a:r) -> if (p x) then ([]:(x:a):r) else ((x:a):r))
[[]] xs
in case rs of ([]:r) -> r ; _ -> rs
foldr's operation is easy enough to visualize:
foldr g z [a,b,c, ...,x] = g a (g b (g c (.... (g x z) ....)))
So when writing the combining function, it is expecting two arguments, 1st of which is "current element" of a list, and 2nd is "result of processing the rest". Here,
g [x] ~(a:r) | p x = ([]:(x:a):r)
| otherwise = ((x:a):r)
So visualizing it working from the right, it just adds into the most recent sublist, and opens up a new sublist if it must. But since lists are actually accessed from the left, we keep it lazy with the lazy pattern, ~(a:r). Now it works even on infinite lists:
Prelude> take 9 $ f odd $ map (:[]) [1..]
[[1,2],[3,4],[5,6],[7,8],[9,10],[11,12],[13,14],[15,16],[17,18]]
The pattern for the 1st argument reflects the peculiar structure of your expected input lists.

Resources