Haskell convert "case of" statement to tail recursive code - haskell

I need help.
I have a function of that form
myFunction = case myFunction of
(Nothing) -> (Just)
(Just) -> (Just)
I want to make it tail recursive.
How would one do it ?
I understand that the fact we have a different statement according to the return of the recursive call makes it difficult (reason I need help ^^).
I can give the original function, but I'm rather looking for a more general solution.
Thanks in advance
Edit: Actual code:
myFunction :: MyTree x -> (x, Maybe(MyTree x))
myFunction = (x, Nothing)
myFunction (MyNode left right) = case myFunction left of
(x, Nothing) -> (x, Just right)
(x, Just left2) -> (x, Just (Node left2 right))

I'll assume you defined
data MyTree x = MyLeaf x | MyNode (MyTree x) (MyTree x)
and meant
myFunction :: MyTree x -> (x, Maybe(MyTree x))
myFunction (MyLeaf x) = (x, Nothing)
myFunction (MyNode left right) = case myFunction left of
(x, Nothing) -> (x, Just right)
(x, Just left2) -> (x, Just (MyNode left2 right))
Which is a function that pulls out the leftmost leaf and sews the corresponding right branch in where it was.
You ask how to make this tail recursive. Why is that? In some (strict) languages, tail recursive code is more efficient, but Haskell uses lazy evaluation, which means it doesn't matter how late the recursive calls happen, but rather how early they produce output. In this case, the head recursive case myFunction left of zooms right down the tree until it finds that leftmost leaf, you can't get to it any quicker. However, on the way back up, it does pass the x around a bit rather than returning immediately, but it also sews all the right branches back on at the appropriate plave without any bookkeeping, which is the joy of using recursion on a recursive data structure.
See this question about why tail recursion isn't the most important thing for efficiency in Haskell.
Three classic things to do to a binary tree with data at the nodes are:
1. pre-order traversal (visit the current node first then the left subtree then right) - doubly tail recursive
2. in-order traversal (visit left subtree, then current node, then right) - head and tail recursive
3. post-order traversal (visit left and right subtrees before the current node) - doubly head recursive.
Post order sounds worryingly head recursive to someone not used to lazy evaluation, but it's an efficient way to sum the values in your tree, for example, particularly if you make sure the compiler knows it's strict.
As always, the best algorithms give the fastest results, and you should compile with -O2 if you want optimisations turned on.

These have to match.
myFunction = ...
myFunction (MyNode left right) = ...
They don't match. You can't use them together. Why? One of them takes zero arguments, the other one takes one argument. They must take the same number of arguments. If you need to ignore an argument, use _. Note that the version that uses _ has to be after the version that doesn't use _.
myFunction :: MyTree x -> Maybe (MyTree x)
myFunction (MyNode left right) =
case myFunction left of
Nothing -> Just right
Just left2 -> Just (MyNode left2 right)
myFunction _ = Nothing
I don't know what x is supposed to be in the body of your function. It's not bound to anything.
This isn't tail recursive. Not all functions can be made into tail recursive functions.
Hint
Maybe if you described what the function was supposed to do, we could help you do that.

Related

Are there ways to call two functions (one just after another) in purely functional language? (in non-io mode)

