简体   繁体   中英

Explicit recursion in Haskell

The task: I'm attempting to write a function with type signature minimum_recursive :: (a -> a -> Bool) -> [a] -> a . For its first parameter, it accepts a function I will call less that takes two parameters, and returns True if the first param is less than the second, False otherwise. minimum_recursive also accepts a list as its second parameter. Using explicit recursion, minimum_recursive should determine the smallest value in its input list [a].

My thinking: I was thinking to put the actual recursion in a helper function that also accepts an accumulator. I would call the helper function with the first item as the accumulator.

What I have so far: So far I have the following:

-- function as first parameter to min'
-- accepts two params, returns True if
-- first must come before second in sorted
-- order
less :: Ord a => a -> a -> Bool
less a b = a < b

-- Subpart B
minimum_recursive :: (a -> a -> Bool) -> [a] -> a
minimum_recursive func list = minimum_recursive_h func list []

I am having trouble figuring out how to even begin to write minimum_recursive_h .

Note: I know there probably is an easier way to accomplish this task, but I'm required to go about it as specified above.

You could do it like this:

minimum_recursive _ [] = error "no minimum of empty list"
minimum_recursive _ [x] = x
minimum_recursive f (x:xs) = let m = minimum_recursive f xs
                             in if f x m then x else m

Or, with an accumulator:

minimum_recursive _ [] = error "no minimum of empty list"
minimum_recursive f (x:xs) = helper f x xs
    where
      helper _ m [] = m
      helper f m (x:xs) 
          | f m x = helper f m xs
          | otherwise = helper f x xs

If you want the smallest ellement in the list I sugest that you add the smallest ellement you currently have as a parameter to the function.

minimum_recursive :: (a -> a -> Bool) -> a -> [a] -> a
minimum_recursive f min [] = min
minimum_recursive f min (x:xs) | f min x   = minimum_recursive f min xs
                               | otherwise = minimum_recursive f x   xs

You should also change the type in the function that call this from a to Maybe a since there are no smallest ellement in an empty list. Here some help about Maybe

If you want to do it without an extra parameter you could store the smallest ellement in the beginning of the list ass well. In this case it's important to use Maybe

minimum_recursive :: (a -> a -> Bool) -> [a] ->Maybe a
minimum_recursive f [] = Nothing
minimum_recursive f (x:[]) = Just x
minimum_recursive f (y:(x:xs)) | f y x     = minimum_recursive f (y:xs)
                               | otherwise = minimum_recursive f (x:xs)

This is how the minumum can be found ehit fold. Look at the beauty of functionall programming. But this wont work for the empty list

simplefold :: [a] -> a
simplefold (x:xs) = foldl min x xs  

But we can embed this function in one that checks if the list is empty and return Nothing in that case.

betterfold :: [a] -> Maybe a
betterfold [] = Nothing
beterfold l   = Just (simplefold l)

The classic way to solve problems recursively is the following:

  1. Assume you've nearly solved the problem, except for the final step.
  2. Write the code that, given the solution for all except that final step, computes the solution produced by that final step.
  3. Write the base case.

In the case of lists, this translates to this pattern:

  1. Base case: what should the solution be for [] ? (if anything; in the case of your minimum_recursive function, this would be an error).
  2. For a nonempty list x:xs , assume you already have almostTheResult = minimum_recursive f xs . How do you compute minimum_recursive (x:xs) given that?

I'll give you a big hint: your minimum_recursive can be implemented in terms of foldr and this function:

minBy :: (a -> a -> Bool) -> a -> a -> a
minBy pred x y = if pred x y then x else y

The foldr function does exactly what I'm describing above. The first argument to foldr is the function that computes the final solution given the list head and the partial solution for the tail, and the second argument is the result base case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM