I am trying to write zipWith function using zip and list comprehension. I need to zip the two lists after the function is applied. However I don't know where to use the list comprehension.
I tried doing two list comprehensions for each list.
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f xs ys = zip [f x | x <- xs] [f y | y <- ys]
I am expecting the function to be identical to zipWith, however it is not loading and giving error:
Occurs check: cannot construct the infinite type:
c ~ (b -> c, b -> c)
Expected type: [c]
Actual type: [(b -> c, b -> c)]
• In the expression: zip [f x | x <- xs] [f y | y <- ys]
In an equation for ‘zipWith'’:
zipWith' f xs ys = zip [f x | x <- xs] [f y | y <- ys]
• Relevant bindings include
ys :: [b] (bound at tutorial5.hs:166:15)
f :: a -> b -> c (bound at tutorial5.hs:166:10)
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
(bound at tutorial5.hs:166:1)
|
166 | zipWith' f xs ys = zip [f x | x <- xs] [f y | y <- ys]
Well, there are a few problems here. At the top level, think about the signature of
zip :: [a] -> [b] -> [(a,b)]: there's no way that it can return a[c]wherecis not a tuple, so you don't wantzipto be the outer function call in your newzipWith. Your type error is arising from GHC noticing that it needs to forcecto be a tuple of things with elements whose types containcthemselves (sincefapplied to anything will always have typeb -> c).Your list comprehensions are also basically the same thing as
map f xsandmap f ys. The second of these can't typecheck, since each element ofysis ab, and you can't applyfto ab(its first argument is ana).You instead could start by zipping the input lists to get
[(a,b)], and then using a list comprehension to runfon each pair:Or, with
mapanduncurryinstead of a list comprehension:Or, using the GHC parallel list comprehension extension (
-XParallelListComp), explicitly designed to imitatezip:As mentioned above, you can't really do the
ziplast, since it'll produce tuples. You could do something likeWhich applies
fto the elements of the first list (in[f x | x <- xs], or alternativelymap f xs), zips this list of partially applied functions with the list of second arguments, and then applies the partial functions to their corresponding second arguments in the outer comprehension, but it's a bit of a roundabout way to do this.