I'm trying to understand order of execution in purely functional language.
I know that in purely functional languages, there is no necessary execution order.
So my question is:
Suppose there are two functions.
I would like to know all ways in which I can call one function after another (except nested call of one function from another) (and except io-mode).
I would like to see examples in Haskell or pseudo-code.
There is no way to do what you describe, if the functions are totally independent and you don't use the result of one when you call the other.
This is because there is no reason to do this. In a side effect free setting, calling a function and then ignoring its result is exactly the same as doing nothing for the amount of time it takes to call that function (setting aside memory usage).
It is possible that seq x y will evaluate x and then y, and then give you y as its result, but this evaluation order isn't guaranteed.
Now, if we do have side effects, such as if we are working inside a Monad or Applicative, this could be useful, but we aren't truly ignoring the result since there is context being passed implicitly. For instance, you can do
main :: IO ()
main = putStrLn "Hello, " >> putStrLn "world"
in the IO Monad. Another example would be the list Monad (which could be thought of as representing a nondeterministic computation):
biggerThanTen :: Int -> Bool
biggerThanTen n = n > 10
example :: String
example = filter biggerThanTen [1..15] >> return 'a' -- This evaluates to "aaaaa"
Note that even here we aren't really ignoring the result. We ignore the specific values, but we use the structure of the result (in the second example, the structure would be the fact that the resulting list from filter biggerThanTen [1..15] has 5 elements).
I should point out, though, that things that are sequenced in this way aren't necessarily evaluated in the order that they are written. You can sort of see this with the list Monad example. This becomes more apparent with bigger examples though:
example2 :: [Int]
example2 =
[1,2,3] >>=
(\x -> [10,100,1000] >>=
(\y -> return (x * y))) -- ==> [10,100,1000,20,200,2000,30,300,3000]
The main takeaway here is that evaluation order (in the absence of side effects like IO and ignoring bottoms) doesn't affect the ultimate meaning of code in Haskell (other than possible differences in efficiency, but that is another topic). As a result, there is never a reason to call two functions "one after another" in the fashion described in the question (that is, where the calls are totally independent from each other).
Do notation
Do notation is actually exactly equivalent to using >>= and >> (there is actually one other thing involved that takes care of pattern match failures, but that is irrelevant to the discussion at hand). The compiler actually takes things written in do notation and converts them to >>= and >> through a process called "desugaring" (since it removes the syntactic sugar). Here are the three examples from above written with do notation:
IO Example
main :: IO ()
main = do
putStrLn "Hello, "
putStrLn "World"
First list example
biggerThanTen :: Int -> Bool
biggerThanTen n = n > 10
example :: String -- String is a synonym for [Char], by the way
example = do
filter biggerThanTen [1..15]
return 'a'
Second list example
example2 :: [Int]
example2 = do
x <- [1,2,3]
y <- [10,100,1000]
return (x * y)
Here is a side-by-side comparison of the conversions:
do --
m -- m >> n
n --
do --
x <- m -- m >>= (\x ->
... -- ...)
The best way to understand do notation is to first understand >>= and return since, as I said, that's what the compiler transforms do notation into.
As a side-note, >> is just the same as >>=, it just ignores the "result" of it's left argument (although it preserves the "context" or "structure"). So all definitions of >> must be equivalent to m >> n = m >>= (\_ -> n).
Expanding the >>= in the second list example
To help drive home the point that Monads are not usually impure, lets expand the >>= calls in the second list example, using the Monad definition for lists. The definition is:
instance Monad [] where
return x = [x]
xs >>= f = concatMap f xs
and we can convert example2 into:
Step 0 (what we already have)
example2 :: [Int]
example2 =
[1,2,3] >>=
(\x -> [10,100,1000] >>=
(\y -> return (x * y)))
Step 1 (converting the first >>=)
example2 =
concatMap
(\x -> [10,100,1000] >>=
(\y -> return (x * y)))
[1,2,3]
Step 2
example2 =
concatMap
(\x -> concatMap
(\y -> return (x * y))
[10,100,1000])
[1,2,3]
Step 3
example2 =
concatMap
(\x -> concatMap
(\y -> [x * y])
[10,100,1000])
[1,2,3]
So, there is no magic going on here, just normal function calls.
You can write a function whose arguments depend on the evaluation of another function:
-- Ads the first two elements of a list together
myFunc :: [Int] -> Int
myFunc xs = (head xs) + (head $ tail xs)
If that's what you mean. In this case, you can't get the output of myFunc xs without evaluating head xs, head $ tail xs and (+). There is an order here. However, the compiler can choose which order to execute head xs and head $ tail xs in since they are not dependent on each other, but it can't do the addition without having both of the other results. It could even choose to evaluate them in parallel, or on different machines. The point is that pure functions, because they have no side effects, don't have to be evaluated in a given order until their results are interdependent.
Another way to look at the above function is as a graph:
myFunc
|
(+)
/ \
/ \
head head
\ |
\ tail
\ /
xs
In order to evaluate a node, all nodes below it have to be evaluated first, but different branches can be evaluated in parallel. First xs must be evaluated, at least partially, but after that the two branches can be evaluated in parallel. There are some nuances due to lazy evaluation, but this is essentially how the compiler constructs evaluation trees.
If you really want to force one function call before the other, you can use the seq function. It takes two arguments, forces the first to be evaluated, then returns the second, e.g.
myFunc2 :: [Int] -> Int
myFunc2 xs = hxs + (hxs `seq` (head $ tail xs))
where hxs = head xs
This will force head xs to evaluate before head $ tail xs, but this is more dealing with strictness than sequencing functions.
Here is an easy way:
case f x of
result1 -> case g y of
result2 -> ....
Still, unless g y uses something from result1 and the subsequent calculations something from result2, or the pattern is such that the result must be evaluated, there is no guarantee that either of f or g are actually called, nor in what order.
Still, you wanted a way to call one function after another, and this is such a way.

