[英]Explicit recursion in Haskell
The task: I'm attempting to write a function with type signature minimum_recursive :: (a -> a -> Bool) -> [a] -> a
. 任务:我正在尝试编写一个带有类型签名
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. 对于它的第一个参数,它接受一个我将调用
less
的函数,它接受两个参数,如果第一个参数小于第二个参数,则返回True,否则返回False。 minimum_recursive
also accepts a list as its second parameter. minimum_recursive
还接受列表作为其第二个参数。 Using explicit recursion, minimum_recursive
should determine the smallest value in its input list [a]. 使用显式递归,
minimum_recursive
应确定其输入列表中的最小值[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
. 我无法弄清楚如何开始编写
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. 您还应该将调用此函数的函数中的类型从
a
更改为Maybe a
因为空列表中没有最小元素。 Here some help about Maybe 这里有一些关于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
在这种情况下,使用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.
看看functionall编程的美妙之处。 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. 但是我们可以将这个函数嵌入到一个检查列表是否为空的函数中,并在这种情况下返回Nothing。
betterfold :: [a] -> Maybe a
betterfold [] = Nothing
beterfold l = Just (simplefold l)
The classic way to solve problems recursively is the following: 递归解决问题的经典方法如下:
In the case of lists, this translates to this pattern: 在列表的情况下,这转换为这种模式:
[]
? []
的解决方案应该是什么? (if anything; in the case of your minimum_recursive
function, this would be an error). minimum_recursive
函数的情况下,这将是一个错误)。 x:xs
, assume you already have almostTheResult = minimum_recursive f xs
. x:xs
,假设您已经有almostTheResult = minimum_recursive f xs
。 How do you compute minimum_recursive (x:xs)
given that? minimum_recursive (x:xs)
呢? I'll give you a big hint: your minimum_recursive
can be implemented in terms of foldr
and this function: 我会给你一个很大的提示:你的
minimum_recursive
可以用foldr
和这个函数来实现:
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. foldr
函数正如我上面所描述的那样。 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. foldr
的第一个参数是在给定列表头和尾部的部分解决方案的情况下计算最终解的函数,第二个参数是结果基本情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.