2013-03-08 174 views
1

所以我想在Haskell中写一个名为Largest的函数,它找到列表中最大的元素,但是使用高阶函数来实现。Haskell函数 - 最大

我是新来的Haskell所以这是我尝试它不工作

largest :: [Int] -> Int 
largest [] = 0 
largest (head : tail) = if (head > tail) then head 
else (largest tail) 

我不知道是什么高阶函数的意思。

一些帮助将不胜感激。

回答

2

高阶函数将一个或多个函数作为其参数之一,或返回一个函数。在这种情况下,我假设高阶参数应该是一个比较函数。这给出了一个简单的定义为最大:

largest :: [a] -> (a -> a -> Ordering) -> a 
largest (x:xs) cmp = go x xs 
    where go largest []  = largest 
      go largest (x:xs) = case cmp largest x of 
      LT -> go x xs 
      _ -> go largest xs 

还,只是为了让你知道,有一个功能叫做maximum前奏为你做这个。 maximum [2,3,4,1] == 4

4

要解决您的尝试:

largest :: [Int] -> Int 
largest [] = 0 
largest (head : tail) = max head (largest tail) 

注意,这只会工作的非负数(您可以通过判定空列表没有最大解决这个问题 - 或通过使用类似前奏曲的maximumminBoundInt而不是0,但这不起作用,例如Integer)。

但是,这仍然不使用更高阶的函数。这种问题适合的功能是foldl(或更好的Data.List.foldl')或foldr,但我不想破坏乐趣。

1

要完成现有的答案,

你必须克服的第一个问题是尝试编译代码,或至少理解的错误消息。这个提示应该给你提供关于你面临的问题的很好的指导,以及如何修改它以获得一个正确的版本(即使你没有填写高级功能的要求,至少你会有一个工作的)。

对于这一点,让我们来看看模式条款的类型签名,(头:尾)

首先对(:)功能,我们有,

(:) :: a -> [a] -> [a] 

然后我们推导出以下类型,(这是争论的(:)),

  • 头是Int类型的。
  • 尾部类型为[Int]。

再次,让我们一起来看看类型签名(>)

(>) :: Ord a => a -> a -> Bool 

如果我们忽略了约束类,以保持它的简单,我们有,

(>) :: a -> a -> Bool 

还是在您的代码是

.... 
if (head > tail) ... 
.... 

哪个可以重写,再次简化为

.... 
if ((>) head tail)) ... 
.... 

使用以前所有的言论,你应该能够重建提供给(>)函数的类型和理解这个问题。

然后,您可以更正您的代码,并使使其工作
之后你可以看看high order function,然后使它正确

作为一般性评论,当你被困在一个复杂的问题上时,试着把它分解成更小的问题,并且对于每个子问题尝试应用以下烹饪原理。

让它工作,
作出正确的,
make如果快。

0
if (head > tail) 

首先,你不需要括号。其次,更严重的是,head是一个整数,但是tail整数列表。你无法比较这两件事。

largest (head : tail) = if (head > tail) then head 
else largest tail 

这不是正确的缩进。 else必须至少缩进至if。您可以把then和在同一行的else,或做类似

if head > tail 
    then head 
    else largest tail 

(同样,你实际上并不需要括号 - 虽然他们没有伤害任何东西。)

最后一点,有一个名为head的预定义函数,以及一个名为tail的函数,所以这些函数不是变量名称的最佳选择。惯用的Haskell选择是xxs(“x”的复数)。你会看到很多这样写的代码。它也有助于提醒你,x是一件事情,xs是一个事情的列表。

+0

http://ideone.com/3veT8I显示'else'在'if'的左边缩进,但它工作正常。 – 2013-03-16 14:09:43