A bit about Haskell Currying

    Reading M. Lipovac “Study Haskell for Good!”, At first I did not understand how partial application differs from currying . Spent some time analyzing this issue and scribbled a "cheat sheet" on the topic.

    In Haskell, functions without parameters are called definitions or names .
    func :: String
    func = "Haskell"

    Functions cannot take 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 takes only one parameter and returns some result ( another function or a specific value ). if the function has the following signature:
    func :: Int -> Double -> Char -> Bool

    then Haskell interprets it as follows:
    func :: Int -> (Double -> (Char -> Bool))

    Those. the func function takes an argument of type Int and returns a new function that takes the next argument - of type Double and returns another new function that takes an argument of type Char and returns a value of type Bool.
    Converting a function from many arguments to a function that takes its arguments one at a time is called currying. Haskell automatically curries all functions that take more than one parameter. It is thanks to currying that partial application of functions becomes possible , as well as the creation of sections . In turn, partial application makes possible the existence of pointless notation .

    Note


    There is no such thing as a partial use of a function in Haskell . There is an application of the function (without "partially"). If we say (for convenience of perception) that a function f :: Int -> Int -> Inthas two arguments (which is technically not correct), then we can say the same (again for convenience of perception) that f 5this is a partially applied function (which is also not will be technically correct).

    Example


    func :: (Num a) => a -> a -> a -> a
    func a b c d = 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

    Pointless notation:
    odd' :: Integral a => a -> Bool
    odd' = odd

    ghci:
    λ: odd' 5
    True
    λ: odd' 4
    False


    Currying and Decarring


    The following functions are defined in the standard Data.Tuple module:
    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 an uncurried 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
    λ: :t n
    n :: Int -> Bool -> String
    λ: :t m
    m :: (Int, Bool) -> String
    λ: n 5 True
    "2"
    λ: m (5,True)
    "2"
    λ: let k = curry m
    λ: :t k
    k :: Int -> Bool -> String
    λ: k 5 True
    "2"

    Also popular now: