Binary map in Haskell - haskell

Is there a two-operand equivalent to map built into Haskell with a type signature of:
map2 :: (a -> b -> c) -> [a] -> [b] -> [c]
The following equivalence should hold:
map2 operator as bs === [operator a b | (a, b) <- zip as bs]
Example:
ghci> map2 (*) [2,3] [4,5]
[8,15]

The function zipWith does what you need. There are also zipWith3 .. zipWith7 for cases with more than two lists.

It's called zipWith.
Here's its type:
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
Example:
zipWith (*) [2,3] [4,5]
Produces:
[8,15]
I might also recommend that you take a look at Hoogle for such questions in the future. A search for "(a->a->a)->[a]->[a]->[a]" turns up what you were looking for. :)

A more general solution is to use the ZipList instance of Applicative for lists:
let z = (+) <$> ZipList [2,3] <*> ZipList [4,5]
in runZipList z
The nice thing here is that it works with operators of arbitrary arity, so instead of zipWith3 .. zipWith7, you just tack on one more <*> e

Related

How to concatenate a value to a list when both are inside Maybes?

I'm reading realworldhaskell and I've come to chapter 4 where the book talks about "Safely and sanely working with crashy functions". I'm trying to write a safe version of init :: [a] -> [a]. This is as far as I got:
mySafeInit :: [a] -> Maybe [a]
mySafeInit [] = Nothing
mySafeInit (_:[]) = Just []
mySafeInit (x:xs) = ???
I get that I can't do something like x : mySafeInit xs, because that would be like doing a : Just [a] (right?). I've read about fmap though, so I tried this:
mySafeInit :: [a] -> Maybe [a]
mySafeInit [] = Nothing
mySafeInit (_:[]) = Just []
mySafeInit (x:xs) = fmap (:) (Just x) (mySafeInit xs)
Well that's guaranteed to work, right? Well no, and I'm struggling to understand why. Here I have a Just a and a Just [a], right? Shouldn't I be able to use fmap, give it the function (:) and my two maybes, and get a Just [a] back?
After some googling I did figure out that this works:
mySafeInit :: [a] -> Maybe [a]
mySafeInit [] = Nothing
mySafeInit (_:[]) = Just []
mySafeInit (x:xs) = fmap (:) (Just x) <*> (mySafeInit xs)
but I don't understand why. Could someone walk me through this? :)
Let's look at
fmap (:) (Just x) (mySafeInit xs)
For Maybe, fmap is defined as
fmap _ Nothing = Nothing
fmap f (Just x) = Just (f x)
Therefore
fmap (:) (Just x)
is
Just ((:) x)
Note that this is not a function; it's a Maybe value of some type (in fact, it's Maybe ([a] -> [a])). That's why
(Just ((:) x)) (mySafeInit xs)
is a type error (you can only apply functions).
In the second version of your code, you did
fmap (:) (Just x) <*> (mySafeInit xs)
, which is
(Just ((:) x)) <*> (mySafeInit xs)
Looking at the type of <*>, we get:
(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
Here f is Maybe, and a and b are both [a]:
(<*>) :: Maybe ([a] -> [a]) -> Maybe [a] -> Maybe [a]
That's why this version checks out.
Shouldn't I be able to use fmap, give it the function (:) and my two maybes, and get a Just [a] back?
No, because fmap only works with functions of one argument. There is another function for two arguments, though:
liftA2 :: (Applicative f) => (a -> b -> c) -> f a -> f b -> f c
Contrast with
fmap :: (Functor f) => (a -> b) -> f a -> f b
liftA2 (:) (Just x) (mySafeInit xs) should indeed work.
But it's needlessly complicated because one of your maybes is artificial: You explicitly wrapped your x in Just. You can simply do this instead:
fmap ((:) x) (mySafeInit xs)
By the definition of fmap, this is either Nothing (if mySafeInit xs is Nothing) or Just ((:) x y) (if mySafeInit xs is Just y).
Simple solution
I think you make things too hard/complex. You can simply consider two cases:
the empty list, in which case you return a Nothing; and
the non-empty list, in which case you can use the old init:
Or putting it into code:
mySafeInit :: [a] -> Maybe [a]
mySafeInit [] = Nothing
mySafeInit l = Just (init l)
Now of course we have to trust that there are only two constructors for a list; and that init will only error when we provide it an empty list. Both assumptions hold, but can (although very unlikely) change in the future.
We can however use our own init function:
mySafeInit :: [a] -> Maybe [a]
mySafeInit [] = Nothing
mySafeInit (l:ls) = Just (init l ls)
where init _ [] = []
init x (x2:xs) = x : init x2 xs
Now the Haskell compiler can verify that both functions are syntactically total. Note that functions can be total, but not syntactically: for instance because we can make assumptions regarding the structure of the data that the compiler can not check.
Working with fmap
You provide a solution like:
-- ...
mySafeInit (x:xs) = fmap (:) (Just x) <*> (mySafeInit xs)
A first aspect we have to understand is that Maybe is a Functor. A Fuctor supports a function fmap where we map the item(s) inside the functor so to speak. For instance a list is a functor as well, and we can thus map all elements in the list with fmap f somelist. You can see Maybe as some sort of list with zero elements (the Nothing) or one element (the Just x). So in case we perform fmap on a Nothing, we get a Nothing back, in case we perform this on a Just x, we get Just (f x).
Here we see fmap (:) (Just x). Since we thus apply it on a Just x, we have actually constructed:
fmap (:) Just x
-> Just ((x :))
This is thus a Just, but it carries a function (x : ), not a value.
Next we see a <*> operator. (<*>) :: Applicative f => f (a -> b) -> f a -> f b is some sort of "multiplication" over an Applicative (a Maybe is an applicative as well). On the left side we have an applicative of functions a -> b, on the right side an applicative of as. The result is an applicative of bs: for every tuple of functions and values.
In case we perform this on a list, we thus obtain a list that starts with the values all applied to the first function, then all values applied to the second function, etc.
For a Maybe we thus have a Maybe (a -> b) left and a Maybe a on the right. In case these are of the form Just f and Just x, we obtain Just (f x), in all other cases we obtain Nothing.
Since we perform a recursive call on mySafeInit xs, we thus obtain the init of the remaining list wrapped in a Just. In that case, we thus prepend that result with xs.
An equivalent code definition is thus:
mySafeInit :: [a] -> Maybe [a]
mySafeInit [] = Nothing
mySafeInit (_:[]) = Just []
mySafeInit (x:xs) | Just ys <- mySafeInit xs = Just (x:ys)
| otherwise = Nothing

Is it possible to fold <*> in haskell?

I want to realize something like
fun1 f a_ziplist
for example
getZipList $ (\x y z -> x*y+z) <$> ZipList [4,7] <*> ZipList [6,9] <*> ZipList [5,10]
f = (\x y z -> x*y+z)
ziplist = [[4,7],[6,9],[5,10]]
To do this, I want to recursively apply <*> like
foldx (h:w) = h <*> foldx w
foldx (w:[]) = w
but it seems impossible to make <*> recursive.
Let's play with the types in ghci, to see where they carry us.
λ import Control.Applicative
The type of (<*>)
λ :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
The type of foldr:
λ :t Prelude.foldr
Prelude.foldr :: (a -> b -> b) -> b -> [a] -> b
Perhaps we could use (<*>) as the function that is passed as the first parameter of foldr. What would be the type?
λ :t Prelude.foldr (<*>)
Prelude.foldr (<*>) :: Applicative f => f a -> [f (a -> a)] -> f a
So it seems that it takes an initial value in an applicative context, and a list of functions in an applicative context, and returns another applicative.
For example, using ZipList as the applicative:
λ getZipList $ Prelude.foldr (<*>) (ZipList [2,3]) [ ZipList [succ,pred], ZipList [(*2)] ]
The result is:
[5]
I'm not sure if this is what the question intended, but it seems like a natural way to fold using (<*>).
If the ziplist argument has to be a plain list, it looks impossible. This is because fold f [a1,...,an] must be well typed for every n, hence f must be a function type taking at least n arguments for every n, hence infinitely many.
However, if you use a GADT list type, in which values expose their length as a type-level natural you can achieve something similar to what you want.
{-# LANGUAGE DataKinds, KindSignatures, TypeFamilies, GADTs #-}
import Control.Applicative
-- | Type-level naturals
data Nat = Z | S Nat
-- | Type family for n-ary functions
type family Fn (n :: Nat) a b
type instance Fn Z a b = b
type instance Fn (S n) a b = a -> Fn n a b
-- | Lists exposing their length in their type
data List a (n :: Nat) where
Nil :: List a Z
Cons :: a -> List a n -> List a (S n)
-- | General <*> applied to a list of arguments of the right length
class Apply (n :: Nat) where
foldF :: Applicative f => f (Fn n a b) -> List (f a) n -> f b
instance Apply Z where
foldF f0 Nil = f0
instance Apply n => Apply (S n) where
foldF fn (Cons x xs) = foldF (fn <*> x) xs
test :: [(Integer,Integer,Integer)]
test = foldF (pure (,,)) (Cons [10,11] (Cons [20,21] (Cons [30,31] Nil)))
-- Result: [(10,20,30),(10,20,31),(10,21,30),(10,21,31)
-- ,(11,20,30),(11,20,31),(11,21,30),(11,21,31)]
In general folding (<*>) is tricky because of types, as others have mentioned. But for your specific example, where your ziplist elements are all of the same type, you can use a different method and make your calculation work with a small change to f to make it take a list argument instead of single elements:
import Data.Traversable
import Control.Applicative
f = (\[x,y,z] -> x*y+z)
ziplist = [[4,7],[6,9],[5,10]]
fun1 f l = getZipList $ f <$> traverse ZipList l
It's even possible to achieve this with just Data.List and Prelude functions:
fun1 f = map f . transpose
To do this, I want to recursively apply <*> like
foldx (h:w) = h <*> foldx w
foldx (w:[]) = w
but it seems impossible to make <*> recursive.
I think you're getting confused over left- vs. right-associativity. danidiaz reformulates this in terms of foldr (<*>), which is quite useful for this analysis. The documentation gives a useful definition of foldr in terms of expansion:
foldr f z [x1, x2, ..., xn] == x1 `f` (x2 `f` ... (xn `f` z) ...)
So applying that to your case:
foldr (<*>) z [x1, x2, ..., xn] == x1 <*> (x2 <*> ... (xn <*> z) ...)
Note the parens. <*> is left-associative, so the foldr expansion is different from:
x1 <*> x2 <*> ... <*> xn <*> z == ((... (x1 <*> x2) <*> ...) <*> xn) <*> z
Let's think also a bit more about what foldr (<*>) means. Another way of thinking of this is to rewrite it just slightly:
flip (foldr (<*>)) :: Applicative f :: [f (a -> a)] -> f a -> f a
Types of the form (a -> a) are often called endomorphisms, and they form a monoid, with composition as the operation and id as the identity. There's a newtype wrapper in Data.Monoid for these:
newtype Endo a = Endo { appEndo :: a -> a }
instance Monoid (Endo a) where
mempty = id
mappend = (.)
This gives us yet another way to think of foldr (<*>), by formulating it in terms of Endo:
toEndo :: Applicative f => f (a -> a) -> Endo (f a)
toEndo ff = Endo (ff <*>)
And then what foldr (<*>) does, basically, is reduce this monoid:
foldrStar :: Applicative f => [f (a -> a)] -> Endo (f a)
foldrStar fs = mconcat $ map toMonoid fs
what you have is equivalent to zipWith3 (\x y z -> x*y+z) [4,7] [6,9] [5,10].
it's impossible to foldl the <*> (and you do need foldl as <*> associates to the left) because foldl :: (a -> b -> a) -> a -> [b] -> a i.e. it's the same a in a -> b -> a, but when you apply your ternary function on first list of numbers, you get a list of binary functions, and then unary functions at the next step, and only finally, numbers (all different types, then):
>> let xs = map ZipList [[4,7],[6,9],[5,10]]
>> getZipList $ pure (\x y z -> x*y+z) <*> (xs!!0) <*> (xs!!1) <*> (xs!!2)
[29,73]
>> foldl (<*>) (pure (\x y z -> x*y+z)) xs
<interactive>:1:6:
Occurs check: cannot construct the infinite type: b = a -> b
Expected type: f (a -> b)
Inferred type: f b
In the first argument of `foldl', namely `(<*>)'
In the expression: foldl (<*>) (pure (\ x y z -> x * y + z)) xs
>> :t foldl
foldl :: ( a -> b -> a ) -> a -> [b] -> a
>> :t (<*>)
(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b -- f (a -> b) = f b
The answer by chi addresses this, but the arity is fixed (for a particular code). In effect, what that answer really does is defining (a restricted version of) zipWithN (well, here, when used with the ZipList applicative - obviously, it works with any applicative in general) for any N (but just for the a -> a -> a -> ... -> a type of functions), whereas e.g.
zipWith7 :: (a -> b -> c -> d -> e -> f -> g -> h) ->
[a] -> [b] -> [c] -> [d] -> [e] -> [f] -> [g] -> [h]
(in other words, zipWith3 (,,) [10,11] ([20,21]::[Integer]) ([30,31]::[Int]) works).

combine-function with list-comprehension

I've a simple question:
combine :: (a -> b -> c) -> [a] -> [b] -> [c]
combine f (a:as) (b:bs) = f a b : combine f as bs
combine _ _ _ = [ ]
This is recursive. Now i want to use a list comprehension to solve the same problem:
combine f (x:xs) (y:ys) = [ f x y | x <- (x:xs), y <- (y:ys) ]
But my problem is the combination of elements. I only want to combine x1 y1, x2 y2, xs ys ... not x1 y1, x1 y2, x1 ys, x2 y1, x2 y2, ......
Thank you!
What you need is a parallel list compehension. To be able to use it you need to specify a ParallelListComp pragma to the compiler:
{-# LANGUAGE ParallelListComp #-}
combine :: (a -> b -> c) -> [a] -> [b] -> [c]
combine f xs ys = [ f x y | x <- xs | y <- ys ]
Compiler desugars it to an application of zipWith:
combine :: (a -> b -> c) -> [a] -> [b] -> [c]
combine f xs ys = zipWith f xs ys
Which is actually what your function is, so:
combine :: (a -> b -> c) -> [a] -> [b] -> [c]
combine = zipWith
Since list comprehension usually gives Cartesian product, you can also try ZipList from Control.Applicative
GHCi> :m + Control.Applicative
GHCi> :info ZipList
newtype ZipList a = ZipList {getZipList :: [a]}
-- Defined in `Control.Applicative'
instance Functor ZipList -- Defined in `Control.Applicative'
instance Applicative ZipList -- Defined in `Control.Applicative'
GHCi> let combine f xs ys = getZipList $ f <$> ZipList xs <*> ZipList ys
GHCi> :t combine
combine :: (a2 -> a1 -> a) -> [a2] -> [a1] -> [a]
GHCi> combine (-) [10,9..] [1..10]
[9,7,5,3,1,-1,-3,-5,-7,-9]
GHCi>
Don't fear of ZipList, it just wraps a list, you can convert a list into ZipList and convert it back using getZipList.
This chapter in LYAH gives you some explanation about how to use it, have fun!
BTW, you can use a bare list in the example above, which gives you the Cartesian product:
GHCi> let combine1 f xs ys = f <$> xs <*> ys
GHCi> :t combine1
combine1 :: Applicative f => (a1 -> a -> b) -> f a1 -> f a -> f b
GHCi> combine (-) [10,9..1] [1..10]
[9,8,7,6,5,4,3,2,1,0,8,7,6,5,4,3,2,1,0,-1,...]
GHCi>
As you can see, there are two ways of merging two lists together, one is to think elements in a list as possible results, if you take one possible value from xs=[1,2], and another possible value from ys=[3,4] to make a tuple, you will end up with all possibilities: [(1,3),(1,4),(2,3),(2,4)], this is basically what [(x,y)| x <- xs, y <-ys] is saying. But there is also another way of merging two lists: every time you take one element simultaneously from two lists, and make a pair, until one of the list reaches its end, this is how ZipList get merged together.
this would be my poor answer
kk :: ( a -> b -> c) -> (a,b) -> c
kk f (x,y) = f x y
combineFunk :: (a -> b -> c) -> [a] -> [b] -> [c]
combineFunk f xs ys = [cs | (a,b) <- zip xs ys , let cs = kk f (a,b) ]

Define map using foldl instead of foldr and an expr

I did it like this – but it is not working:
ma f [] = []
ma f (xs) = foldl (\y ys -> ys++(f y)) [] xs
foldl :: (a -> b -> a) -> a -> [b] -> a
foldr :: (a -> b -> b) -> b -> [a] -> b
Why is there a difference in the function that fold takes. I mean, (a -> b -> a) and (a -> b -> b)?
Is it possible to define map using foldl?
I have another question
I have an expr.
map (:)
I want to know what it will do. I tried to test it but i only get error.
type is map (:) :: [a] -> [[a] -> [a]]
I tried to send in a list of [1,2,3]
Not if you want it to work for infinite as well as finite lists. head $ map id (cycle [1]) must return 1.
foldling over an infinite list diverges (never stops), because foldl is recursive. For example,
foldl g z [a,b,c] = g (g (g z a) b) c
Before g gets a chance to ignore its argument, foldl must reach the last element of the input list, to construct the first call to g. There is no last element in an infinite list.
As for your new question, here's a GHCi transcript that shows that map (:) is a function, and map (:) [1,2,3] is a list of functions, and GHCi just doesn't know how to Show functions:
Prelude> map (:)
<interactive>:1:0:
No instance for (Show ([a] -> [[a] -> [a]]))
Prelude> :t map (:)
map (:) :: [a] -> [[a] -> [a]]
Prelude> map (:) [1,2,3]
<interactive>:1:0:
No instance for (Show ([a] -> [a]))
Prelude> :t map (:) [1,2,3]
map (:) [1,2,3] :: (Num a) => [[a] -> [a]]
Prelude> map ($ [4]) $ map (:) [1,2,3]
[[1,4],[2,4],[3,4]]
Prelude> foldr ($) [4] $ map (:) [1,2,3]
[1,2,3,4]
It becomes more obvious when you swap the type-variable names in one of the functions:
foldl :: (b -> a -> b) -> b -> [a] -> b
foldr :: (a -> b -> b) -> b -> [a] -> b
...because after all, what we need is the result, i.e. [a] -> b. Or, more specially, [a] -> [b], so we might as well substitute that
foldl :: ([b] -> a -> [b]) -> [b] -> [a] -> [b]
foldr :: (a -> [b] -> [b]) -> [b] -> [a] -> [b]
which leaves only one non-list item in each signature, namely the a. That's what we can apply f to, so, in the case of foldl it has to be the 2nd argument of the lambda:
foldl (\ys y -> ys ++ f y)
As Xeo remarks, this isn't done yet, because f y has type b, not [b]. I think you can figure out how to fix that yourself...
ma f [] = []
ma f (xs) = foldl (\ys y -> ys++[(f y)]) [] xs
Works but why does order of arg to lambda matter.
ma f (xs) = foldl (\y ys -> ys++[(f y)]) [] xs gives error

What's wrong with following foldl implementation?

By the task we've had to implement foldl by foldr. By comparing both function signatures and foldl implementation I came with the following solution:
myFoldl :: (a -> b -> a) -> a -> [b] -> a
myFoldl _ acc [] = acc
myFoldl fn acc (x:xs) = foldr fn' (fn' x acc) xs
where
fn' = flip fn
Just flip function arguments to satisfy foldr expected types and mimic foldl definition by recursively applying passed function.
It was a surprise as my teacher rated this answer with zero points.
I even checked this definition stacks its intermediate results in the same way as the standard foldl:
> myFoldl (\a elm -> concat ["(",a,"+",elm,")"]) "" (map show [1..10])
> "((((((((((+1)+10)+9)+8)+7)+6)+5)+4)+3)+2)"
> foldl (\a elm -> concat ["(",a,"+",elm,")"]) "" (map show [1..10])
> "((((((((((+1)+10)+9)+8)+7)+6)+5)+4)+3)+2)"
The correct answer was the following defintion:
myFoldl :: (a -> b -> a) -> a -> [b] -> a
myFoldl f z xs = foldr step id xs z
where step x g a = g (f a x)
Just asking why is my previous definition incorrect ?
Essentially, your fold goes in the wrong order. I think you didn't copy your output from foldl correctly; I get the following:
*Main> myFoldl (\ a elem -> concat ["(", a, "+", elem, ")"]) "" (map show [1..10])
"((((((((((+1)+10)+9)+8)+7)+6)+5)+4)+3)+2)"
*Main> foldl (\ a elem -> concat ["(", a, "+", elem, ")"]) "" (map show [1..10])
"((((((((((+1)+2)+3)+4)+5)+6)+7)+8)+9)+10)"
so what happens is that your implementation gets the first element--the base case--correct but then uses foldr for the rest which results in everything else being processed backwards.
There are some nice pictures of the different orders the folds work in on the Haskell wiki:
This shows how foldr (:) [] should be the identity for lists and foldl (flip (:)) [] should reverse a list. In your case, all it does is put the first element at the end but leaves everything else in the same order. Here is exactly what I mean:
*Main> foldl (flip (:)) [] [1..10]
[10,9,8,7,6,5,4,3,2,1]
*Main> myFoldl (flip (:)) [] [1..10]
[2,3,4,5,6,7,8,9,10,1]
This brings us to a deeper and far more important point--even in Haskell, just because the types line up does not mean your code works. The Haskell type system is not omnipotent and there are often many--even an infinite number of--functions that satisfy any given type. As a degenerate example, even the following definition of myFoldl type-checks:
myFoldl :: (a -> b -> a) -> a -> [b] -> a
myFoldl _ acc _ = acc
So you have to think about exactly what your function is doing even if the types match. Thinking about things like folds might be confusing for a while, but you'll get used to it.

Resources