Function in a function testing prog - haskell

I have a question about a selecting process.
I want to make a program where you type in a operation, a value and a list.
For example: programName (>) 4 [1,2,4,2,5], and it should return: [1,2,3].
I know how to make a program that make the function take takes whats equal in a list and make a new list like this:
programEqual :: Eq a => a -> [a] -> [a]
programEqual e [] = []
programEqual e (x:xs) = if (e == x) then e : takeEqual e xs else takeEqual e xs
I also understand that that you need two functions for this, but I can't understand how I should get the (tester) stuff in there.

You can adapt your previous program by adding a function argument. Here's a hint:
programEqual :: (a -> a -> Bool) -> a -> [a] -> [a]
programEqual f e [] = []
programEqual f e (x:xs) = if ....

If you want to implement that the easiest way possible
Just use filter:
filter :: (a -> Bool) -> [a] -> [a]
filter (< 4) [1, 2, 4, 2, 5] == [1, 2, 2]
If you want to pass the operator and the operand separately:
filter' op x = filter (op x)
and then
filter' (<) 4 [1,2,4,2,5] == [1,2,2]
If you want to tinker
There's a very useful function defined in Data.List:
takeWhile :: (a -> Bool) -> [a] -> [a]
Its signature should be rather helpful for you.
Here's a hint:
(>) :: Int -> Int -> Bool -- simplified from Eq a => ..
(> 4) :: Int -> Bool

Related

How can I change the (x, y) pair with a generic relation between them?

I am new to Haskell. I want to create a generic function to check if every 2 consecutive elements in a list are in a relation given by the user as input (eg: <, >, ==)
ordonata :: [a] -> (a -> a -> Bool) -> Bool
ordonata [] f = True
ordonata list f = and (map (\(x, y) -> f x y ) (zip list (tail(list))))
The program compiles, but when I try the input "ordonata[1, 2, 3, 4] < " I get this error:
"parse error (possibly incorrect indentation or mismatched brackets)"
Your implementation is correct!
When passing operators like > as a function Haskell requires brackets around the operator: (>).
You can use your function like this:
ordonata [1, 2, 3, 4] (<)
Looks like you're getting the hang of things!
A few notes on style; firstly, most Haskell developers would swap the argument order of the function to:
ordonata :: (a -> a -> Bool) -> [a] -> Bool
because it's more amenable to currying; with this version we can easily define partially applied functions:
ascending = ordanata (<)
descending = ordanata (>)
allEq = ordanata (==)
Also you might want to check out zipWith; we can use it to clean things up a little:
ordonata :: [a] -> (a -> a -> Bool) -> Bool
ordonata [] f = True
ordonata list f = and (zipWith f list (tail list))

Haskell concat / filter according specific rules

According to following rules, I tried to solve the following problem:
No definition of recursion
No List of Comprehension
Only Prelude-Module is allowed.
Now I have to implement higher-order for concat and filter.
Im at this point:
concat' :: [[a]] -> [a]
concat' a = (concat a)
filter' :: (a -> Bool) -> [a] -> [a]
filter' p [] = []
filter' p (x:xs)
| p x = x : filter p xs
| otherwise = filter p xs
The concat function is working (nothing special so far) -> Is that a defined recursion? I mean I use the predefined concat from standard-prelude but myself I don't define it - or am I wrong?
For the filter, the function I've looked up the definition of standard prelude but that's either not working and it contains a definition of recursion.
I'm supposing the concat and filter functions should be avoided. Why would we need to implement concat and filter if they're already available? So try implementing them from scratch.
We can use folding instead of recursion and list comprehensions. The below solutions use the function foldr.
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
concat' :: [[a]] -> [a]
concat' = foldr (++) []
filter' :: (a -> Bool) -> [a] -> [a]
filter' p = foldr (\x acc -> if p x then x:acc else acc) []
Examples:
main = do
print $ concat' ["A", "B", "CAB"] -- "ABCAB"
print $ filter' (\x -> x `mod` 2 == 0) [1..9] -- [2, 4, 6, 8]
You may do as follows;
concat' :: Monad m => m (m b) -> m b
concat' = (id =<<)
filter' p = ((\x-> if p x then [x] else []) =<<)
=<< is just flipped version of the monadic bind operator >>=.
filter' (< 10) [1,2,3,10,11,12]
[1,2,3]

