best way to write a-> ..->[a] recursive functions in haskell - haskell

So I keep having this small problem where I have something like
func :: a -> b -> [a] -- # or basically any a-> ...-> [a] where ... is any types ->
func x y = func' [x] y -- '# as long as they are used to generate a list of [a] from x
func' :: [a] -> b -> [a]
func' = undefined -- # situation dependant generates a list from
-- # each element and returns it as one long list
should I keep it like this?
should I use func' hidden by a where?
should I only use the [a] -> b -> [a] version and leave the responsibility of passing [variable] to the callee?
I might well need to compose these functions and might want to mess around with the order so I'm leaning towards option 3. What do you think?

It looks like you are trying to reinvent concatMap:
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f = concat . map f
So the "map" bit takes each element of the input list applies "f" to it. "f" takes a single "a" and returns a "[b]". These individual lists are then concatenated into a single list.

As Paul noted, func' can be replaced with concatMap and func.
And func itself reminds me of unfoldr from Data.List:
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
It is used to generate a list of a from b.
By the way, func and func' are unfortunate names for such functions.

Related

Short-circuit list, type of `(a -> Either e a) -> [a] -> Either e [a]` ... monadic operation?

Consider the following function:
validateList :: (a -> Either e a) -> [a] -> Either e [a]
validateList validate [] = Right []
validateList validate (x:xs) =
case validate x of
Left err -> Left err
Right y -> case validateList validate xs of
Left err -> Left err
Right ys -> Right $ y:ys
Is there a way to write this in a more concise way? Maybe using the >>= operator?
A bit to think about because there are actually two monads here: [] and Either, although List here is not acting as a monad but just more so as a Traversable
I believe your Traversable idea is exactly what you need.
validateList :: (a -> Either e a) -> [a] -> Either e [a]
validateList = traverse
This is traverse using the Either a applicative functor and the [] traversable/foldable.
Note that this does indeed lazy/short-circuiting: as soon as a Left is found the rest of the input list is no longer demanded. Here is a test using an infinite list:
> validateList (\n -> case n of 1 -> Right 56 ; 2 -> Left "fdsf") [1..]
Left "fdsf"

How to write a code in Haskell to filter out Nothing values from a list

I wish to "map a list and drop it if the map function returns Nothing". I am doing as follows:-
filteredList f l = map to_int (mapMaybe f l)
The to_int function here is as follows
to_int some_value = case some_value of
Just a -> a
Nothing -> 0
This although logically correct to me, is not working as it should. Can someone please explain where I am wrong here?
What you are trying to implement already exists. Indeed, mapMaybe :: (a -> Maybe b) -> [a] -> [b] will take function and a list, call the function on the elements of the list, and retrieve the items that returned a Just … object. The items are unwrapped from the Just data constructor.
This function is defined in the base package, but not in the Prelude. This means that you should import this from the Data.Maybe module:
import Data.Maybe(mapMaybe)
filteredList :: (a -> Maybe b) -> [a] -> [b]
filteredList = mapMaybe
You can specialize this for example with a ~ b ~ Integer and thus use this as (Integer -> Maybe Integer) -> [Integer] -> [Integer].
You can also implement this function yourself, for example with list comprehension:
filteredList :: (a -> Maybe b) -> [a] -> [b]
filteredList f l = [ y | Just y <- map f l ]
Here we thus use pattern matching to ensure that we receive an Just x pattern. If the pattern does not match, then this item is skipped. We also unwrap the y from the Just y pattern, and use this as item to put in the list.

Isn't map takes a function and a list return a list?

