在Haskell中查找列表的最大元素和索引 [英] Find max element and index of a list in Haskell

查看:378
本文介绍了在Haskell中查找列表的最大元素和索引的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在迈出第一步,进入Haskell的美好世界。作为一个练习,我想实现一个方法,它可以找到列表的最大元素及其索引。我们称这个函数为maxi。在列表中调用maxi应返回以下结果:

  ghci> maxi [1,3,4,1,2,3] 
(4,2)

4是此列表中最大的int,它位于索引2处。



我试图按如下方式实现此功能:

  maxim ::(Ord a)=> [a]  - > (a,Int)
maxim l =
let pmaxim ::(Ord a)=> [a] - > Int - > (a,Int) - 执行工作的内部函数
pmaxim [] _ =错误空列表 - 列表为空,错误
pmaxim [x] xi =(x,xi) - - 列表有一个项目,返回它和索引
pmaxim(x:xs)xi - 不止一个项目,分隔列表
| x> t =(x,xi) - 如果当前项目较大,则返回它并指数
|否则=(t,ti) - 如果列表尾部有更大的项目,则返回
其中(t,ti)= pmaxim xs(ti + 1) - 获取列表尾部的最大值
在pmaxim l 0 - 调用内部函数与开始索引

当我调用这个时,奇怪:ghci似乎在返回max元素的值后挂起。

  ghci> maxi [1,3,4,1,2,3] 
(4,

我会冒险猜测这与Haskell的懒惰评估本质有关,但我发现很难弄清楚这里发生了什么,以及如何解决它。我也会很感激任何提示可能有关于如何在Haskell中进行调试有没有一种简单的方法可以在执行时打印出值而不会影响行为?



我只想指出,我知道有几种更好的方法可以使用内置的Haskell函数来实现这种行为,我从头开始尝试学习Haskell。



谢谢

解决方案

这是因为你的代码中有一个小错误,你有:

 其中(t,ti)= pmaxim xs(ti + 1)

......但实际上它应该是:

$ p $ code>其中(t,ti)= pmaxim xs(xi + 1)

这会修复您的代码,现在可以产生正确的解决方案:

 >>> ;格言[1,2,3,2,1] 
(3,2)

你的代码被吊死了,因为你对 ti 的计算会导致无限循环,因为你意外地根据它自己定义了它。请注意, ghc 是一个足够聪明的编译器,并且指出 t 不依赖于<$ c $的值c> ti ,这就是为什么即使无法计算索引,您的版本仍可以成功计算最大值的原因。



调试纯计算是 Debug.Trace 模块。



作为一个方面说明,有一个更简单的解决方案:

  import Data.List 
import Data.Ord

maxi xs = maximumBy(比较fst)(zip xs [0 ..])

编辑:哎呀,我没有看到你故意从头开始实施它,但我仍然会离开那里。


I'm taking my first steps into the wonderful world of Haskell. As an exercise, I would like to implement a method which finds the maximum element of a list and its index. Let's call this function "maxi". Calling maxi on a list should return the following result:

ghci> maxi [1, 3, 4, 1, 2, 3]
(4, 2)

4 is the largest int in this list, and it is located at index 2.

I have attempted to implement this function as follows:

maxim :: (Ord a) => [a] -> (a, Int)
maxim l = 
  let pmaxim :: (Ord a) => [a] -> Int -> (a, Int) -- Internal function to do the work
      pmaxim [] _  = error "Empty list"           -- List is empty, error
      pmaxim [x] xi = (x, xi)                     -- List has one item, return it and the index
      pmaxim (x:xs) xi                            -- More than one item, break list apart
        | x > t     = (x, xi)                     -- If current item is bigger, return it and its index
        | otherwise = (t, ti)                     -- If list tail has a bigger item, return that
        where (t, ti) = pmaxim xs (ti + 1)        -- Get max of tail of the list
  in pmaxim l 0                                   -- Call internal function with start index

When I call this, I get something really weird: ghci seems to hang after returning the max element's value.

ghci> maxi [1, 3, 4, 1, 2, 3]
(4,

I will venture a guess that this has something to do with Haskell's lazy evaluation nature, but I'm finding it difficult to figure out what is actually going on here, and how to fix it. I would also be really grateful for any tips anyone might have about how to debug in Haskell. Is there an easy way to print out values during execution without effecting behavior?

I just wanted to point out that I am aware that there are several better ways to get this behavior using built-in Haskell functions. I am implementing this from scratch to try and learn Haskell.

Thank you

解决方案

It's because of a slight bug in your code. You have:

where (t, ti) = pmaxim xs (ti + 1)

... but it should actually be:

where (t, ti) = pmaxim xs (xi + 1)

This fixes your code, which now produces the correct solution:

>>> maxim [1, 2, 3, 2, 1]
(3, 2)

Your code hanged because your computation for ti results in an endless loop since you accidentally defined it in terms of itself. Note that ghc is a sufficiently smart compiler and figures out that t does not depend on the value of ti, which is why your version could still successfully compute the maximum value even if it cannot compute the index.

The standard way to debug pure computations is the Debug.Trace module.

As a side note, there is a much simpler solution:

import Data.List
import Data.Ord

maxi xs = maximumBy (comparing fst) (zip xs [0..])

Edit: Oops, I didn't see that you were deliberately implementing it from scratch, but I'll still leave that there.

这篇关于在Haskell中查找列表的最大元素和索引的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