Basic encryption using higher order functions in Haskell

I'm working on a problem that runs along the lines of basic encryption. I'm trying to create a function called encryptf that
takes a list xs of a's
takes a list ys of a's
returns a function that maps elements of xs to the corresponding elements of ys and maps everything else to itself.
So far it looks like this:
encryptf :: Eq a => [a] -> [a] -> (a -> a)
encryptf xs ys = \f -> head [d | (c,d) <- (zip xs ys)]
Then there's a second function called encryptString that looks like this:
encryptString :: (a -> a) -> [a] -> [a]
encryptString f xs = map f xs
and these functions will be used like this:
encryptString (encryptf "abc" "xyz") "dcba"
and that would return "dzyx"
Now I know that my encryptf function is wrong, because it would change everything to the first element of ys. I'm not sure where to go from here. Any help would be appreciated.
The idea is you search the given character in zipped list, and if it there then return second pair and if not then return the character itself.
encryptf :: Eq a => [a] -> [a] -> (a -> a)
encryptf xs ys =
let ret = zip xs ys in
\f ->
case lookup f ret of
Just c -> c
Nothing -> f
encryptString :: (a -> a) -> [a] -> [a]
encryptString f xs = map f xs
*Main> encryptString (encryptf "abc" "xyz") "dcba"
"dzyx"

Lambdas and Folds (Left and Right)

