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

I'd like a more elegant way to write the following two functions, ideally in one :
applyOperatorBetweenVariableLists:: [Variable] -> String -> [Variable] -> [Variable]
applyOperatorBetweenVariableLists firstList operator secondList = concat $ map (test firstList operator) secondList
test:: [Variable] -> String -> Variable -> [Variable]
test firstVariables operator secondVariable = concat $ map (applyOperatorBetweenVariables secondVariable operator) firstVariables
The declaration of applyOperatorBetweenVariables is :
applyOperatorBetweenVariables:: Variable -> String -> Variable -> [Variable]
I'm quite sure there must be a Prelude Function that does exactly this, or a very elegant way to write it.

This can be done concisely with a do block:
applyOperatorBetweenVariableLists firstList operator secondList = do
secondVariable <- secondList
firstVariable <- firstList
applyOperatorBetweenVariables secondVariable operator firstVariable
If you wanted to be even more concise, you could reorder the arguments to both applyOperatorBetweenVariableLists and applyOperatorBetweenVariables, and then use either liftJoin2 or bind2 to implement it (like my final sentence below but with it in place of liftA2).
My original answer was wrong, as it left a layer of nesting (i.e., should have done an extra concat or join):
That's almost just liftA2, but your arguments are in a weird order. Here's how you'd implement what you wrote in terms of that:
import Control.Applicative (liftA2)
applyOperatorBetweenVariableLists firstList operator secondList = liftA2 (flip applyOperatorBetweenVariables operator) secondList firstList
From that definition, it should be clear how you could change and simplify that to applyOperatorBetweenVariableLists = liftA2 . applyOperatorBetweenVariables just by reordering the arguments to it and to applyOperatorBetweenVariables.

Related

Haskell Pattern Matching (beginner)

I have to implement a small programm in Haskell that increments/decrements a result by what in the console line is. For example if we have -a in the console the results must be 0, if -b the result must be incremented with 6 and so on. I have to do this with pattern matching.
I haven't used Haskell until now and I find it pretty hard to understand. I have this to start with:
import System.Environment
main = getArgs >>= print . (foldr apply 0) . reverse
apply :: String -> Integer -> Integer
I don't understand what in the main is. What does it make and the reverse from end, what does it do? As I've read on the internet the getArgs function gives me the values from the console line. But how can I use them? Are there are equivalent functions like for/while in Haskell?
Also, if you have some examples or maybe could help me, I will be very thankful.
Thanks!
This is not beginner-friendly code. Several shortcuts are taken there to keep the code very compact (and in pointfree form). The code
main = getArgs >>= print . (foldr apply 0) . reverse
can be expanded as follows
main = do
args <- getArgs
let reversedArgs = reverse args
result = foldr apply 0 reversedArgs
print result
The result of this can be seen as follows. If the command line arguments are, say, args = ["A","B","C"], then we get reversedArgs = ["C","B","A"] and finally
result = apply "C" (apply "B" (apply "A" 0))
since foldr applies the function apply in such way.
Honestly, I'm unsure about why the code uses reverse and foldr for your task. I would have considered foldl (or, to improve performance, foldl') instead.
I expect the exercise is not to touch the given code, but to expand on it to perform your function. It defines a complicated-looking main function and declares the type of a more straight forward apply, which is called but not defined.
import System.Environment -- contains the function getArgs
-- main gets arguments, does something to them using apply, and prints
main = getArgs >>= print . (foldr apply 0) . reverse
-- apply must have this type, but what it does must be elsewhere
apply :: String -> Integer -> Integer
If we concentrate on apply, we see that it receives a string and an integer, and returns an integer. This is the function we have to write, and it can't decide control flow, so we can just get to it while hoping the argument handling works out.
If we do want to figure out what main is up to, we can make a few observations. The only integer in main is 0, so the first call must get that as its second argument; later ones will be chained with whatever is returned, as that's how foldr operates. r stands for from the right, but the arguments are reversed, so this still processes arguments from the left.
So I could go ahead and just write a few apply bindings to make the program compile:
apply "succ" n = succ n
apply "double" n = n + n
apply "div3" n = n `div` 3
This added a few usable operations. It doesn't handle all possible strings.
$ runhaskell pmb.hs succ succ double double succ div3
3
$ runhaskell pmb.hs hello?
pmb.hs: pmb.hs:(5,1)-(7,26): Non-exhaustive patterns in function apply
The exercise should be about how you handle the choice of operation based on the string argument. There are several options, including distinct patterns as above, pattern guards, case and if expressions.
It can be useful to examine the used functions to see how they might fit together. Here's a look at a few of the used functions in ghci:
Prelude> import System.Environment
Prelude System.Environment> :t getArgs
getArgs :: IO [String]
Prelude System.Environment> :t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Prelude System.Environment> :t print
print :: Show a => a -> IO ()
Prelude System.Environment> :t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
Prelude System.Environment> :t foldr
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
Prelude System.Environment> :t reverse
reverse :: [a] -> [a]
This shows that all the strings come out of getArgs, it and print operate in the IO monad, which must be the m in >>=, and . transfers results from the right function into arguments for the left function. The type signature alone doesn't tell us what order foldr handles things, though, or what reverse does (though it can't create new values, only reorder including repetition).
As a last exercise, I'll rewrite the main function in a form that doesn't switch directions as many times:
main = print . foldl (flip apply) 0 =<< getArgs
This reads from right to left in a data flow sense and handles arguments from left to right because foldl performs left-associative folding. flip is just there to match the argument order for apply.
As suggested in the comment, hoogle is a great tool.
To find out what exactly you get from getArgs you can search for it on hoogle:
https://hackage.haskell.org/package/base-4.11.1.0/docs/System-Environment.html#v:getArgs
As you can see, it's of type IO [String].
Since I don't know how familiar you are with the IO abstractions yet, we'll just say that the right part of >>= gets those as argument.
The arguments for a call like ./a.out -a -b --asdf Hi will then be a list of strings:
["-a", "-b", "--asdf", "Hi"].
The fold + reverse in the main will then do some magic, and your apply function will be called with each string in the list and the previous return value (0 for the first invocation).
In Haskell, String is the same as [Char] with a bit of compiler sugar, so you can match on strings like you would on regular lists in your definition of apply.

