Haskell中的显式递归

时间:2012-04-11 17:29:37

标签: haskell recursion

任务:我正在尝试编写类型为签名minimum_recursive :: (a -> a -> Bool) -> [a] -> a的函数。对于它的第一个参数,它接受一个我将调用less的函数,它接受两个参数,如果第一个参数小于第二个参数,则返回True,否则返回False。 minimum_recursive也接受列表作为其第二个参数。使用显式递归,minimum_recursive应确定其输入列表中的最小值[a]。

我的想法:我在考虑将实际的递归放在一个也接受累加器的辅助函数中。我会用第一个项目作为累加器来调用辅助函数。

到目前为止我所拥有的内容:到目前为止,我有以下内容:

-- 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 []

我遇到了麻烦搞清楚如何开始写minimum_recursive_h

注意:我知道可能有更简单的方法来完成此任务,但我需要按照上面的说明进行操作。

3 个答案:

答案 0 :(得分:2)

你可以这样做:

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

或者,使用累加器:

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

答案 1 :(得分:1)

如果你想要列表中最小的元素,我认为你将目前最小的元素作为参数添加到函数中。

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

您还应该将函数中的类型从a更改为Maybe a,因为空列表中没有最小的元素。 Here some help about Maybe

如果你想在没有额外参数的情况下这样做,你可以将最小的元素存储在列表的开头。在这种情况下,使用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)

这就是如何找到最小的折叠。看看functionall编程的美妙之处。但这不适用于空列表

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

但是我们可以将这个函数嵌入到一个检查列表是否为空的函数中,并在这种情况下返回Nothing。

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

答案 2 :(得分:1)

递归地解决问题的经典方法如下:

  1. 假设你已经解决了这个问题,除了最后一步。
  2. 编写代码,给出除最后一步之外的所有解决方案,计算最后一步产生的解决方案。
  3. 写下基本案例。
  4. 对于列表,这会转换为此模式:

    1. 基本情况:[]的解决方案应该是什么? (如果有的话;在minimum_recursive函数的情况下,这将是一个错误。)
    2. 对于非空列表x:xs,假设您已经拥有almostTheResult = minimum_recursive f xs。你如何计算minimum_recursive (x:xs)
    3. 我会给你一个很大的提示:你的minimum_recursive可以用foldr和这个函数来实现:

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

      foldr函数正如我上面所描述的那样。 foldr的第一个参数是给定列表头和尾部的部分解决方案计算最终解的函数,第二个参数是结果基本情况。