I really don't understand code
myReverse'' :: [a] -> [a]
myReverse'' xs = foldr (\x fId empty -> fId (x : empty)) id xs []
In case:
empty mapping to [] <---- accumulator
id mapping to fID (func id)
x is first element of xs (list)
Can i sort/change the postion of agruments "id xs []" ?
myReverse'' xs = foldr (\x fId empty -> fId (x : empty)) xs id []
I have read a book yesterday http://learnyouahaskell.com/higher-order-functions#lambdas
elem' :: (Eq a) => a -> [a] -> Bool
elem' y ys = foldl (\acc x -> if x == y then True else acc) False ys
The explanation is understandable to me.
the left fold's binary function has the accumulator as the first parameter and the current value as the second one (so \acc x -> ...)
or I can write as
elem' :: (Eq a) => a -> [a] -> Bool
elem' y ys = foldr (\x acc -> if x == y then True else acc) False ys
Anyone, can help/guide/explain me ?
Many thanks!
The way I like to understand these "reverse list with foldr" problems is to split it into pieces, and apply the lesson of "Foldr is made of monoids". Don't worry, this isn't as scary as it sounds.
First, let's note that reverse can be implemented this way:
my_reverse xs = foldl (flip (:)) xs []
This is the first simplification to our problem: if we can figure out how to write foldl in terms of foldr, then we can plug that solution into my_reverse to and be done with it.
Now, the standard type signature for foldr is this:
foldr :: (a -> r -> r) -> r -> [a] -> r
But the order of the arguments doesn't really matter, so let's rearrange things this way (throwing in a few implicit parentheses as well), and we'll compare it with map:
my_foldr :: (a -> (r -> r)) -> [a] -> (r -> r)
map :: (a -> b ) -> [a] -> [b]
Once you see this correspondence, it's not hard to see that we can write my_foldr this way:
my_foldr :: (a -> (r -> r)) -> [a] -> (r -> r)
my_foldr f as = compose (map f as)
where compose :: [r -> r] -> (r -> r)
compose = foldr (.) id
Think of this in the following way:
The map operation is converting each element of the list into a "step" of the transformation that we apply to the r values.
The compose function takes the resulting list of "steps" and wires them all together, using the . operator.
And now the trick is that we can write a foldl counterpart with a small change:
my_foldl :: (a -> (r -> r)) -> [a] -> (r -> r)
my_foldl f as = compose (map f as)
where compose :: [r -> r] -> (r -> r)
compose = foldr (flip (.)) id
{- Example:
>>> my_foldl (:) [1..3] []
[3,2,1]
-}
All I did was change (.) to flip (.)! And note that my_foldl is written in terms of map and foldr... but map can be rewritten in terms of foldr as well:
my_map :: (a -> b) -> [a] -> [b]
my_map f = foldr (\a bs -> f a : bs) []
So we've ended up with a solution that's different and longer than the one you're trying to understand, but hopefully it's illuminating.
The crucial thing is how this work with difference lists. Let's write out some explicit conversions:
type DList a = [a]->[a]
emptyDList :: Dlist a
emptyDList = id
fromDList :: DList a -> [a]
fromDList f = f []
myReverse'' :: ∀ a . [a] -> [a]
myReverse'' xs = fromDList $ foldr revCons emptyDList xs
where revCons :: a -> DList a -> DList a
revCons x fId empty = fId $ x : empty
Note that revCons has three arguments, though its signature actually suggests only two: difference lists are really a function type, but you can think of these functions as an abstract optimised representation for concrete lists.
If you do:
Prelude :t \x fId empty -> fId (x : empty)
You will get:
\x fId empty -> fId (x : empty) :: a -> ([a] -> t) -> [a] -> t
This function type here is equivalent to:
a -> ([a] -> t) -> ([a] -> t)
which means a function (binary function) that takes two arguments (the second argument is a function i.e. [a] -> t) and returns a function (i.e. [a] -> t).
This binary function matches the first argument that foldr takes (i.e. a -> b -> b).
In other words, foldr (\x fId empty -> fId (x : empty)) takes two arguments: a function and a list and returns a function.
Prelude> :t foldr (\x fId empty -> fId (x : empty))
foldr (\x fId empty -> fId (x : empty))
:: ([a] -> t) -> [a] -> [a] -> t
Take this example: foldr (\x fId empty -> fId (x : empty)) id [1, 2, 3].
Step 1: 3 and id are passed to the anonymous binary function as arguments. A function like \empty -> id (3 : empty) is returned as the new accumulator value.
Step 2: 2 and \empty -> id (3 : empty) are passed to the anonymous binary function. And \empty -> id (3 : (2 : empty)) is returned.
Step 3: 1 and \empty -> id (3 : (2 : empty)) are passed to the anonymous binary function. And \empty -> id (3 : (2 : (1 : empty))) is returned.
So foldr (\x fId empty -> fId (x : empty)) id [1, 2, 3] produces a function like \empty -> id (3 : (2 : (1 : empty))).
If you apply \empty -> id (3 : (2 : (1 : empty))) to [], then it will give you [3, 2, 1].
This means foldr (\x fId empty -> fId (x : empty)) id [1, 2, 3] [] produces [3, 2, 1].

Adding predicate to a map function

