Home > Mobile >  Haskell: for every even appearance in an array, concatenate an int to the final list
Haskell: for every even appearance in an array, concatenate an int to the final list

Time:10-30

I'm currently trying to write a function that takes as arguments an Int and an array of Ints and for every even value in the array, it concatenates the Int to the final array. So, something like this: f 3 [1,2,3,4,5,6] = [1,2,3,3,4,3,5,6,3]

This is the code I imagined would work (I'm just beginning so sorry if it's bad):

f :: Int -> [Int] -> [Int]
f(x,[]) = []
f(x,y) 
    |even head(y) = (head(y)    [x]    f(x,drop 1 y)
    |otherwise = head(y)    f(x,(drop 1 y))

The error I'm getting is "Couldn't match expected type of 'Int' with actual type (a3, [[a3]])'. I understand the parameters types are mismatched, but I'm not sure how a proper syntax would look like here

CodePudding user response:

You use (x, []), so that means the input type would be a tuple, so f :: (Int, [Int]) -> [Int].

I would also use pattern matching instead of head and tail, so:

f :: Int -> [Int] -> [Int]
f _ [] = []
f x (y:ys)
    | even y = y : x : f x ys
    | otherwise = y : f x ys

You can also generalize the type signature, and work with an inner function to avoid passing the x each time:

f :: Integral a => a -> [a] -> [a]
f x = go
  where go [] = []
        go (y:ys)
          | even y = y : x : go ys
          | otherwise = y : go ys

CodePudding user response:

Another way of looking at this would be using a right fold to insert the desired element after even numbers.

f :: Int -> [Int] -> [Int]
f x lst = foldr (\y i -> if even y then y:x:i else y:i) [] lst

Which we can simplify to:

f :: Int -> [Int] -> [Int]
f x = foldr (\y i -> if even y then y:x:i else y:i) []

Note that without specifying the type, the more general inferred type of f would be:

f :: (Foldable t, Integral a) => a -> t a -> [a]
  • Related