📜 ⬆️ ⬇️

A little bit about currying in Haskell

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" 

')

Source: https://habr.com/ru/post/249241/


All Articles