Why does this function work even though the argument is missing?

I'm trying to understand the following piece of code:
import Data.Char (ord)
encodeInteger :: String -> Integer
encodeInteger = read . concatMap ch
where ch c = show (ord c)
But I don't see how this can work when encodeInteger is defined as a function that takes a string, but in the second line, the function is implemented without that string argument.
Also, concatMap (according to hoogle), takes a function and a list, but only the function ch is provided.
Why does this code still work? Is the argument somehow magically passed? Has it something to do with currying?
edit: And why doesn't it work to change it like this:
encodeInteger :: String -> Integer
encodeInteger a = read . concatMap ch a
where ch c = show (ord c)
Basically defining a function
f = g
is the same as defining the function
f x = g x
In your specific case, you can use
encodeInteger a = (read . concatMap ch) a
to define your function. The parentheses are needed, otherwise it is parsed as
encodeInteger a = (read) . (concatMap ch a)
and concatMap ch a is not a function and can not be composed. At most you could write
encodeInteger a = read (concatMap ch a)
-- or
encodeInteger a = read $ concatMap ch a
About "why concatMap ch takes only one argument?". This is a partial application, which is very common in Haskell. If you have
f x y z = x+y+z
you can call f with fewer arguments, and obtain as the result a function of the remaining arguments. E.g., f 1 2 is the function taking z and returning 1+2+z.
Concretely, thanks to Currying, there's no such a thing as a function taking two or more arguments. Every function always takes only one argument. When you have a function like
foo :: Int -> Bool -> String
then foo takes one argument, an Int. It returns a function, which takes a Bool and finally returns a String. You can visualize this by writing
foo :: Int -> (Bool -> String)
Anyway, if you look up currying and partial application, you will find plenty of examples.
encodeInteger :: String -> Integer
encodeInteger = read.concatMap (\char -> show $ ord char)
The encodeInteger on the left hand side (LHS) of "=" is a name; it refers to the function on the right hand side (RHS) of "=". Both have the function type: String -> Integer. Both take a list of characters and produces an integer. Haskell enables us to express such function equality without specifying formal arguments (a style known as point-free).
Now, let's look at the RHS. The (.) operator composes two functions together. The composed function takes a string as its input from concatMap and produces an integer coming out of read as the output of the composed function.
concatMap itself takes 2 inputs, but we need to leave out the second one for the composed function, which requires a string as its input. We achieve this by partially applying concatMap, including only its first argument.

