2

Really, I'd like to figure out the more general solution of composing a fold with a zipwith in a single function point free.

zWMult :: Num c => [c] -> [c] -> [c]
zWMult = zipWith (*)

foldPl0 :: Num c => [c] -> c
foldPl0 = foldl (+) 0

I get the correct solution when I use arguements

dPr x y = foldPl0 (zWMult x y)
dPr x y = foldPl0 $ zWMult x y

But have no idea how to naturally compose these without arguments. Both these fail:

Prelude> :{
Prelude| let dPr1 :: Num c => [c] -> [c] -> c
Prelude|     dPr1 = fPl0 $ zWMult
Prelude| :}

<interactive>:171:19:
Couldn't match expected type ‘[[c] -> [c] -> c]’
            with actual type ‘[Integer] -> [Integer] -> [Integer]’
Relevant bindings include
  dPr1 :: [c] -> [c] -> c (bound at <interactive>:171:5)
Probable cause: ‘zWMult’ is applied to too few arguments
In the second argument of ‘($)’, namely ‘zWMult’
In the expression: fPl0 $ zWMult

Prelude> :{
Prelude| let dPr1 :: Int c => [c] -> [c] -> c
Prelude|     dPr1 = foldPl0 $ zWMult
Prelude| :}

<interactive>:11:13:
‘Int’ is applied to too many type arguments
In the type signature for ‘dPr1’: dPr1 :: Int c => [c] -> [c] -> c

As well as

dPr2 = foldPl0 . zWMult

Edit: Cool, one should cross reference this post if you want a more complete understanding of the solution below. What does (f .) . g mean in Haskell?

  • 1
    You can use http://pointfree.io/ to convert to pointfree. Use with care, since pointfree easily turns into obfuscation. – chi Mar 26 '18 at 11:53

1 Answers1

6

Starting with a simpler version:

dot x y = sum (zipWith (*) x y)

you can convert \x -> f (g x) with function composition to f . g:

dot x = sum . zipWith (*) x

f . g means (.) f g:

dot x = (sum.) (zipWith (*) x)

and you can convert \x -> f (g x) with function composition to f . g:

dot = (sum.) . zipWith (*)
Ry-
  • 218,210
  • 55
  • 464
  • 476
  • 3
    While this `(f .) . g` idiom is a common point-free way to compose a 1-argument function with a 2-argument one, it can also be written `fmap sum . zipWith (*)` or even `fmap sum <$> zipWith (*)` which I find slightly more descriptive than partial application of `(.)`, since while `fmap` in the `(->)` functor is equivalent to composition, it illustrates the fact that you’re “mapping” over the result of a function by ignoring arguments (one `fmap` for each argument). – Jon Purdy Mar 26 '18 at 01:14