Completely new to Haskell and learning through Learn Haskell the greater good.
I am looking at the map function
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
is it possible to add a predicate to this? for example, to only map to every other element in the list?
You can code your own version of map to apply f only to even (or odd) positions as follows. (Below indices start from 0)
mapEven :: (a->a) -> [a] -> [a]
mapEven f [] = []
mapEven f (x:xs) = f x : mapOdd f xs
mapOdd :: (a->a) -> [a] -> [a]
mapOdd f [] = []
mapOdd f (x:xs) = x : mapEven f xs
If instead you want to exploit the library functions, you can do something like
mapEven :: (a->a) -> [a] -> [a]
mapEven f = map (\(flag,x) -> if flag then f x else x) . zip (cycle [True,False])
or even
mapEven :: (a->a) -> [a] -> [a]
mapEven f = map (uncurry (\flag -> if flag then f else id)) . zip (cycle [True,False])
If you want to filter using an arbitrary predicate on the index, then:
mapPred :: (Int -> Bool) -> (a->a) -> [a] -> [a]
mapPred p f = map (\(i,x) -> if p i then f x else x) . zip [0..]
A more direct solution can be reached using zipWith (as #amalloy suggests).
mapEven :: (a->a) -> [a] -> [a]
mapEven f = zipWith (\flag x -> if flag then f x else x) (cycle [True,False])
This can be further refined as follows
mapEven :: (a->a) -> [a] -> [a]
mapEven f = zipWith ($) (cycle [f,id])
The "canonical" way to perform filtering based on positions is to zip the sequence with the naturals, so as to append an index to each element:
> zip [1, 1, 2, 3, 5, 8, 13] [0..]
[(1,0),(1,1),(2,2),(3,3),(5,4),(8,5),(13,6)]
This way you can filter the whole thing using the second part of the tuples, and then map a function which discards the indices:
indexedFilterMap p f xs = (map (\(x,_) -> f x)) . (filter (\(_,y) -> p y)) $ (zip xs [0..])
oddFibsPlusOne = indexedFilterMap odd (+1) [1, 1, 2, 3, 5, 8, 13]
To be specific to you question, one might simply put
mapEveryOther f = indexedFilterMap odd f
You can map with a function (a lambda is also possible):
plusIfOdd :: Int -> Int
plusIfOdd a
| odd a = a
| otherwise = a + 100
map plusIfOdd [1..5]
As a first step, write the function for what you want to do to the individual element of the list:
applytoOdd :: Integral a => (a -> a) -> a -> a
applytoOdd f x = if odd x
then (f x)
else x
So applytoOdd function will apply the function f to the element if the element is odd or else return the same element if it is even. Now you can apply map to that like this:
λ> let a = [1,2,3,4,5]
λ> map (applytoOdd (+ 100)) a
[101,2,103,4,105]
Or if you want to add 200 to it, then:
λ> map (applytoOdd (+ 200)) a
[201,2,203,4,205]
Looking on the comments, it seems you want to map based on the index position. You can modify your applytoOdd method appropriately for that:
applytoOdd :: Integral a => (b -> b) -> (a, b) -> b
applytoOdd f (x,y) = if odd x
then (f y)
else y
Here, the type variable a corresponds to the index element. If it's odd you are applying the function to the actual element of the list. And then in ghci:
λ> map (applytoOdd (+ 100)) (zip [1..5] [1..])
[101,2,103,4,105]
λ> map (applytoOdd (+ 200)) (zip [1..5] [1..])
[201,2,203,4,205]
Or use a list comprehension:
mapOdd f x = if odd x then f x else x
[ mapOdd (+100) x | x <- [1,2,3,4,5]]
I'm glad that you're taking the time to learn about Haskell. It's an amazing language. However it does require you to develop a certain mindset. So here's what I do when I face a problem in Haskell. Let's start with your problem statement:
Is it possible to add a predicate to the map function? For example, to only map to every other element in the list?
So you have two questions:
Is it possible to add a predicate to the map function?
How to map to every other element in the list?
So the way people think in Haskell is via type signatures. For example, when an engineer is designing a building she visualizes how the building should look for the top (top view), the front (front view) and the side (side view). Similarly when functional programmers write code they visualize their code in terms of type signatures.
Let's start with what we know (i.e. the type signature of the map function):
map :: (a -> b) -> [a] -> [b]
Now you want to add a predicate to the map function. A predicate is a function of the type a -> Bool. Hence a map function with a predicate will be of the type:
mapP :: (a -> Bool) -> (a -> b) -> [a] -> [b]
However, in your case, you also want to keep the unmapped values. For example mapP odd (+100) [1,2,3,4,5] should result in [101,2,103,4,105] and not [101,103,105]. Hence it follows that the type of the input list should match the type of the output list (i.e. a and b must be of the same type). Hence mapP should be of the type:
mapP :: (a -> Bool) -> (a -> a) -> [a] -> [a]
It's easy to implement a function like this:
map :: (a -> Bool) -> (a -> a) -> [a] -> [a]
mapP p f = map (\x -> if p x then f x else x)
Now to answer your second question (i.e. how to map to every other element in the list). You could use zip and unzip as follows:
snd . unzip . mapP (odd . fst) (fmap (+100)) $ zip [1..] [1,2,3,4,5]
Here's what's happening:
We first zip the index of each element with the element itself. Hence zip [1..] [1,2,3,4,5] results in [(1,1),(2,2),(3,3),(4,4),(5,5)] where the fst value of each pair is the index.
For every odd index element we apply the (+100) function to the element. Hence the resulting list is [(1,101),(2,2),(3,103),(4,4),(5,105)].
We unzip the list resulting in two separate lists ([1,2,3,4,5],[101,2,103,4,105]).
We discard the list of indices and keep the list of mapped results using snd.
We can make this function more general. The type signature of the resulting function would be:
mapI :: ((Int, a) -> Bool) -> (a -> a) -> [a] -> [a]
The definition of the mapI function is simple enough:
mapI :: ((Int, a) -> Bool) -> (a -> a) -> [a] -> [a]
mapI p f = snd . unzip . mapP p (fmap f) . zip [1..]
You can use it as follows:
mapI (odd . fst) (+100) [1,2,3,4,5]
Hope that helps.
Is it possible to add a predicate to this? for example, to only map to every other element in the list?
Yes, but functions should ideally do one relatively simple thing only. If you need to do something more complicated, ideally you should try doing it by composing two or more functions.
I'm not 100% sure I understand your question, so I'll show a few examples. First: if what you mean is that you only want to map in cases where a supplied predicate returns true of the input element, but otherwise just leave it alone, then you can do that by reusing the map function:
mapIfTrue :: (a -> Bool) -> (a -> a) -> [a] -> [a]
mapIfTrue pred f xs = map step xs
where step x | pred x = f x
| otherwise = x
If what you mean is that you want to discard list elements that don't satisfy the predicate, and apply the function to the remaining ones, then you can do that by combining map and filter:
filterMap :: (a -> Bool) -> (a -> b) -> [a] -> [b]
filterMap pred f xs = map f (filter pred xs)
Mapping the function over every other element of the list is different from these two, because it's not a predicate over the elements of the list; it's either a structural transformation of the list of a stateful traversal of it.
Also, I'm not clear whether you mean to discard or keep the elements you're not applying the function to, which would imply different answers. If you're discarding them, then you can do it by just discarding alternate list elements and then mapping the function over the remaining ones:
keepEven :: [a] -> [a]
keepEven xs = step True xs
where step _ [] = []
step True (x:xs) = x : step False xs
step False (_:xs) = step True xs
mapEven :: (a -> b) -> [a] -> [b]
mapEven f xs = map f (keepEven xs)
If you're keeping them, one way you could do it is by tagging each list element with its position, filtering the list to keep only the ones in even positions, discard the tags and then map the function:
-- Note: I'm calling the first element of a list index 0, and thus even.
mapEven :: (a -> a) -> [a] -> [a]
mapEven f xs = map aux (filter evenIndex (zip [0..] xs))
where evenIndex (i, _) = even i
aux (_, x) = f x
As another answer mentioned, zip :: [a] -> [b] -> [(a, b)] combines two lists pairwise by position.
But this is the general philosophy: to do a complex thing, use a combination of general-purpose generic functions. If you're familiar with Unix, it's similar to that.
Another simple way to write the last one. It's longer, but keep in mind that evens, odds and interleave all are generic and reusable:
evens, odds :: [a] -> [a]
evens = alternate True
odds = alternate False
alternate :: Bool -> [a] -> [a]
alternate _ [] = []
alternate True (x:xs) = x : alternate False xs
alternate False (_:xs) = alternate True xs
interleave :: [a] -> [a] -> [a]
interleave [] ys = ys
interleave (x:xs) ys = x : interleave ys xs
mapEven :: (a -> a) -> [a] -> [a]
mapEven f xs = interleave (map f (evens xs)) (odds xs)
You can't use a predicate because predicates operate on list values, not their indices.
I quite like this format for what you're trying to do, since it makes the case handling quite clear for the function:
newMap :: (t -> t) -> [t] -> [t]
newMap f [] = [] -- no items in list
newMap f [x] = [f x] -- one item in list
newMap f (x:y:xs) = (f x) : y : newMap f xs -- 2 or more items in list
For example, running:
newMap (\x -> x + 1) [1,2,3,4]
Yields:
[2,2,4,4]

Resources