Variable scope in a higher-order lambda function

In working through a solution to the 8 Queens problem, a person used the following line of code:
sameDiag try qs = any (\(colDist,q) -> abs (try - q) == colDist) $ zip [1..] qs
try is an an item; qs is a list of the same items.
Can someone explain how colDist and q in the lambda function get bound to anything?
How did try and q used in the body of lambda function find their way into the same scope?
To the degree this is a Haskell idiom, what problem does this design approach help solve?
The function any is a higher-order function that takes 2 arguments:
the 1st argument is of type a -> Bool, i.e. a function from a to Bool
the 2nd argument is of type [a], i.e. a list of items of type a;
i.e. the 1st argument is a function that takes any element from the list passed as the 2nd argument, and returns a Bool based on that element. (well it can take any values of type a, not just the ones in that list, but it's quite obviously certain that any won't be invoking it with some arbitrary values of a but the ones from the list.)
You can then simplify thinking about the original snippet by doing a slight refactoring:
sameDiag :: Int -> [Int] -> Bool
sameDiag try qs = any f xs
where
xs = zip [1..] qs
f = (\(colDist, q) -> abs (try - q) == colDist)
which can be transformed into
sameDiag :: Int -> [Int] -> Bool
sameDiag try qs = any f xs
where
xs = zip [1..] qs
f (colDist, q) = abs (try - q) == colDist)
which in turn can be transformed into
sameDiag :: Int -> [Int] -> Bool
sameDiag try qs = any f xs
where
xs = zip [1..] qs
f pair = abs (try - q) == colDist) where (colDist, q) = pair
(Note that sameDiag could also have a more general type Integral a => a -> [a] -> Bool rather than the current monomorphic one)
— so how does the pair in f pair = ... get bound to a value? well, simple: it's just a function; whoever calls it must pass along a value for the pair argument. — when calling any with the first argument set to f, it's the invocation of the function any who's doing the calling of f, with individual elements of the list xs passed in as values of the argument pair.
and, since the contents of xs is a list of pairs, it's OK to pass an individual pair from this list to f as f expects it to be just that.
EDIT: a further explanation of any to address the asker's comment:
Is this a fair synthesis? This approach to designing a higher-order function allows the invoking code to change how f behaves AND invoke the higher-order function with a list that requires additional processing prior to being used to invoke f for every element in the list. Encapsulating the list processing (in this case with zip) seems the right thing to do, but is the intent of this additional processing really clear in the original one-liner above?
There's really no additional processing done by any prior to invoking f. There is just very minimalistic bookkeeping in addition to simply iterating through the passed in list xs: invoking f on the elements during the iteration, and immediately breaking the iteration and returning True the first time f returns True for any list element.
Most of the behavior of any is "implicit" though in that it's taken care of by Haskell's lazy evaluation, basic language semantics as well as existing functions, which any is composed of (well at least my version of it below, any' — I haven't taken a look at the built-in Prelude version of any yet but I'm sure it's not much different; just probably more heavily optimised).
In fact, any is simple it's almost trivial to re-implement it with a one liner on a GHCi prompt:
Prelude> let any' f xs = or (map f xs)
let's see now what GHC computes as its type:
Prelude> :t any'
any' :: (a -> Bool) -> [a] -> Bool
— same as the built-in any. So let's give it some trial runs:
Prelude> any' odd [1, 2, 3] -- any odd values in the list?
True
Prelude> any' even [1, 3] -- any even ones?
False
Prelude> let adult = (>=18)
Prelude> any' adult [17, 17, 16, 15, 17, 18]
— see how you can sometimes write code that almost looks like English with higher-order functions?
zip :: [a] -> [b] -> [(a,b)] takes two lists and joins them into pairs, dropping any remaining at the end.
any :: (a -> Bool) -> [a] -> Bool takes a function and a list of as and then returns True if any of the values returned true or not.
So colDist and q are the first and second elements of the pairs in the list made by zip [1..] qs, and they are bound when they are applied to the pair by any.
q is only bound within the body of the lambda function - this is the same as with lambda calculus. Since try was bound before in the function definition, it is still available in this inner scope. If you think of lambda calculus, the term \x.\y.x+y makes sense, despite the x and the y being bound at different times.
As for the design approach, this approach is much cleaner than trying to iterate or recurse through the list manually. It seems quite clear in its intentions to me (with respect to the larger codebase it comes from).

