I’ll give my newbie perspective.
I too, got a bit of an “allergic” reaction when I first stumbled upon partial functions in Haskell. That’s because I came from Elm, that showed me that I could express programs in a disciplined way, to avoid runtime errors.
However, I since found that there are rare cases where partial functions are useful, and not having them would be a hindrance.
Example 1:
See this algorithm that wants to extract the first and last item of a list in a flip-flop fashion, while still keeping things performant considering the usage of linked lists under the hood.
{- |
>>> arrange []
[]
>>> arrange [1]
[1]
>>> arrange [1,2]
[1,2]
>>> arrange [1,2,3]
[1,3,2]
>>> arrange [1,2,3,4]
[1,4,3,2]
>>> arrange [1,2,3,4,5]
[1,5,4,2,3]
>>> arrange [1,2,3,4,5,6]
[1,6,5,2,3,4]
-}
arrange :: [a] -> [a]
arrange lst = aux lst (reverse lst) (length lst)
where
aux fwd bwd len
| len == 0 = []
| len == 1 = [head fwd]
| otherwise = head fwd : head bwd : aux (tail bwd) (tail fwd) (len - 2)
I found this algorithm really cool. While I did find a way to express the same computation without using unsafe functions, if you look at it you have to ask yourself “What’s wrong with it?”.
Well, I don’t think there’s anything “wrong” with it, I think we may have simply reached the limit of a type system.
Example 2:
So you probably know about the function fold
, but how about its twin brother unfold
, that instead generates a list.
As you can see below, I re-implemented map
with unfold
+ using unsafe/partial functions.
{- |
>>> map' f = unfold null (f . head) tail
>>> map' toUpper "mapping"
"MAPPING"
-}
unfold :: (a -> Bool) -> (a -> b) -> (a -> a) -> a -> [b]
unfold test h t x
| test x = []
| otherwise = h x : unfold test h t (t x)
Is the concept of unfolding unsound? Again, I feel here we’re reaching the limit of the type system. Which is something I’ve been wondering about (what does expressing computation with partial functions actually mean?).
So, to sum up, I think partial functions are ok/useful but in closing:
With great power comes great responsibility
Anyhow, hope that helps ![:laughing: :laughing:](https://discourse.haskell.org/images/emoji/twitter/laughing.png?v=10)