So I have this haskell code, and I understand half of it, but I can't get my head around this \x ->
here:
testDB :: Catalogue
testDB = fromList [
("0265090316581", ("The Macannihav'nmor Highland Single Malt", "75ml bottle")),
("0903900739533", ("Bagpipes of Glory", "6-CD Box")),
("9780201342758", ("Thompson - \"Haskell: The Craft of Functional Programming\"", "Book")),
("0042400212509", ("Universal deep-frying pan", "pc"))
]
-- Exercise 1
longestProductLen :: [(Barcode, Item)] -> Int
longestProductLen = maximum . map (\(x, y) -> length $ fst y)
formatLine :: Int -> (Barcode, Item) -> String
formatLine k (x, (y1, y2)) = x ++ "..." ++ y1 ++ (take (k - length y1) (repeat '.')) ++ "..." ++ y2
showCatalogue :: Catalogue -> String
showCatalogue c = foldr (++) "" $ map (\x -> (formatLine (longestProductLen (toList testDB)) x) ++ "\n") $ toList c
I understand that longestProductLen
returns and integer meaning the longest title in testDB
and then it uses this integer to match k
in formatLine
, but I can't understnad how it matches (Bardcode, Item)
and I guess it has something to do with \x ->
, if it does can you please explain how it does that?
Thank you!
The expression in the parentheses is a lambda function. The backslash is used as the nearest ASCII equivalent to the Greek letter lambda (λ). This lambda function takes two arguments, x and str , and it evaluates to "x + read str".
(->) is often called the "function arrow" or "function type constructor", and while it does have some special syntax, there's not that much special about it. It's essentially an infix type operator. Give it two types, and it gives you the type of functions between those types.
() is very often used as the result of something that has no interesting result. For example, an IO action that is supposed to perform some I/O and terminate without producing a result will typically have type IO () .
The ++ operator is the list concatenation operator which takes two lists as operands and "combines" them into a single list.
The syntax
function x y = <body>
Is equivalent to
function = \x y -> <body>
And is called a lambda or anonymous function. The compiler actually turns all your functions into assignments of lambda functions (the second form) since it's just giving a function value (functions are values in Haskell) a name.
If you see it given as an argument to another function like map
:
map (\x -> x + 1) [1, 2, 3]
This is semantically equivalent to
map add1 [1, 2, 3] where add1 x = x + 1
Lambdas can perform arbitrary pattern matching on their arguments, too. Also, if you have a definition like
fib 0 = 1
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)
This is equivalent to
fib = \n -> case n of
0 -> 1
1 -> 1
n -> fib (n - 1) + fib (n - 2)
Because the compiler will first translate the multiple pattern matching into a case statement, then convert it to assigning a lambda to a name (in this case assigning the lambda to the name fib
).
That's Haskell's syntax for lambda abstraction. The Haskell
\x -> e
corresponds to the mathematical
λx.e
In this case,
\(x, y) -> length $ fst y
is a function that takes a pair (x,y)
and returns the length of the first component of the pair y
. This is a slightly odd way to write the expression; it would be better to write it as
\(x, (y1, y2)) -> length y1
or as
length . fst . snd
for consistency.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With