map2_List :: (a -> b -> c) -> [a] -> [b] -> [c]
map2_List f [] _ = []
map2_List f (a:as) bs = map (f a) bs ++ map2_List f as bs
This is an example from my lecture, which try to apply a binary function to all pairs of elements of two lists. The part (f a) makes me confused. Does it suppose to be a value but not a function? Then what does map value bs do?
"The part (f a) makes me confused."
What is happening here is called currying and if you are coming to Haskell from imperative languages, it can be confusing.
In Haskell, all functions technically take a single value and return a single value. The returned value could be another function. Most programmers take the mental shortcut of thinking of functions taking all the values in their definition (the term is "saturated" BTW) and producing the final value, but even with this mental shortcut, there are a lot of times, like this, when it is not the case.
The function f is a binary function, and (f a) is that function partially applied. The type of (f a) :: b -> c.
"Then what does map value bs do?"
The map function (map :: (a->b) -> [a] ->[b]) is part of the standard prelude. It takes a simple function and applies it to each element in a list.
So let's take map (f a) bs apart:
map :: (b->c) -> [b] ->[c] applies a function to each element of a list
(f a) :: b -> c using currying a function f :: a -> b -> c is applied to an a and returns a function b -> c
bs is the second list from map2_List
The result of this function is [c], the function f applied to one element of the first list then applied to every element of the second list.

How to analyse a function in Haskell?

Hi everyone Haskell newbie here. I'm really confused about how to look at a curried function.
For example, here is a function definition
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' _ [] _ = []
zipWith' _ _ [] = []
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys
When I call
zipWith' (zipWith' (*)) [[1,2,3],[3,5,6]] [[3,2,2],[3,4,5]]
I understand that
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
is equivalent to
zipWith' :: (a -> b -> c) -> ([a] -> ([b] -> [c]))
But what I don't understand is the way/order to look at it. Should we analyse it from left to right? Such as look at the (a -> b -> c) first and then apply the [a] in to the (a -> b -> c) and lastly apply ([b] -> [c]) into (a -> b -> c) -> [a]? Or is it the other way round?
And if you don't understand what I'm asking (sorry :( ), could you just show me how you think when you see this kind of problems? I freak out whenever I see these functions and it usually takes me a while to figure out :P
Curried functions look scarier than they are. One way of thinking about how they work is uncurrying them. For instance:
(++) :: [t] -> [t] -> [t]
Becomes, when uncurried:
(++) :: ([t], [t]) -> [t]
In my eyes, that's all the explanation needed, but here's a more detailed one, that might explain it fully:
A function of type a -> b takes an argument of type a and returns an argument of type b. Remember that a -> b is in itself a concrete type and could take the place of b in the first, making a function of something like a -> (b -> c).
Let's say that a function f is of type a -> b -> c, which is as above. What does that mean? It is a function that returns a function! That is how currying works. The idea of functions returning other functions allows us to partially apply functions, limiting or specifying their traits.
Let's now make our own function specifying that:
func :: a -> [a] -> [a]
func = \elem -> ( \list -> elem : list )
The lambda expressions here have been written in such a way that it should be obvious what the type means: the first lambda (\elem -> ...) constructs the other based on it's input.
Now, let's have a look at zipWith:
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
The first argument to zipWith is a function, which in itself takes two arguments. Not too crazy.
The second argument is a list which can be passed to the function, because of the type variables defined.
The third argument is another list that can be passed to the function after the first.
The return value is a list of the resultant type of the function we passed to zipWith first.
So, let's start with zipping function. It's type is a -> (b -> c). It takes as a parameter of type a, and returns function which transforms b to c. It is isomorphic to it's uncurried equivalence (a, b) -> c, the difference is that we fix first parameter, to get function which now requires only b to return c.
So this is what the zipper's type mean. Now let's move on to zipWith'. It takes as a parameter zipping function (explained above). It returns something of type [a] -> ([b] -> [c]), which is pretty similiar to zipper function. We can say that zipWith' lifts zipping function to work with lists -zipWith' returns a function witch takes a list of as, and returns function which takes list of bs and returns list of cs.
In your example we have zipWith' (*). For simplicity assume that (*) is of type Int -> (Int -> Int) (in reality it is more general - (Num a) => a -> (a -> a). Then we have a ~ b ~ c ~ Int and zipWith' (*) :: [Int] -> ([Int] -> [Int]). Then zipWith' (*) takes as a parameter a list of Ints and returns a function which transforms one list of Ints to another. So it can be used to zip two lists of lists of as. And this is exactly what happens.
In this case it might be helpful to think of the nested lists as (2-dimensional) matrices.
A = ( 1 2 3 ) B = ( 3 2 2 ) --> result = ( 3 4 6 )
( 3 5 6 ) ( 3 4 5 ) ( 9 20 30 )
The outer zip' combines the rows from A and B and the inner zip combines a pair of rows into another row, and so it is clear the result will have the same shape as the inputs.
It also might be helpful to realize that zipWith (*) is just component-wise multiplication of vectors. In fact there is a pattern:
zipWith (*) -- component-wise * on 1-d matrices
zipWith (zipWith (*)) -- component-wise * on 2-d matrices
zipWith (zipWith (zipWith (*))) -- component-wise * on 3-d matrices
...
and of course (*) can be replaced by any binary operation.
Some other list functions and their matrix interpretations:
map - iterate over all of the rows
transpose - transpose rows and columns
concat - flatten the first dimension (i.e. all rows into a single row)
As an exercise you might try implementing matrix multiplication with list operations.
Left to right.
In fact you can see it with 4 different point of view
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
-- take a function, 2 list and returns a list
zipWith (*) :: [a] -> [b] -> [c]
-- new function which takes 2 list and returns a new one
zipWith (*) [1,2,3] :: [b] -> [c]
-- new function which takes a list a produce a new one
zipPwith * [1,2,3] [3,5,6] :: [c]
-- a function without argument, or a value (equivalent in Haskell)
Or right to left :-)
zipPwith * [1,2,3] [3,5,6] :: [c]
-- a function without argument, or a value (equivalent in Haskell)
zipWith (*) [1,2,3] :: [b] -> [c]
-- new function which takes a list a produce a new one
zipWith (*) :: [a] -> [b] -> [c]
-- new function which takes 2 list and returns a new one
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
-- take a function, 2 list and returns a list