Inverse of 'concat': transforming a flattened list into a nested list [duplicate]

This question already has answers here:
Haskell: Is there an idiomatic way to insert every item in a list into its own list?
(6 answers)
Closed 5 years ago.
Given a flattened list in Haskell:
['a', 'b','c','d']
how can I change it to:
[['a'], ['b'], ['c'], ['d']]
One way to describe what you want to do is to take each element in your list and wrap it, individually, with another list. Or, you'd like to perform the operation 'a' ---> ['a'] to each element of the list.
Whenever you're speaking about turning "each element of the list, individually, into something else" you're talking about a map [0] and so we'll write this function a bit like
example :: [Char] -> [[Char]]
example cs = map _ cs
Where the _ is the function 'a' ---> ['a']. This function can be written as an explicit anonymous function, though
example :: [Char] -> [[Char]]
example cs = map (\c -> [c]) cs
And this will achieve what we need!
But we can go a little further. First, in Haskell you're allowed to drop the last argument applied if it's the same as the last input argument. Or, more concretely, we can also write example as
example :: [Char] -> [[Char]]
example = map (\c -> [c])
by simply deleting the cs in both the argument list and as an argument to map. Second, we can take note that example's type is weaker than it could be. A better way of writing it is certainly
example :: [a] -> [[a]]
example = map (\c -> [c])
which reflects the fact that we didn't use anything specific to Char on the inside.
[0] Or, more generally, an fmap
You can do:
singleton x = [x]
f = map singleton
Well, Ting already answered, but I feel compelled to introduce you to the monkey operator (:[])
You can use this in place of singleton.
map (:[]) ['a', 'b', 'c', 'd']

Composing Haskell filters

I am converting the zxcvbn password strength algorithm to Haskell.
I have two functions that check for all characters being ASCII and that a brute force attack is possible:
filterAscii :: [String] -- ^terms to filter
-> [String] -- ^filtered terms
filterAscii = filter $ all (\ chr -> ord chr < 128)
and
filterShort :: [String] -- ^terms to filter
-> [String] -- ^filtered terms
filterShort terms = map fst $ filter long $ zip terms [1..]
where long (term, index) = (26 ^ length term) > index
I composed these into a single function:
filtered :: [String] -- ^terms to filter
-> [String] -- ^filtered terms
filtered = filterAscii . filterShort
I now have need to compose these with a third filter to check if the terms are not null:
filter (not . null) terms
It has occurred to me that I am creating a chain of filters and that it would make more sense to create a single function that takes a list of filter functions and composes them in the order given.
If I recall from my reading, this is a job for an applicative functor, I believe. Can I use applicatives for this?
I am not sure how to handle the filterShort function where I need to zip each item with its one-based index before filtering.
You can use the Endo wrapper from Data.Monoid to get a monoid instance that will allow you to use mconcat like so:
Prelude> :m + Data.Monoid
Prelude Data.Monoid> :t appEndo $ mconcat [Endo filterAscii, Endo filterShort]
appEndo $ mconcat [Endo filterAscii, Endo filterShort] :: [String] -> [String]
In other words, you want :
filters :: [a -> Bool] -> [a] -> [a]
filters fs = filter (\a -> and $ map ($ a) fs)
But you should also know that a pipeline of filters is very likely to be optimized by GHC (as far as I know) anyway. So it may not be worth it to create this function. Note that there will be some problems with your filterShort since it's not a pure filter.

Resources