14 ms·
Loved the concise explanations of the What. A nice extension of this would be the Why, something I usually struggle to understand. Currying as an example, I'm n
by have_faith 9y ago
Loved the concise explanations of the What. A nice extension of this would be the Why, something I usually struggle to understand. Currying as an example, I'm none the wiser as to why it's a preferable way of composing a function and it's arguments, or when either is applicable.
- hood_syntax 9y agoLet's say you have a validation function that matches a string with a given regex, and you need to use that same logic in several places, using a different regex. Currying allows you to write something like this: validate :: Regex -> String -> T validate r s = ... validateIpAddr :: String -> T validateIpAddr = validate ipRegex validateZipCode :: String -> T validateZipCode = validate zipCodeRegex And so on and so forth. It can reduce boilerplate, and lets you do stuff like map partially applied functions to functors.
- jandrese 9y agoThis doesn't really seem to save you much, since you're going from: validate(IpAddr, Regex) to validateIpAddr(Regex) I have to admit I'm a little fuzzy on why currying is desirable so there's probably something obvious I'm missing.
- taejo 9y agoIt's `validateIpAddr(String)`: the first argument is fixed. Suppose you have a list of strings, and you want to extract the ones that are IP addresses. Then you can just write filter (validate ipRegex) listOfStrings instead of filter validateIpAddr listOfStrings where validateIpAddr string = validate ipRegex string
- jandrese 9y agoWhy not just map { validate(ipRegex, $) } listOfStrings
- masklinn 9y ago> Currying as an example, I'm none the wiser as to why it's a preferable way of composing a function and it's arguments, or when either is applicable. The primary advantage of curried functions is that they're trivially partially applicable. With an uncurried function, if you have a function of two arguments and you want to apply the first but "hold off" on the second you have to wrap the thing in a new function with a single argument which will do the application later (the language may also provide a helper) whereas with curried functions, you can just apply one of the parameters: let add5 = (a) => a.map((n) => n + 5) versus let add5 = map (\n -> n + 5) This means you can very easily create "small specialisations" of very generic functions. Languages with curried functions also tend to provide features like the ability to treat operators as functions ("sections"): let add5 = map (+5) and more function composition tooling: let add5ToEven = map (+5) . filter even though these are not really intrinsic.
- mbrock 9y agoCurrying is a form of higher order function, and it's not necessarily preferable, but often just makes sense. I think it is in some way overused in Haskell for example. When your function takes five different parameters, it's unlikely that the curried style really makes sense, other than that it's just convenient and idiomatic in Haskell—in many cases you would be better off using a record type for the parameters. But if you consider for example the map function, it really makes sense to consider it a higher order function in a "curried" way. That is to say, map f makes sense on its own, because map takes a function and transforms it into a function that works on lists. So the type map :: (a -> b) -> ([a] -> [b]) is really nice, and nicer than the uncurried alternative: map :: (a -> b, [a]) -> [b] Of course they're isomorphic, but the curried one seems to definitely win in terms of elegance, and you avoid ever having to type \x -> map (f, x) or similar. I think if Haskell had really convenient named parameters, people would use currying less, but we'd still want to use the curried style for many functions that actually make sense as higher-order functions.
- jethrolarson 9y agoI considered that quite a lot while contributing to the repo but it's super easy to go overboard and turn a single definition into many pages of explanation. I feel that this glossary should be just a taste of the concepts in a shallow, practical, and hand-wavy way. To be honest, each concept like "partial application", or "applicative functors" deserves an hour-long lecture or more but if the content went that deep I think it'd lose its current audience.