How I make result a list of booleans - haskell

I have this:
getMask (/= 3) [1, 2, 3, 4, 5]
and result must be this:
[True, True, False, True, True]
i tried something like this
getMask p xs = [x | (x,m) <- enumerate xs, if p x then True else False]
but i get only numbers. I need list of booleans

You can use map :: (a -> b) -> [a] -> [b]:
> map (/= 3) [1, 2, 3, 4, 5]
[True,True,False,True,True]
or a simple list comprehension:
getMask p xs = [p x | x <- xs]

Related

Return a list, which contains a pair of elements, but only if the respective elements' sums are odd

Implement the oddPairs :: [Int] -> [Int] -> [(Int, Int)] function that returns a list of pairs, but only if the parameters' lists' respective elements' sums are odd.
For example:
oddPairs [1,2,3] [2,2,2] == [(1,2),(3,2)]
oddPairs [1,3,5] [2,4,6] == zip [1,3,5] [2,4,6]
oddPairs [1,2,3] [1,2,3] == []
So far, I've tried
oddPairs (x:xs) (y:ys) | (x+y) `mod` 2 == 0 = []
| (x+y) `mod` 2 /= 0 = [(x, y)] ++ oddPairs (xs) (ys)
And on the first example, it returns only [(1,2)], on the second, it returns the correct values but with a Non-exhaustive patterns error.
In case the two items are even, you should not just return an empty list, but continue the recursion until at least one of the lists is exhausted, so:
oddPairs :: Integral a => [a] -> [a] -> [(a, a)]
oddPairs [] _ = []
oddPairs _ [] = []
oddPairs (x:xs) (y:ys)
-- keep searching for new items &downarrow;
| (x+y) `mod` 2 == 0 = oddPairs xs ys
| otherwise = (x, y) : oddPairs xs ys
Another way to look at the problem is that you want only the pairs that have an odd sum. This is a slight difference in emphasis that might lead to the following.
Use the zip function to combine each list into pairs. Then use filter to find the ones with odd sum.
oddPairs :: Integral a => [a] -> [a] -> [(a, a)]
oddPairs f s = filter oddPair (zip f s)
where oddPair (l, r) = not $ even (l + r)
Quite straightforwardly with a list comprehension:
oddPairs :: [Int] -> [Int] -> [(Int, Int)]
oddPairs ms ns = [(m, n) | (m, n) <- zip ms ns, odd (m + n)]
Indeed:
> oddPairs [1, 2, 3] [2, 2, 2] == [(1, 2),(3, 2)]
True
> oddPairs [1, 3, 5] [2, 4, 6] == zip [1, 3, 5] [2, 4, 6]
True
> oddPairs [1, 2, 3] [1, 2, 3] == []
True

Haskell equivalent of Ruby's slice_when

I am new to Haskell, and I want a function works like Ruby's slice_when:
slice_when
Ruby
a = [1,2,4,9,10,11,12,15,16,19,20,21]
b = a.slice_when {|i, j| i+1 != j }
p b.to_a #=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]]
Haskell
ghci > slice_when (\x y -> x+1 /= y) [1,2,4,9,10,11,12,15,16,19,20,21]
=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]]
Thank you very much.
Here’s a sliceWhen implementation that I believe works like you want:
sliceWhen :: (a -> a -> Bool) -> [a] -> [[a]]
sliceWhen _ [] = []
sliceWhen _ [x] = [[x]]
sliceWhen f (x:y:xs)
| f x y = [x] : sliceWhen f (y:xs)
| otherwise = let z:zs = sliceWhen f (y:xs)
in (x:z) : zs
The above function runs the provided predicate on each boundary, and if it returns True, it creates a seam. Otherwise, it tacks the “current” value onto the first element of the rest of the list.
Without explicit recursion, and using NonEmpty:
import Data.List.NonEmpty
sliceWhen :: (a -> a -> Bool) -> [a] -> [NonEmpty a]
sliceWhen p = foldr f []
where
f z [] = [z :| []]
f z gss#(gs#(x :| xs) : xss) = if p z x
then (z :| []) : gss
else cons z gs : xss

A simple version of Haskell's map

I'm trying to define map in ghci recursively. What I've come up with so far is the following:
let mymap f (x:xs) = if null xs then [] else f x : map f xs
What I'd like to do now is to simplify it a bit and hardcode the list inside the code, i.e., write a map function which takes a function as argument and does what the real map does but only to a specific list e.g., [1, 2, 3, 4, 5].
Is such a thing possible?
First of all, your map function isn't entirely correct. If I were to input mymap (+1) [1], I would expect to get [2] back, but instead I'd get []. If I tried mymap (+1) [], my program would crash on a pattern match failure, since you haven't defined that case. Instead, consider defining your mymap as
mymap :: (a -> b) -> [a] -> [b]
mymap f [] = []
mymap f (x:xs) = f x : mymap f xs
If you want to do it inline with an if statement then you'd have to do
mymap f xs = if null xs then [] else f (head xs) : mymap f (tail xs)
These do essentially the same thing, but the first is a bit easier to read in my opinion.
If you want to use mymap to define a function that maps only over a specific list, you could do so pretty easily as
mapOnMyList :: (Int -> b) -> [b]
mapOnMyList f = mymap f [1, 2, 3, 4, 5]
Or in point-free form
mapOnMyList = (`mymap` [1, 2, 3, 4, 5])
using mymap as an infix operator. This is equivalent to flip mymap [1, 2, 3, 4, 5], but the operator form is usually preferred since flip is not necessarily free to execute.
You can also do this using list comprehensions:
mymap f xs = [f x | x <- xs]
Or if you want to hard code the list
mapOnMyList f = [f x | x <- [1, 2, 3, 4, 5]]

