Haskell: Print elements of a list - haskell

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.

Related

Map then filter in Haskell

I want to Map an Integer type list in Haskell, and then if the map function returns Nothing I want to discard the result. The function I am trying to write will have a type signature of
mapThenFilter :: (Integer -> Maybe Integer) -> [Integer] -> [Integer]
and so far, I have thought of doing this:
checkIfNothing value = case value of
Just a -> a
Nothing -> 0
mapThenFilter = map checkIfNothing(map f l)
But this is incorrect. I am new to Haskell, so if possible can you advise me on where I am going wrong here? I believe since this is Map then Filter, the Haskell filter function is probably expected to be used too, however, I believe the outer map function in my function definition is doing the job intended(of the filter function)right?
As stated in the comments you are reimplementing mapMaybe.
Which is good. It is a non-obvious function, and it is good that you feel the need for it and came up with that idea, expressed in its type.
If you'd like to do it your way, you were off to a good start actually. Need to tweak it though:
checkIfNothing value = case value of
Just a -> a
Nothing -> 0
0 is too specific, let's go with []. But now simply returning a won't work. Let's put it in a list, too:
checkIfNothing :: Maybe t -> [t]
checkIfNothing value = case value of
Just a -> [a]
Nothing -> []
So that now,
mapThenFilter f l = map checkIfNothing (map f l)
is almost right. We produce our results in lists, and those that were skipped result in empty lists:
-- instead of
[ a, b, c, .... , z ]
-- we produce
[ [], [b], [], .... , [z] ]
and so we just need to concatenate them, to join them together with ++s:
[]++[b]++[]++...,++[z]
[ b, ...., z ]
And so we define
mapThenFilter :: (a1 -> Maybe a) -> [a1] -> [a]
mapThenFilter f l = concat $ map checkIfNothing (map f l)
By the way checkIfNothing also already exists. It is known as maybeToList:
> foo f l = concat $ map maybeToList $ map f l
foo :: (a1 -> Maybe a) -> [a1] -> [a]
> foo (\x -> listToMaybe [x | even x]) [1..10]
[2,4,6,8,10]
A combination of concat and map is important enough to have a special function assigned to do its job, concatMap. And that function is important enough to even be assigned a special operator, to do its job:
foo f = concat . map maybeToList . map f
= concat . map (maybeToList . f)
= concatMap (maybeToList . f)
= (maybeToList . f =<<)

Nested Loop Formatting

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.

Using Haskell's foldr

I'm learning Haskell and I've been wrestling with this problem:
Write func :: (a -> Bool) -> [a] -> [a] (take elements of a list until the predicate is false) using foldr
This is what I have so far:
func :: (a -> Bool) -> [a] -> [a]
func f li = foldr f True li
and got the following errors:
Couldn't match expected type ‘[a]’ with actual type ‘Bool’
and
Couldn't match type ‘Bool’ with ‘Bool -> Bool’
Expected type: a -> Bool -> Bool
Actual type: a -> Bool
I'm a bit confused since I learned foldr by passing a function with two arguments and getting a single value. For example I've used the function by calling
foldr (\x -> \y -> x*y*5) 1 [1,2,3,4,5]
to get a single value but not sure how it works when passing a single argument function into foldr and getting a list in return. Thank you very much.
Let’s do an easier case first, and write a function that uses foldr to do nothing (to break down the list and make a the same list). Let’s look at the type signature of foldr:
foldr :: (a -> b -> b) -> b -> [a] -> [b]
And we want to write an expression of the form
foldr ?1 ?2 :: [a] -> [a]
Now this tells us that (in the signature of foldr) we can replace b with [a].
A thing we haven’t worked out, ?2, is what we replace the end of the list with and it has type b = [a]. We don’t really have anything of type a so let’s just try the most stupid thing we can:
foldr ?1 []
And now the next missing thing: we have ?1 :: a -> [a] -> [a]. Let’s write a function for this. Now there are two reasonable things we can do with a list of things and another thing and nothing else:
Add it to the start
Add it to the end
I think 1 is more reasonable so let’s try that:
myFunc = foldr (\x xs -> x : xs) []
And now we can try it out:
> myFunc [1,2,3,4]
[1,2,3,4]
So what is the intuition for foldr here? Well one way to think of it is that the function passed gets put into your list instead of :, with the other item replacing [] so we get
foldr f x [1,2,3,4]
——>
foldr f x (1:(2:(3:(4:[]))))
——>
f 1 (f 2 (f 3 (f 4 x)))
So how can we do what we want (essentially implement takeWhile with foldr) by choosing our function carefully? Well there are two cases:
The predicate is true on the item being considered
The predicate is false for the item being considered
In case 1 we need to include our item in the list, and so we can try doing things like we did with our identity function above.
In case 2, we want to not include the item, and not include anything after it, so we can just return [].
Suppose our function does the right thing for the predicate "less than 3", here is how we might evaluate it:
f 1 (f 2 (f 3 (f 4 x)))
--T T F F (Result of predicate)
-- what f should become:
1 : (2 : ([] ))
——>
[1,2]
So all we need to do is implement f. Suppose the predicate is called p. Then:
f x xs = if p x then x : xs else []
And now we can write
func p = foldr f [] where
f x xs = if p x then x : xs else []

