7 ms·
I'm not sure I understand the relationship between partial function and exception handling. Aren't partial functions just curried? One or more arguments are bou
by swagonomixxx 6y ago
I'm not sure I understand the relationship between partial function and exception handling. Aren't partial functions just curried? One or more arguments are bound, but not all? At least in Python, if you partial-ify a function that raises an exception, it still raises. I don't understand if the author likes that behavior or doesn't. Maybe this is some Haskell implementation detail that I'm not aware of.
Last time I wrote any non-trivial Haskell was in 2014, so a long time ago, but I found that my biggest problem with it at the time was the really huge variety of Haskell in the wild. If you're doing simple stuff, you probably stick to the prelude and you'll be happy. But if you're doing anything that's a bit complex, you'll end up seeing hundreds of mini-dialects of Haskell in the wild, so much so that I found it really difficult as a newcomer to understand code on the net. In many cases it's almost like a different language completely, what with the user-defined infix functions, tons of currying everywhere, laziness, and the like, made it very difficult to follow code paths.
- UncleMeat 6y ago"Partial function" is an overloaded term. In this context it means "a function which does not map its entire domain to an output". This means that there are some inputs which return "Bottom", which happily gets propagated through the system until it is needed as input to some function and then your application explodes. The downside here is that rather than blowing up your application immediately upon a bug it blows up your application somewhere else depending on your logic. This can be a useful thing. You can write powerful and elegant algorithms that avoid error management because the bottom values never actually get used. But most people aren't doing that and instead these are time bombs.
- codesnik 6y agowhen bottom is actually reached that point of evaluation, does haskell provide any indication on where it came from? stacktrace or something?
- cies 6y ago> This can be a useful thing. You can write powerful and elegant algorithms that avoid error management because the bottom values never actually get used. Agreed. This would be with some escape hatch function, maybe even from Unsafe. But having head in Prelude, without huge warning in the docs, without deprecation warnings, it just, well, not very Haskelly, I'd say.
- NovemberWhiskey 6y ago>Aren't partial functions just curried? One or more arguments are bound, but not all? No; a partial function is one that isn't well-defined for the whole of its domain. So, as per the article, head is a partial function because its type signature of [a] -> a implies that all arrays have a head value. But head [] does not. It's a partial function.
- mhotchen 6y agoWhat approaches and tools do Haskell developers take to guard against this? I assume in the head case a Maybe would be a better return type? But then why doesn't the Haskell core do that in the head function?
- NovemberWhiskey 6y agoIn my experience (which is quite dated at this point; my Haskell usage is back to the turn of the millennium), the usual approach was pattern matching. i.e. if you knew you were going to use a function that might not be defined you would write an alternate case. The type system isn't helping you at all there. The feeling I had was that much of the prelude stuff was there to provide for beautiful, terse examples of functional programming and less to protect a software engineer.
- mhotchen 6y agoFew interesting things in this comment, thanks! What you say makes sense; it sounds like Haskell can't literally hold my hand for me which is fair enough. I've just started my Haskell journey and the undefined paths through partial function implementation caught me by surprise. Just skimming Wikipedia it looks like I would want to use "total/strong functional programming" but apparently "total functional programming is not Turing-complete" https://en.wikipedia.org/wiki/Total_functional_programming https://en.wikipedia.org/wiki/Total_functional_programming Also found this on the Haskell site after some more googling: https://wiki.haskell.org/Partial_functions https://wiki.haskell.org/Partial_functions
- samthecoy 6y agoPartial functions are not the same thing as "partially applied functions". Partial functions means that not every element of the domain is mapped to an element of the range, for example: divTenBy :: Double -> Double divTenBy n = 10 / n If you actually call the above function you get a runtime exception. We really don't like functions that do this; they are called partial.
- a_wild_dandan 6y agoAh, so partial functions aren't onto (i.e. surjective).
- deleted 6y ago[deleted]
- curtisf 6y agoNo, they are not functions in the mathematical sense. It's not that they don't cover the output space, they don't cover the input space.
- wetmore 6y agoNot exactly, partial functions can be surjective, eg f :: Int -> Bool f 0 = True f 1 = False f n = f (n + 1) is surjective onto Bool but also partial (doesn't return for n > 1). In Haskell we say that when a function doesn't return, the output is bottom, written as ⊥. You could say that a function f : A -> B is partial if f^{-1}(B \ ⊥) is surjective.
- deleted 6y ago[deleted]
- Athas 6y agoAm I missing something subtle? Why would you get a runtime exception if you call this function?
- jsmith45 6y agoThe parent missed a part. If you call it with 0 you get an exception, because division by zero obviously.
- augusto2112 6y agoA partial function is a function where all inputs have an output. For example, calling head on an empty list will throw an exception. To make this a total function you’d need to return a Maybe instead.
- samthecoy 6y ago*not all inputs
- augusto2112 6y agoExactly, meant to say that :)
- masklinn 6y ago> I'm not sure I understand the relationship between partial function and exception handling. Aren't partial functions just curried? You're thinking "partially applied function", which uses very similar terms but means something completely unrelated. A partially applied function is a function which is applied to a subset of its formal arguments, yielding a function taking the leftover arguments. A partial function is contrasted with a total function and the term is about the relation between inputs and outputs, namely does every possible input value yield an output. The example of `first` used in the essay is pretty common because it's quite clear: given `first :: [a] -> a`, what happens if you call `first` with an empty list? Well it can't succeed, it can't just give you an `a` out of nowhere because it doesn't have anything to do that. So despite an empty array being a possible input value, there is no output for it: it is a partial function, it only partially maps its inputs to its outputs. `first :: [a] -> Maybe a` would be total: in the case of an empty input it returns `None`, otherwise it returns `Some a`.