Nested loop equivalent

I want to do a list of concatenations in Haskell.
I have [1,2,3] and [4,5,6]
and i want to produce [14,15,16,24,25,26,34,35,36].
I know I can use zipWith or sth, but how to do equivalent of:
foreach in first_array
foreach in second_array
I guess I have to use map and half curried functions, but can't really make it alone :S
You could use list comprehension to do it:
[x * 10 + y | x <- [1..3], y <- [4..6]]
In fact this is a direct translation of a nested loop, since the first one is the outer / slower index, and the second one is the faster / inner index.
You can exploit the fact that lists are monads and use the do notation:
do
a <- [1, 2, 3]
b <- [4, 5, 6]
return $ a * 10 + b
You can also exploit the fact that lists are applicative functors (assuming you have Control.Applicative imported):
(+) <$> (*10) <$> [1,2,3] <*> [4,5,6]
Both result in the following:
[14,15,16,24,25,26,34,35,36]
If you really like seeing for in your code you can also do something like this:
for :: [a] -> (a -> b) -> [b]
for = flip map
nested :: [Integer]
nested = concat nested_list
where nested_list =
for [1, 2, 3] (\i ->
for [4, 5, 6] (\j ->
i * 10 + j
)
)
You could also look into for and Identity for a more idiomatic approach.
Nested loops correspond to nested uses of map or similar functions. First approximation:
notThereYet :: [[Integer]]
notThereYet = map (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3]
That gives you nested lists, which you can eliminate in two ways. One is to use the concat :: [[a]] -> [a] function:
solution1 :: [Integer]
solution1 = concat (map (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3])
Another is to use this built-in function:
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f xs = concat (map f xs)
Using that:
solution2 :: [Integer]
solution2 = concatMap (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3]
Other people have mentioned list comprehensions and the list monad, but those really bottom down to nested uses of concatMap.
Because do notation and the list comprehension have been said already. The only other option I know is via the liftM2 combinator from Control.Monad. Which is the exact same thing as the previous two.
liftM2 (\a b -> a * 10 + b) [1..3] [4..6]
The general solution of the concatenation of two lists of integers is this:
concatInt [] xs = xs
concatInt xs [] = xs
concatInt xs ys = [join x y | x <- xs , y <- ys ]
where
join x y = firstPart + secondPart
where
firstPart = x * 10 ^ lengthSecondPart
lengthSecondPart = 1 + (truncate $ logBase 10 (fromIntegral y))
secondPart = y
Example: concatInt [1,2,3] [4,5,6] == [14,15,16,24,25,26,34,35,36]
More complex example:
concatInt [0,2,10,1,100,200] [24,2,999,44,3] == [24,2,999,44,3,224,22,2999,244,23,1024,102,10999,1044,103,124,12,1999,144,13,10024,1002,100999,10044,1003,20024,2002,200999,20044,2003]

Understanding the functions elem and isInfixOf

A while ago I've asked a question about the function elem here, but I don't think the answer is fully satisfactory. My question is about the expression:
any (`elem` [1, 2]) [1, 2, 3]
We know elem is in a backtick so elem is an infix and my explanation is:
1 `elem` [1, 2] -- True
2 `elem` [1, 2] -- True
3 `elem` [1, 2] -- False
Finally it will return True since it's any rather than all. This looked good until I see a similar expression for isInfixOf:
any (isInfixOf [1, 2, 3]) [[1, 2, 3, 4], [1, 2]]
In this case a plausible explanation seems to be:
isInfixOf [1, 2, 3] [1, 2, 3, 4] -- True
isInfixOf [1, 2, 3] [1, 2] -- False
I wonder why they've been used in such different ways since
any (elem [1, 2]) [1, 2, 3]
will give an error and so will
any (`isInfixOf` [[1, 2, 3, 4], [1, 2]]) [1, 2, 3]
Your problem is with the (** a) syntactic sugar. The thing is that (elem b) is just the partial application of elem, that is:
(elem b) == (\xs -> elem b xs)
However when we use back ticks to make elem infix, we get a special syntax for infix operators which works like this:
(+ a) == (\ b -> b + a)
(a +) == (\ b -> a + b)
So therefore,
(`elem` xs) == (\a -> a `elem` xs) == (\ a -> elem a xs)
while
(elem xs) == (\a -> elem xs a)
So in the latter case your arguments are in the wrong order, and that is what is happening in your code.
Note that the (** a) syntactic sugar works for all infix operators except - since it is also a prefix operator. This exception from the rule is discussed here and here.
Using back-ticks around a function name turns it into an infix operator. So
x `fun` y
is the same as
fun x y
Haskell also has operator sections, f.e. (+ 1) means \x -> x + 1.
So
(`elem` xs)
is the same as
\x -> x `elem` xs
or
\x -> elem x xs
or
flip elem xs
It's called partial application.
isInfixOf [1, 2, 3] returns a function that expects one parameter.
any (elem [1, 2]) [1, 2, 3] is an error because you're looking for an element [1, 2], and the list only contains numbers, so haskell cannot match the types.

Resources