Get first item matching a criteria using foldr

I am giving my self exercises and wondering if there is a way to find the first item from left in the list matching a certain criteria using just foldr? I want the recursion to stop when the first item is found (I know I could probably combine using take) but I am curious to know if it is possible to do just using foldr?
firstFind (\x -> x > 1000) [] xs
The problem: find f and b.
firstFind :: (a -> Bool) -> [a] -> Maybe a
firstFind p list = foldr f b list
where f = ???
b = ???
We want:
firstFind p [] = Nothing
but we also have
firstFind p []
= def. firstFind
foldr f b []
= def. foldr
b
from which we see what b must be.
Further, take list = x:xs
firstFind p list
= def. firstFind
foldr f b (x:xs)
= def. foldr
f x (foldr f b xs)
= def. firstFind
f x (firstFind p xs)
Now, we just need to find f so that this chooses the first match.
Recall that f can depend on p. What should f return when p x is true? What in the opposite case?
where -- f :: a -> Maybe a -> Maybe a
f x y = ???
(Note: above I wrote the type signature for f for clarity, but you don't have to include it in your code. If you add it, uncommented, you will trip into a type variable confusion: that a is not the same a as in findFirst because it is generalized locally -- since you are just beginning, ignore this and simply remove it for the moment being.)

Explicit recursion in Haskell

The task: I'm attempting to write a function with type signature minimum_recursive :: (a -> a -> Bool) -> [a] -> a . For its first parameter, it accepts a function I will call less that takes two parameters, and returns True if the first param is less than the second, False otherwise. minimum_recursive also accepts a list as its second parameter. Using explicit recursion, minimum_recursive should determine the smallest value in its input list [a].
My thinking: I was thinking to put the actual recursion in a helper function that also accepts an accumulator. I would call the helper function with the first item as the accumulator.
What I have so far: So far I have the following:
-- function as first parameter to min'
-- accepts two params, returns True if
-- first must come before second in sorted
-- order
less :: Ord a => a -> a -> Bool
less a b = a < b
-- Subpart B
minimum_recursive :: (a -> a -> Bool) -> [a] -> a
minimum_recursive func list = minimum_recursive_h func list []
I am having trouble figuring out how to even begin to write minimum_recursive_h.
Note: I know there probably is an easier way to accomplish this task, but I'm required to go about it as specified above.
You could do it like this:
minimum_recursive _ [] = error "no minimum of empty list"
minimum_recursive _ [x] = x
minimum_recursive f (x:xs) = let m = minimum_recursive f xs
in if f x m then x else m
Or, with an accumulator:
minimum_recursive _ [] = error "no minimum of empty list"
minimum_recursive f (x:xs) = helper f x xs
where
helper _ m [] = m
helper f m (x:xs)
| f m x = helper f m xs
| otherwise = helper f x xs
If you want the smallest ellement in the list I sugest that you add the smallest ellement you currently have as a parameter to the function.
minimum_recursive :: (a -> a -> Bool) -> a -> [a] -> a
minimum_recursive f min [] = min
minimum_recursive f min (x:xs) | f min x = minimum_recursive f min xs
| otherwise = minimum_recursive f x xs
You should also change the type in the function that call this from a to Maybe a since there are no smallest ellement in an empty list. Here some help about Maybe
If you want to do it without an extra parameter you could store the smallest ellement in the beginning of the list ass well. In this case it's important to use Maybe
minimum_recursive :: (a -> a -> Bool) -> [a] ->Maybe a
minimum_recursive f [] = Nothing
minimum_recursive f (x:[]) = Just x
minimum_recursive f (y:(x:xs)) | f y x = minimum_recursive f (y:xs)
| otherwise = minimum_recursive f (x:xs)
This is how the minumum can be found ehit fold. Look at the beauty of functionall programming. But this wont work for the empty list
simplefold :: [a] -> a
simplefold (x:xs) = foldl min x xs
But we can embed this function in one that checks if the list is empty and return Nothing in that case.
betterfold :: [a] -> Maybe a
betterfold [] = Nothing
beterfold l = Just (simplefold l)
The classic way to solve problems recursively is the following:
Assume you've nearly solved the problem, except for the final step.
Write the code that, given the solution for all except that final step, computes the solution produced by that final step.
Write the base case.
In the case of lists, this translates to this pattern:
Base case: what should the solution be for []? (if anything; in the case of your minimum_recursive function, this would be an error).
For a nonempty list x:xs, assume you already have almostTheResult = minimum_recursive f xs. How do you compute minimum_recursive (x:xs) given that?
I'll give you a big hint: your minimum_recursive can be implemented in terms of foldr and this function:
minBy :: (a -> a -> Bool) -> a -> a -> a
minBy pred x y = if pred x y then x else y
The foldr function does exactly what I'm describing above. The first argument to foldr is the function that computes the final solution given the list head and the partial solution for the tail, and the second argument is the result base case.

Resources