How is the calculation of types in Haskell

Lets say
flip :: (a->b->c) ->b->a->c
const ::d->e->d
type of (flip const) would be
a=d,b=e,c=d
in
b->a->c
so the type would be
e->d->d
But for (map take) its
[Int]->[[a]]->[[a]]
so i didn't understand how the ghci this one calculated.
i understood the [[a]]->[[a]] but why and how [Int] ?
edit: For example if we'd write in ghci
:t flip const
it would return b->c->c
and ghci would calculate that as i did.
But
map :: (a->b)->[a]->[b]
take :: Int->[c]->[c]
so why is map take
[Int]->[[a]->[a]]
why [Int] how did the ghci calculate that
Let's do the same analysis:
map :: (a -> b) -> [a] -> [b]
And
take :: Int -> [x] -> [x]
But that actually means
take :: Int -> ([x] -> [x])
So with a=Int and b=([x] -> [x]) you get
map take :: [Int] -> [ [x] -> [x] ]
A list of list functions!
You should copy and paste the types you see, not re-type them into the question. The reason is you saw wrong. The type for map take is:
map take :: [Int] -> [[a] -> [a]]
In other words, the unification works as such:
:t map
map :: (a -> b) -> [a] -> [b]
:t take
take :: Int -> [c] -> [c]
so when applying take as the first argument to map you get a ~ Int and b ~ [c] -> [c] (notice that is a function). Performing these replacements in the map type and applying the first argument:
map take :: [a] -> [b] (for some specific 'a' and 'b')
-- recall a ~ Int
map take :: [Int] -> [b] (for some specific 'b')
-- recall b ~ [c] -> [c]
map take :: [Int] -> [[c] -> [c]]
Yay, map take is exactly what you expect. A function that operates over lists of Ints and results in a list of functions that will take some number of elements from the start of a list.

Resources