Reading M. Lipovach “Learn Haskell in the name of good!”, I initially did not understand how
partial application differs from
currying . Spent some time on the analysis of this issue and sketched himself a "cheat sheet" on the designated topic.
In Haskell, functions without parameters are called
definitions (definitions) or
names .
func :: String func = "Haskell"
Functions cannot accept more than one parameter. If a function takes several parameters, then
in fact it is a function with
one parameter and
returns another function that also accepts only one parameter and returns some result (
another function or a specific value ). If the function has such a signature:
func :: Int -> Double -> Char -> Bool
then Haskell interprets it as follows:
func :: Int -> (Double -> (Char -> Bool))
Those. the func function takes an Int type parameter and
returns a new function that takes a
regular Double parameter and returns
another new function that takes a Char parameter and returns a Bool value.
Transforming a function from many arguments into a function that takes its arguments one by one is called currying. Haskell automatically curries all functions that take more than one parameter. Due to the currying, it becomes possible to
partially apply the functions, as well as create
sections . In turn, partial application makes it possible to have
pointless notation .
Note
In Haskell, there is no such thing as a partial use of a function. There is an application function (without "partially"). If we say (for convenience of perception) that the function f :: Int -> Int -> Int
has two arguments (which, from a technical point of view, is not correct), then we can also say (again for convenience of perception) that f 5
is a partially applied function (which is also not technically correct).
Example
func :: (Num a) => a -> a -> a -> a func abcd = a + b + c + d
ghci
Partial application:
λ: let n = func 2 3 λ: let m = n 10 λ: let g = m 7 λ: g 22
Sections:
λ: let a = (/2) λ: a 10 5.0 λ: let b = (15/) λ: b 5 3.0
Current notation:
odd' :: Integral a => a -> Bool odd' = odd
ghci:
λ: odd' 5 True λ: odd' 4 False
Currying and currying
In the standard Data.Tuple module, the following functions are defined, among other things:
curry :: ((a, b) -> c) -> a -> b -> c uncurry :: (a -> b -> c) -> (a, b) -> c
The curry function converts a non-curried function to a curried function.
The uncurry function converts a curried function to a non-curried function.
Example
msg :: Int -> Bool -> String msg n True = show $ n `div` 2 msg n _ = show $ n * 2
ghci
λ: let n = msg λ: let m = uncurry n λ: :tn n :: Int -> Bool -> String λ: :tm m :: (Int, Bool) -> String λ: n 5 True "2" λ: m (5,True) "2" λ: let k = curry m λ: :tk k :: Int -> Bool -> String λ: k 5 True "2"