繁体   English   中英

Haskell中的显式递归

[英]Explicit recursion in Haskell

任务:我正在尝试编写一个带有类型签名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

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

你可以这样做:

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

如果你想要列表中最小的元素,我会把你当前拥有的最小元素作为参数添加到函数中。

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因为空列表中没有最小元素。 这里有一些关于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)

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

  1. 假设你几乎解决了这个问题,除了最后一步。
  2. 编写代码,给出除最后一步之外的所有解决方案,计算最后一步产生的解决方案。
  3. 写下基本案例。

在列表的情况下,这转换为这种模式:

  1. 基本情况: []的解决方案应该是什么? (如果有的话;在你的minimum_recursive函数的情况下,这将是一个错误)。
  2. 对于非空列表x:xs ,假设您已经有almostTheResult = minimum_recursive f xs 你如何计算minimum_recursive (x:xs)呢?

我会给你一个很大的提示:你的minimum_recursive可以用foldr和这个函数来实现:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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