Home > Mobile >  Refactoring Haskell lambda functions
Refactoring Haskell lambda functions

Time:03-18

I have a lambda function ((:) . ((:) x)) that I am passing to foldr like so: foldr ((:) . ((:) x)) [] xs where xs is a 2d list. I would like to refactor to make it clearer (so I can better understand it). I imagine it would be done like so:

foldr (\ element acc -> (element:acc) . (x:acc)) [] xs

But this gives me the error:

ex.hs:20:84: error:
    • Couldn't match expected type ‘a0 -> b0’ with actual type ‘[[a]]’
    • Possible cause: ‘(:)’ is applied to too many arguments
      In the second argument of ‘(.)’, namely ‘(x : acc)’
      In the expression: (element : acc) . (x : acc)
      In the first argument of ‘foldr’, namely
        ‘(\ element acc -> (element : acc) . (x : acc))’
    • Relevant bindings include
        acc :: [[a]] (bound at ex.hs:20:60)
        element :: [a] (bound at ex.hs:20:52)
        xs :: [[a]] (bound at ex.hs:20:30)
        x :: [a] (bound at ex.hs:20:28)
        prefixes :: [a] -> [[a]] (bound at ex.hs:20:1)
   |
20 | prefixes = foldr (\x xs -> [x] : (foldr (\ element acc -> (element:acc) . (x:acc)) [] xs)) []
   |  

Edit: My all relevant code surrounding this snippet is

prefixes :: Num a => [a] -> [[a]]
prefixes = foldr (\x acc -> [x] : (foldr ((:) . ((:) x)) [] acc)) []

and its invocation is:

prefixes [1, 2, 3]

How can I refactor the lambda ((:) . ((:) x)) to include both its arguments?

CodePudding user response:

You can step-by-step convert it to a lambda.

(:) . ((:) x)
\y -> (:) (((:) x) y)   -- definition of (.)
\y -> (:) (x : y)       -- rewrite second (:) using infix notation
\y z -> (:) (x : y) z   -- add another parameter
\y z -> (x : y) : z     -- rewrite first (:) using infix notation
  • Related