mapEithers function in Haskell

How does the following function work:
mapEithers :: (a -> Either b c) -> [a] -> Either b [c]
mapEithers f (x:xs) = case mapEithers f xs of
Left err -> Left err
Right ys -> case f x of
Left err -> Left err
Right y -> Right (y:ys)
mapEithers _ _ = Right []
In the first case expression (case mapEithers f xs), how does it pattern match with Left and Right values when the function f has not be applied to the elements of the list yet.
This is classic recursion, we apply mapEithers to a sublist yielding something of the type Either b [c], if it's Left b, the we just propagate that through.
If it's Right cs. Then we apply f to the head of the list. If this yields an error, we drop everything and propagate that up, if it's Right c, then the result is Right (c : cs).
And because we need a recusive base case, an empty list is Right [].
For the record, this can be written more idiomatically with a fold. In real Haskell code, you rarely see explicit recursion. Rather, we have a bunch of functions (among other fold, replicateM, map, filter) which do the "heavy lifting" for us, and we only need to provide some parameters that customize them a little when we use them.
In your case, you have two Either values – the result from the rest of the list and the result from the current value. If both are Right you want them together in a list, and if they are Left you want to only keep the error message.
What I described can in Haskell be written as
(:) <$> f elem <*> rest
This will return the Left value if either f elem is a Left or if rest is a Left. If both are Right, it will extract the list from rest and the value from f elem and create a new list of both.
Put into a fold call, this means that mapEithers would in the real world be more likely to be written as
mapEithers f = foldr (\elem rest -> (:) <$> f elem <*> rest) (Right [])
Edit: I just realised it can be even simpler with a few additioal transformations. (My Haskell-fu isn't strong enough to be able to read this fluently though...)
mapEithers f = foldr (liftA2 (:) . f) (Right [])

Using Either correctly

So I have the following function:
chk2 :: [(Integer,Integer)] -> Either [(Integer,Integer)] (Integer,Integer)
chk2 i#((n,_):_)
| chkp (prod $ lgst i)==True = Right $ lgst i
| lgst i==i!!0 = Left $ chk2 $ (4-2,4-2):next i
| otherwise = Left $ chk2 $ next i
where prod (a,b) = a*b
lgst = foldl1 (\(a,b) (c,d) -> if prod (a,b) > prod (c,d) then (a,b) else (c,d))
next t = map (\(a,b) -> if (a,b)==lgst t then (a-1,b+1) else (a,b)) t
along with this error:
runhugs: Error occurred
ERROR "4/4.hs":14 - Type error in explicitly typed binding
*** Term : chk2
*** Type : [(Integer,Integer)] -> Either (Either [(Integer,Integer (Integer,Integer)) (Integer,Integer)
*** Does not match : [(Integer,Integer)] -> Either [(Integer,Integer)] (Integer,Integer)
I'm trying to get this function to either end up with an (a,b) i.e. first guard or [(a,b)] i.e. the latter two guards. The basic problem is in the latter two guards.. if I take out the recursion, everything works fine, but I'm not sure how to define the type signature when returning the function itself.
The problem is with how you recurse.
According to the type of chk2, chk2 $ next i is of type Either [(Integer,Integer)] (Integer,Integer). Left is of type b -> Either b a, so Left $ chk2 $ next i is of type Either (Either [(Integer,Integer)] (Integer,Integer)) a for some unspecified type a.
Left $ chk2 $ (4-2,4-2):next i has a similar problem.
To fix, you need to decide how you want to handle the recursive value.
Easy fix:
| lgst i==i!!0 = chk2 $ (4-2,4-2):next i
| otherwise = chk2 $ next i
However, I doubt this is what you want, since it means all your results will be Right.
I'm not sure how to do what you want, because I'm not sure what you want.
What does a list result mean? What does a non-list result mean?
What you probably want to do is pattern match the result of the recursion, transforming Right pair -> Left [pair], perhaps appending some other result to the front.
As an example, I'll construct a recursive function with a similar type signature. Let foo be a function that takes a list of integers, and:
if the first element of the list is the maximum of the whole list, returns that element
otherwise, return a subsequence of the list, where each is the maximum of all the elements between it and the next element in the subsequence (or the end)
To do this:
foo :: [Integer] -> Either [Integer] Integer
foo [] = Left []
foo (x:xs) = case foo xs of
Left ys -> if all (<=x) ys
then Right x
else let (_,ys') = break (>x) ys in Left (x:ys')
Right y -> if x >= y
then Right x
else Left [x,y]
Note how I use case to pattern match on the result of the recursive call to foo.
To solve Euler #4, yours seems to be a very awkward style for Haskell. It's usually a bad idea to try and "port" code from other languages into Haskell, since the paradigm for Haskell is so very different.
You'll find a very clean, sensible solution to Euler #4 that uses list comprehensions at the Haskell Wiki. Certainly not the only solution, but it is at least 20x as readable as your current code. No offense.
I (and tons of other Haskellers) highly recommend Learn You a Haskell and Real World Haskell for learning how to approach problems the Haskell way, which in my experience is usually to create small, simple helper methods and compose them into a solution.

Common recursion pattern

I'm getting used to Haskell's higher-order functions. Usually I can replace explicit patterns of recursion with functions like map, fold, and scan. However, I often run into the following recursion pattern which I don't understand how to express using higher-order functions:
f (x:[]) = k x
f (x:xs) = g x (f xs)
For instance, suppose I am representing analytic tableaux. Then I create a data type such as:
data Tableau = N Expr | S Expr (Tableau) | B Expr (Tableau) (Tableau)
If I want to convert a list of Exprs into a tableau structure, I want a function part of which might resemble:
f (x:[]) = N x
f (x:xs) = S x (f xs)
Now, I see three options: (1) create a function which decides, given a tableau and a list, whether the next branch in the tableau should be an S or N (or B, but we'll ignore that case); (2) use a higher-order function to encapsulate the recursion pattern of f; (3) use a function like f.
What would the best option be?
I'd most probably use the following:
f xs = foldr g (k (last xs)) (init xs)
It basically means that the end of the list is replaced by k x when folding. Thanks to lazy evaluation present everywhere, it works even for infinite lists.
There are two other solutions - adding empty case and using Maybe.
A) adding empty case:
It would be best if f [] was well-defined. Then, you could write the definition as
f [] = c
f (x:xs) = g x (f xs)
which is f = foldr g c. For example, if you change
data Tableau = N Expr | S Expr Tableau | B Expr Tableau Tableau
to
data Tableau = N | S Expr Tableau | B Expr Tableau Tableau
then you can represent single-element tableaux as S expr N, and the function is defined as one-liner
f = foldr S N
It's the best solution as long the empty case makes sense.
B) use Maybe:
On the other hand, if f [] cannot be sensibly defined, it's worse.
Partial functions are often considered ugly. To make it total, you can use Maybe. Define
f [] = Nothing
f [x] = Just (k x)
f (x:xs) = Just (g x w)
where Just w = f xs
It is a total function - that's better.
But now you can rewrite the function into:
f [] = Nothing
f (x:xs) = case f xs of
Nothing -> Just (k x)
Just w -> Just (g x w)
which is a right fold:
addElement :: Expr -> Maybe Tableaux -> Maybe Tableaux
addElement x Nothing = Just (N x)
addElement x (Just w) = Just (S x w)
f = foldr addElement Nothing
In general, folding is idiomatic and should be used when you fit the recursion pattern. Otherwise use explicit recursion or try to reuse existing combinators. If there's a new pattern, make a combinator, but only if you'll use the pattern a lot - otherwise it's overkill. In this case, the pattern is fold for nonempty lists defined by: data List a = End a | Cons a (List a).
If I've understood the question properly, then here's my evaluation of your options:
It's probably a bit nasty to have to match the (presumably arbitrarily complex?) tableau out from underneath the constructor in order to write that function. This approach seems somewhat brittle, although it would probably work just fine.
I don't see the need to generalise the pattern out, given that it's a recursive function operating on a recursive structure. Introducing a higher-order pattern would (I think) obfuscate the actual logic behind performing a recursive traversal of this data structure.
I think this makes a good deal of sense. As you've observed, it's a reasonably recognised "pattern", but I think it matches the description of the algorithm well to write it down in exactly this way. It may not be as generalisable or reusable, but given that it's essentially the crux of the algorithmic approach, I think it makes sense to write the cases directly as you have done in a function like f. This would be my favoured approach.
Sorry to not provide a particularly concrete answer, but it is a reasonably subjective answer, so given the three options above, I would pick option 3 for reasons of clarity and readability.

When destructuring tuples in Haskell, where can the elements be used?

I am reading a tutorial that uses the following example (that I'll generalize somewhat):
f :: Foo -> (Int, Foo)
...
fList :: Foo -> [Int]
fList foo = x : fList bar
where
(x, bar) = f foo
My question lies in the fact that it seems you can refer to x and bar, by name, outside of the tuple where they are obtained. This would seem to act like destructuring parameter lists in other languages, if my guess is correct. (In other words, I didn't have to do the following:)
fList foo = (fst tuple) : fList (snd tuple)
where
tuple = f foo
Am I right about this behavior? I've never seen it mentioned yet in the tutorials/books I've been reading. Can someone point me to more info on the subject?
Edit: Can anything (lists, arrays, etc.) be destructured in a similar way, or can you only do this with tuples?
Seeing your edit, I think what your asking about is Pattern matching.
And to answer your question: Yes, anything you can construct, you can also 'deconstruct' using the constructors. For example, you're probably familiar with this form of pattern matching:
head :: [a] -> a
head (x:xs) = x
head [] = error "Can't take head of empty list"
However, there are more places where you can use pattern matching, other valid notations are:
head xs = case xs of
(y:ys) -> y
[] -> error "Can't take head of empty list"
head xs = let (y:ys) = xs
in y
head xs = y
where
(y:ys) = xs
Note that the last two examples are a bit different from the first to because they give different error messages when you call them with an empty list.
Although these examples are specific to lists, you can do the same with other data types, like so:
first :: (a, b) -> a
first tuple = x
where
(x, y) = tuple
second :: (a, b) -> b
second tuple = let (x, y) = tuple
in y
fromJust :: Maybe a -> a
fromJust ma = x
where
(Just x) = ma
Again, the last function will also crash if you call it with Nothing.
To sum up; if you can create something using constructors (like (:) and [] for lists, or (,) for tuples, or Nothing and Just for Maybe), you can use those same constructors to do pattern matching in a variety of ways.
Am I right about this behavior?
Yes. The names exist only in the block where you have defined them, though. In your case, this means the logical unit that your where clause is applied to, i.e. the expression inside fList.
Another way to look at it is that code like this
x where x = 3
is roughly equivalent to
let x = 3 in x
Yes, you're right. Names bound in a where clause are visible to the full declaration preceding the where clause. In your case those names are f and bar.
(One of the hard things about learning Haskell is that it is not just permitted but common to use variables in the source code in locations that precede the locations where those variables are defined.)
The place to read more about where clauses is in the Haskell 98 Report or in one of the many fine tutorials to be found at haskell.org.

Resources